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