Remove major and minor code smells in dr-node
[dmaap/datarouter.git] / datarouter-node / src / main / java / org / onap / dmaap / datarouter / node / NodeUtils.java
1 /*******************************************************************************
2  * ============LICENSE_START==================================================
3  * * org.onap.dmaap
4  * * ===========================================================================
5  * * Copyright © 2017 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  * * ============LICENSE_END====================================================
19  * *
20  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
21  * *
22  ******************************************************************************/
23
24
25 package org.onap.dmaap.datarouter.node;
26
27 import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
28 import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
29 import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS;
30 import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
31
32 import com.att.eelf.configuration.EELFLogger;
33 import com.att.eelf.configuration.EELFManager;
34 import java.io.File;
35 import java.io.FileInputStream;
36 import java.io.IOException;
37 import java.net.InetAddress;
38 import java.security.KeyStore;
39 import java.security.KeyStoreException;
40 import java.security.MessageDigest;
41 import java.security.NoSuchAlgorithmException;
42 import java.security.cert.CertificateException;
43 import java.security.cert.X509Certificate;
44 import java.text.SimpleDateFormat;
45 import java.util.Date;
46 import java.util.Enumeration;
47 import java.util.TimeZone;
48 import java.util.UUID;
49 import java.util.zip.GZIPInputStream;
50 import javax.servlet.http.HttpServletRequest;
51 import javax.servlet.http.HttpServletResponse;
52 import org.apache.commons.codec.binary.Base64;
53 import org.apache.commons.lang3.StringUtils;
54 import org.onap.dmaap.datarouter.node.eelf.EelfMsgs;
55 import org.slf4j.MDC;
56
57 /**
58  * Utility functions for the data router node
59  */
60 public class NodeUtils {
61
62     private static EELFLogger eelfLogger = EELFManager.getInstance()
63             .getLogger(NodeUtils.class);
64
65     private NodeUtils() {
66     }
67
68     /**
69      * Base64 encode a byte array
70      *
71      * @param raw The bytes to be encoded
72      * @return The encoded string
73      */
74     public static String base64Encode(byte[] raw) {
75         return (Base64.encodeBase64String(raw));
76     }
77
78     /**
79      * Given a user and password, generate the credentials
80      *
81      * @param user User name
82      * @param password User password
83      * @return Authorization header value
84      */
85     public static String getAuthHdr(String user, String password) {
86         if (user == null || password == null) {
87             return (null);
88         }
89         return ("Basic " + base64Encode((user + ":" + password).getBytes()));
90     }
91
92     /**
93      * Given a node name, generate the credentials
94      *
95      * @param node Node name
96      */
97     public static String getNodeAuthHdr(String node, String key) {
98         try {
99             MessageDigest md = MessageDigest.getInstance("SHA");
100             md.update(key.getBytes());
101             md.update(node.getBytes());
102             md.update(key.getBytes());
103             return (getAuthHdr(node, base64Encode(md.digest())));
104         } catch (Exception exception) {
105             eelfLogger
106                     .error("Exception in generating Credentials for given node name:= " + exception.toString(),
107                             exception);
108             return (null);
109         }
110     }
111
112     /**
113      * Given a keystore file and its password, return the value of the CN of the first private key entry with a
114      * certificate.
115      *
116      * @param kstype The type of keystore
117      * @param ksfile The file name of the keystore
118      * @param kspass The password of the keystore
119      * @return CN of the certificate subject or null
120      */
121     public static String getCanonicalName(String kstype, String ksfile, String kspass) {
122         KeyStore ks;
123         try {
124             ks = KeyStore.getInstance(kstype);
125             if (loadKeyStore(ksfile, kspass, ks)) {
126                 return (null);
127             }
128         } catch (Exception e) {
129             setIpAndFqdnForEelf("getCanonicalName");
130             eelfLogger.error(EelfMsgs.MESSAGE_KEYSTORE_LOAD_ERROR, e, ksfile);
131             return (null);
132         }
133         return (getCanonicalName(ks));
134     }
135
136     /**
137      * Given a keystore, return the value of the CN of the first private key entry with a certificate.
138      *
139      * @param ks The KeyStore
140      * @return CN of the certificate subject or null
141      */
142     public static String getCanonicalName(KeyStore ks) {
143         try {
144             Enumeration<String> aliases = ks.aliases();
145             while (aliases.hasMoreElements()) {
146                 String name = getNameFromSubject(ks, aliases);
147                 if (name != null) {
148                     return name;
149                 }
150             }
151         } catch (Exception e) {
152             eelfLogger.error("NODE0402 Error extracting my name from my keystore file " + e.toString(), e);
153         }
154         return (null);
155     }
156
157     /**
158      * Given a string representation of an IP address, get the corresponding byte array
159      *
160      * @param ip The IP address as a string
161      * @return The IP address as a byte array or null if the address is invalid
162      */
163     public static byte[] getInetAddress(String ip) {
164         try {
165             return (InetAddress.getByName(ip).getAddress());
166         } catch (Exception exception) {
167             eelfLogger
168                     .error("Exception in generating byte array for given IP address := " + exception.toString(),
169                             exception);
170         }
171         return (null);
172     }
173
174     /**
175      * Given a uri with parameters, split out the feed ID and file ID
176      */
177     public static String[] getFeedAndFileID(String uriandparams) {
178         int end = uriandparams.length();
179         int i = uriandparams.indexOf('#');
180         if (i != -1 && i < end) {
181             end = i;
182         }
183         i = uriandparams.indexOf('?');
184         if (i != -1 && i < end) {
185             end = i;
186         }
187         end = uriandparams.lastIndexOf('/', end);
188         if (end < 2) {
189             return (null);
190         }
191         i = uriandparams.lastIndexOf('/', end - 1);
192         if (i == -1) {
193             return (null);
194         }
195         return (new String[]{uriandparams.substring(i + 1, end), uriandparams.substring(end + 1)});
196     }
197
198     /**
199      * Escape fields that might contain vertical bar, backslash, or newline by replacing them with backslash p,
200      * backslash e and backslash n.
201      */
202     public static String loge(String s) {
203         if (s == null) {
204             return (s);
205         }
206         return (s.replaceAll("\\\\", "\\\\e").replaceAll("\\|", "\\\\p").replaceAll("\n", "\\\\n"));
207     }
208
209     /**
210      * Undo what loge does.
211      */
212     public static String unloge(String s) {
213         if (s == null) {
214             return (s);
215         }
216         return (s.replaceAll("\\\\p", "\\|").replaceAll("\\\\n", "\n").replaceAll("\\\\e", "\\\\"));
217     }
218
219     /**
220      * Format a logging timestamp as yyyy-mm-ddThh:mm:ss.mmmZ
221      */
222     public static String logts(long when) {
223         return (logts(new Date(when)));
224     }
225
226     /**
227      * Format a logging timestamp as yyyy-mm-ddThh:mm:ss.mmmZ
228      */
229     public static synchronized String logts(Date when) {
230         SimpleDateFormat logDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
231         logDate.setTimeZone(TimeZone.getTimeZone("GMT"));
232         return (logDate.format(when));
233     }
234
235     /* Method prints method name, server FQDN and IP Address of the machine in EELF logs
236      * @Method - setIpAndFqdnForEelf - Rally:US664892
237      * @Params - method, prints method name in EELF log.
238      */
239     public static void setIpAndFqdnForEelf(String method) {
240         MDC.clear();
241         MDC.put(MDC_SERVICE_NAME, method);
242         try {
243             MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName());
244             MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
245         } catch (Exception exception) {
246             eelfLogger
247                     .error("Exception in generating byte array for given IP address := " + exception.toString(),
248                             exception);
249         }
250
251     }
252
253     /* Method sets RequestIs and InvocationId for se in EELF logs
254      * @Method - setIpAndFqdnForEelf
255      * @Params - Req, Request used to get RequestId and InvocationId
256      */
257     public static void setRequestIdAndInvocationId(HttpServletRequest req) {
258         String reqId = req.getHeader("X-ONAP-RequestID");
259         if (StringUtils.isBlank(reqId)) {
260             reqId = UUID.randomUUID().toString();
261         }
262         MDC.put(MDC_KEY_REQUEST_ID, reqId);
263         String invId = req.getHeader("X-InvocationID");
264         if (StringUtils.isBlank(invId)) {
265             invId = UUID.randomUUID().toString();
266         }
267         MDC.put("InvocationId", invId);
268     }
269
270     public static void sendResponseError(HttpServletResponse response, int errorCode, EELFLogger intlogger) {
271         try {
272             response.sendError(errorCode);
273         } catch (IOException ioe) {
274             intlogger.error("IOException", ioe);
275         }
276     }
277
278     /**
279      * Method to check to see if file is of type gzip
280      *
281      * @param file The name of the file to be checked
282      * @return True if the file is of type gzip
283      */
284     public static boolean isFiletypeGzip(File file) {
285         try (FileInputStream fileInputStream = new FileInputStream(file);
286                 GZIPInputStream gzip = new GZIPInputStream(fileInputStream)) {
287
288             return true;
289         } catch (IOException e) {
290             eelfLogger.error("NODE0403 " + file.toString() + " Not in gzip(gz) format: " + e.toString() + e);
291             return false;
292         }
293     }
294
295
296     private static boolean loadKeyStore(String ksfile, String kspass, KeyStore ks)
297             throws NoSuchAlgorithmException, CertificateException {
298         try (FileInputStream fileInputStream = new FileInputStream(ksfile)) {
299             ks.load(fileInputStream, kspass.toCharArray());
300         } catch (IOException ioException) {
301             eelfLogger.error("IOException occurred while opening FileInputStream: " + ioException.getMessage(),
302                     ioException);
303             return true;
304         }
305         return false;
306     }
307
308
309     private static String getNameFromSubject(KeyStore ks, Enumeration<String> aliases) throws KeyStoreException {
310         String s = aliases.nextElement();
311         if (ks.entryInstanceOf(s, KeyStore.PrivateKeyEntry.class)) {
312             X509Certificate c = (X509Certificate) ks.getCertificate(s);
313             if (c != null) {
314                 String subject = c.getSubjectX500Principal().getName();
315                 String[] parts = subject.split(",");
316                 if (parts.length < 1) {
317                     return null;
318                 }
319                 subject = parts[5].trim();
320                 if (!subject.startsWith("CN=")) {
321                     return null;
322                 }
323                 return subject.substring(3);
324             }
325         }
326         return null;
327     }
328 }