d44ba066bce30d4514912cd0e2db67ac0ff7a3df
[appc.git] / appc-inbound / appc-artifact-handler / provider / src / main / java / org / onap / appc / artifact / handler / dbservices / CtxParameterizedResolver.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * ============LICENSE_END=========================================================
20  */
21
22
23 package org.onap.appc.artifact.handler.dbservices;
24
25 import java.sql.Connection;
26 import java.sql.PreparedStatement;
27 import java.sql.ResultSet;
28 import java.sql.ResultSetMetaData;
29 import java.sql.SQLException;
30 import java.util.ArrayList;
31
32 import javax.sql.rowset.CachedRowSet;
33
34 import org.apache.commons.lang3.StringUtils;
35 import org.onap.ccsdk.sli.core.dblib.DbLibService;
36 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
37
38 import com.att.eelf.configuration.EELFLogger;
39 import com.att.eelf.configuration.EELFManager;
40
41 public class CtxParameterizedResolver {
42
43     private static String CRYPT_KEY = "QtfJMKggVk";
44     private static final EELFLogger log = EELFManager.getInstance().getLogger(CtxParameterizedResolver.class);
45     
46     protected static String resolveCtxVars(String key, SvcLogicContext ctx, ArrayList<String> arguments) {
47         if (key == null) {
48             return (null);
49         }
50
51         if (key.startsWith("'") && key.endsWith("'")) {
52             key = key.substring(1, key.length() - 1);
53             log.debug("Stripped outer single quotes - key is now [" + key + "]");
54         }
55
56         String[] keyTerms = key.split("\\s+");
57
58         StringBuffer sqlBuffer = new StringBuffer();
59
60         for (int i = 0; i < keyTerms.length; i++) {
61             sqlBuffer.append(resolveTerm(keyTerms[i], ctx, arguments));
62             sqlBuffer.append(" ");
63         }
64
65         return (sqlBuffer.toString());
66     }
67
68     private static String resolveTerm(String term, SvcLogicContext ctx, ArrayList<String> arguments) {
69         if (term == null) {
70             return (null);
71         }
72
73         log.trace("resolveTerm: term is " + term);
74
75         if (term.startsWith("$") && (ctx != null)) {
76             // Resolve any index variables.
77             term = resolveCtxVariable(term.substring(1), ctx);
78             // Escape single quote
79             if (term != null) {
80                 term = term.replaceAll("'", "''");
81             }
82             arguments.add(term);
83             return "?";
84         } else {
85             return (term);
86         }
87
88     }
89
90     private static String resolveCtxVariable(String ctxVarName, SvcLogicContext ctx) {
91
92         if (ctxVarName.indexOf('[') == -1) {
93             // Ctx variable contains no arrays
94             if ("CRYPT_KEY".equals(ctxVarName)) {
95                 // Handle crypt key as special case. If it's set as a context
96                 // variable, use it. Otherwise, use
97                 // configured crypt key.
98                 String cryptKey = ctx.getAttribute(ctxVarName);
99                 if ((cryptKey != null) && (cryptKey.length() > 0)) {
100                     return (cryptKey);
101                 } else {
102                     return (CRYPT_KEY);
103                 }
104             }
105             return (ctx.getAttribute(ctxVarName));
106         }
107
108         // Resolve any array references
109         StringBuffer sbuff = new StringBuffer();
110         String[] ctxVarParts = ctxVarName.split("\\[");
111         sbuff.append(ctxVarParts[0]);
112         for (int i = 1; i < ctxVarParts.length; i++) {
113             if (ctxVarParts[i].startsWith("$")) {
114                 int endBracketLoc = ctxVarParts[i].indexOf("]");
115                 if (endBracketLoc == -1) {
116                     // Missing end bracket ... give up parsing
117                     log.warn("Variable reference " + ctxVarName + " seems to be missing a ']'");
118                     return (ctx.getAttribute(ctxVarName));
119                 }
120
121                 String idxVarName = ctxVarParts[i].substring(1, endBracketLoc);
122                 String remainder = ctxVarParts[i].substring(endBracketLoc);
123
124                 sbuff.append("[");
125                 sbuff.append(ctx.getAttribute(idxVarName));
126                 sbuff.append(remainder);
127
128             } else {
129                 // Index is not a variable reference
130                 sbuff.append("[");
131                 sbuff.append(ctxVarParts[i]);
132             }
133         }
134
135         return (ctx.getAttribute(sbuff.toString()));
136     }
137         
138         protected static void saveCachedRowSetToCtx(CachedRowSet results, SvcLogicContext ctx, String prefix, DbLibService dblibSvc)
139                 throws SQLException {
140             if (ctx != null) {
141                 if ((prefix != null) && prefix.endsWith("[]")) {
142                     // Return an array.
143                     String pfx = prefix.substring(0, prefix.length() - 2);
144                     int idx = 0;
145                     do {
146                         ResultSetMetaData rsMeta = results.getMetaData();
147                         int numCols = rsMeta.getColumnCount();
148
149                         for (int i = 0; i < numCols; i++) {
150                             String colValue = null;
151                             String tableName = rsMeta.getTableName(i + 1);
152                             if (rsMeta.getColumnType(i + 1) == java.sql.Types.VARBINARY) {
153                                 colValue = decryptColumn(tableName, rsMeta.getColumnName(i + 1), results.getBytes(i + 1),
154                                         dblibSvc);
155                             } else {
156                                 colValue = results.getString(i + 1);
157                             }
158                             log.debug("Setting " + pfx + "[" + idx + "]."
159                                     + rsMeta.getColumnLabel(i + 1).replaceAll("_", "-") + " = " + colValue);
160                             ctx.setAttribute(pfx + "[" + idx + "]." + rsMeta.getColumnLabel(i + 1).replaceAll("_", "-"),
161                                     colValue);
162                         }
163                         idx++;
164                     } while (results.next());
165                     log.debug("Setting " + pfx + "_length = " + idx);
166                     ctx.setAttribute(pfx + "_length", "" + idx);
167                 } else {
168                     ResultSetMetaData rsMeta = results.getMetaData();
169                     int numCols = rsMeta.getColumnCount();
170
171                     for (int i = 0; i < numCols; i++) {
172                         String colValue = null;
173                         String tableName = rsMeta.getTableName(i + 1);
174                         if ("VARBINARY".equalsIgnoreCase(rsMeta.getColumnTypeName(i + 1))) {
175                             colValue = decryptColumn(tableName, rsMeta.getColumnName(i + 1), results.getBytes(i + 1),
176                                     dblibSvc);
177                         } else {
178                             colValue = results.getString(i + 1);
179                         }
180                         if (prefix != null) {
181                             log.debug("Setting " + prefix + "." + rsMeta.getColumnLabel(i + 1).replaceAll("_", "-") + " = "
182                                     + colValue);
183                             ctx.setAttribute(prefix + "." + rsMeta.getColumnLabel(i + 1).replaceAll("_", "-"), colValue);
184                         } else {
185                             log.debug("Setting " + rsMeta.getColumnLabel(i + 1).replaceAll("_", "-") + " = " + colValue);
186                             ctx.setAttribute(rsMeta.getColumnLabel(i + 1).replaceAll("_", "-"), colValue);
187                         }
188                     }
189                 }
190             }
191         }
192         
193         private static String decryptColumn(String tableName, String colName, byte[] colValue, DbLibService dblibSvc) {
194             String strValue = new String(colValue);
195
196             if (StringUtils.isAsciiPrintable(strValue)) {
197
198                 // If printable, not encrypted
199                 return (strValue);
200             } else {
201                 ResultSet results = null;
202                 try (Connection conn =  dblibSvc.getConnection();
203                    PreparedStatement stmt = conn.prepareStatement("SELECT CAST(AES_DECRYPT(?, ?) AS CHAR(50)) FROM DUAL")) {
204
205                     stmt.setBytes(1, colValue);
206                     stmt.setString(2, CRYPT_KEY);
207                     results = stmt.executeQuery();
208
209                     if ((results != null) && results.next()) {
210                         strValue = results.getString(1);
211                         log.debug("Decrypted value is " + strValue);
212                     } else {
213                         log.warn("Cannot decrypt " + tableName + "." + colName);
214                     }
215                 } catch (Exception e) {
216                     log.error("Caught exception trying to decrypt " + tableName + "." + colName, e);
217                 }finally {
218                     if (results != null) {
219                         try {
220                             results.close();
221                         } catch (SQLException se) {
222                             log.error("Caught exception trying to close ResultSet",se);
223                         }
224                     }
225                 }
226             }
227             return (strValue);
228         }
229 }