SDN-R common Elasticsearch 7.x support
[ccsdk/features.git] / sdnr / wt / common / src / main / java / org / onap / ccsdk / features / sdnr / wt / common / http / BaseHTTPClient.java
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP : ccsdk features
4  * ================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property.
6  * All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  *
21  */
22 package org.onap.ccsdk.features.sdnr.wt.common.http;
23
24 import java.io.ByteArrayInputStream;
25 import java.io.File;
26 import java.io.FileInputStream;
27 import java.io.FileNotFoundException;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.OutputStream;
31 import java.net.HttpURLConnection;
32 import java.net.URL;
33 import java.net.URLConnection;
34 import java.nio.charset.Charset;
35 import java.nio.charset.StandardCharsets;
36 import java.nio.file.Files;
37 import java.security.KeyFactory;
38 import java.security.KeyManagementException;
39 import java.security.KeyStore;
40 import java.security.KeyStoreException;
41 import java.security.NoSuchAlgorithmException;
42 import java.security.UnrecoverableKeyException;
43 import java.security.cert.Certificate;
44 import java.security.cert.CertificateException;
45 import java.security.cert.CertificateFactory;
46 import java.security.cert.X509Certificate;
47 import java.security.interfaces.RSAPrivateKey;
48 import java.security.spec.InvalidKeySpecException;
49 import java.security.spec.PKCS8EncodedKeySpec;
50 import java.util.Base64;
51 import java.util.Map;
52 import javax.annotation.Nonnull;
53 import javax.net.ssl.HostnameVerifier;
54 import javax.net.ssl.HttpsURLConnection;
55 import javax.net.ssl.KeyManager;
56 import javax.net.ssl.KeyManagerFactory;
57 import javax.net.ssl.SSLContext;
58 import javax.net.ssl.TrustManager;
59 import javax.xml.bind.DatatypeConverter;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63 public class BaseHTTPClient {
64
65     private static Logger LOG = LoggerFactory.getLogger(BaseHTTPClient.class);
66     private static final int SSLCERT_NONE = -1;
67     private static final int SSLCERT_PCKS = 0;
68     private static final int SSLCERT_PEM = 1;
69     private static final int BUFSIZE = 1024;
70     private static final Charset CHARSET = StandardCharsets.UTF_8;
71     private static final String SSLCONTEXT = "TLSv1.2";
72     private static final int DEFAULT_HTTP_TIMEOUT_MS = 30000; // in ms
73
74     private final boolean trustAll;
75     private String baseUrl;
76
77     private int timeout = DEFAULT_HTTP_TIMEOUT_MS;
78     private SSLContext sc = null;
79
80     public BaseHTTPClient(String base) {
81         this(base, false);
82     }
83
84     public BaseHTTPClient(String base, boolean trustAllCerts) {
85         this(base, trustAllCerts, null, null, SSLCERT_NONE);
86     }
87
88     public BaseHTTPClient(String base, boolean trustAllCerts, String certFilename, String passphrase, int sslCertType) {
89         if (!base.endsWith("/")) {
90             base += "/";
91         }
92         this.baseUrl = base;
93         this.trustAll = trustAllCerts;
94         try {
95             sc = setupSsl(trustAll, certFilename, passphrase, sslCertType);
96         } catch (KeyManagementException | NoSuchAlgorithmException | UnrecoverableKeyException | CertificateException
97                 | KeyStoreException | IOException | InvalidKeySpecException e) {
98             LOG.warn("problem ssl setup: " + e.getMessage());
99         }
100     }
101
102     public void setBaseUrl(String base) {
103         if (!base.endsWith("/")) {
104             base += "/";
105         }
106         this.baseUrl = base;
107     }
108
109     @Nonnull
110     protected BaseHTTPResponse sendRequest(String uri, String method, String body, Map<String, String> headers)
111             throws IOException {
112         return this.sendRequest(uri, method, body != null ? body.getBytes(CHARSET) : null, headers);
113     }
114
115     protected @Nonnull BaseHTTPResponse sendRequest(String uri, String method, byte[] body, Map<String, String> headers)
116             throws IOException {
117         if (uri == null) {
118             uri = "";
119         }
120         String surl = this.baseUrl;
121         if (!surl.endsWith("/") && uri.length() > 0) {
122             surl += "/";
123         }
124         if (uri.startsWith("/")) {
125             uri = uri.substring(1);
126         }
127         surl += uri;
128         LOG.debug("try to send request with url=" + this.baseUrl + uri + " as method=" + method);
129         LOG.trace("body:" + (body == null ? "null" : new String(body, CHARSET)));
130         URL url = new URL(surl);
131         URLConnection http = url.openConnection();
132         http.setConnectTimeout(this.timeout);
133         if (surl.toString().startsWith("https")) {
134             if (sc != null) {
135                 ((HttpsURLConnection) http).setSSLSocketFactory(sc.getSocketFactory());
136                 if (trustAll) {
137                     LOG.debug("trusting all certs");
138                     HostnameVerifier allHostsValid = (hostname, session) -> true;
139                     ((HttpsURLConnection) http).setHostnameVerifier(allHostsValid);
140                 }
141             } else // Should never happen
142             {
143                 LOG.warn("No SSL context available");
144                 return new BaseHTTPResponse(-1, "");
145             }
146         }
147         ((HttpURLConnection) http).setRequestMethod(method);
148         http.setDoOutput(true);
149         if (headers != null && headers.size() > 0) {
150             for (String key : headers.keySet()) {
151                 http.setRequestProperty(key, headers.get(key));
152                 LOG.trace("set http header " + key + ": " + headers.get(key));
153             }
154         }
155         byte[] buffer = new byte[BUFSIZE];
156         int len = 0, lensum = 0;
157         // send request
158         // Send the message to destination
159         if (!method.equals("GET") && body != null && body.length > 0) {
160             try (OutputStream output = http.getOutputStream()) {
161                 output.write(body);
162             }
163         }
164         // Receive answer
165         int responseCode = ((HttpURLConnection) http).getResponseCode();
166         String sresponse = "";
167         InputStream response = null;
168         try {
169             if (responseCode >= 200 && responseCode < 300) {
170                 response = http.getInputStream();
171             } else {
172                 response = ((HttpURLConnection) http).getErrorStream();
173                 if (response == null) {
174                     response = http.getInputStream();
175                 }
176             }
177             if (response != null) {
178                 while (true) {
179                     len = response.read(buffer, 0, BUFSIZE);
180                     if (len <= 0) {
181                         break;
182                     }
183                     lensum += len;
184                     sresponse += new String(buffer, 0, len, CHARSET);
185                 }
186             } else {
187                 LOG.debug("response is null");
188             }
189         } catch (Exception e) {
190             LOG.debug("No response. ", e);
191         } finally {
192             if (response != null) {
193                 response.close();
194             }
195         }
196         LOG.debug("ResponseCode: " + responseCode);
197         LOG.trace("Response (len:{}): {}", String.valueOf(lensum), sresponse);
198         return new BaseHTTPResponse(responseCode, sresponse);
199     }
200
201     public static SSLContext setupSsl(boolean trustall)
202             throws NoSuchAlgorithmException, KeyManagementException, CertificateException, FileNotFoundException,
203             IOException, UnrecoverableKeyException, KeyStoreException, InvalidKeySpecException {
204
205         return setupSsl(trustall, null, null, SSLCERT_NONE);
206     }
207
208     /**
209      * @param keyFilename filename for key file
210      * @param certFilename filename for cert file
211      * @throws NoSuchAlgorithmException
212      * @throws KeyManagementException
213      * @throws IOException
214      * @throws FileNotFoundException
215      * @throws CertificateException
216      * @throws KeyStoreException
217      * @throws UnrecoverableKeyException
218      * @throws InvalidKeySpecException
219      */
220     /**
221      * Setup of SSLContext
222      *
223      * @param trustall true to switch of certificate verification
224      * @param certFilename filename for certificate file
225      * @param passPhrase for certificate
226      * @param certType of certificate
227      * @return SSL Context according to parameters
228      * @throws NoSuchAlgorithmException according name
229      * @throws KeyManagementException according name
230      * @throws CertificateException according name
231      * @throws FileNotFoundException according name
232      * @throws IOException according name
233      * @throws UnrecoverableKeyException according name
234      * @throws KeyStoreException according name
235      * @throws InvalidKeySpecException according name
236      */
237     public static SSLContext setupSsl(boolean trustall, String certFilename, String passPhrase, int certType)
238             throws NoSuchAlgorithmException, KeyManagementException, CertificateException, FileNotFoundException,
239             IOException, UnrecoverableKeyException, KeyStoreException, InvalidKeySpecException {
240
241         SSLContext sc = SSLContext.getInstance(SSLCONTEXT);
242         TrustManager[] trustCerts = null;
243         if (trustall) {
244             trustCerts = new TrustManager[] {new javax.net.ssl.X509TrustManager() {
245                 @Override
246                 public java.security.cert.X509Certificate[] getAcceptedIssuers() {
247                     return null;
248                 }
249
250                 @Override
251                 public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
252
253                 @Override
254                 public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
255             }};
256
257         }
258         KeyManager[] kms = null;
259         if (certFilename != null && passPhrase != null && !certFilename.isEmpty() && !passPhrase.isEmpty()) {
260             if (certType == SSLCERT_PCKS) {
261                 LOG.debug("try to load pcks file " + certFilename + " with passphrase=" + passPhrase);
262                 KeyStore keyStore = KeyStore.getInstance("PKCS12");
263                 FileInputStream fileInputStream = new FileInputStream(certFilename);
264                 keyStore.load(fileInputStream, passPhrase.toCharArray());
265                 KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
266                 kmf.init(keyStore, passPhrase.toCharArray());
267                 kms = kmf.getKeyManagers();
268                 fileInputStream.close();
269                 LOG.debug("successful");
270
271             } else if (certType == SSLCERT_PEM) {
272                 LOG.debug("try to load pem files cert=" + certFilename + " key=" + passPhrase);
273                 File fCert = new File(certFilename);
274                 File fKey = new File(passPhrase);
275                 KeyStore keyStore = KeyStore.getInstance("JKS");
276                 keyStore.load(null);
277                 byte[] certBytes = parseDERFromPEM(Files.readAllBytes(fCert.toPath()), "-----BEGIN CERTIFICATE-----",
278                         "-----END CERTIFICATE-----");
279                 byte[] keyBytes = parseDERFromPEM(Files.readAllBytes(fKey.toPath()), "-----BEGIN PRIVATE KEY-----",
280                         "-----END PRIVATE KEY-----");
281
282                 X509Certificate cert = generateCertificateFromDER(certBytes);
283                 RSAPrivateKey key = generatePrivateKeyFromDER(keyBytes);
284                 keyStore.setCertificateEntry("cert-alias", cert);
285                 keyStore.setKeyEntry("key-alias", key, "changeit".toCharArray(), new Certificate[] {cert});
286
287                 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
288                 kmf.init(keyStore, "changeit".toCharArray());
289                 kms = kmf.getKeyManagers();
290                 LOG.debug("successful");
291             }
292         }
293         // Init the SSLContext with a TrustManager[] and SecureRandom()
294         sc.init(kms, trustCerts, new java.security.SecureRandom());
295         return sc;
296     }
297
298     protected static byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter) {
299         String data = new String(pem);
300         String[] tokens = data.split(beginDelimiter);
301         tokens = tokens[1].split(endDelimiter);
302         return DatatypeConverter.parseBase64Binary(tokens[0]);
303     }
304
305     protected static RSAPrivateKey generatePrivateKeyFromDER(byte[] keyBytes)
306             throws InvalidKeySpecException, NoSuchAlgorithmException {
307         PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
308
309         KeyFactory factory = KeyFactory.getInstance("RSA");
310
311         return (RSAPrivateKey) factory.generatePrivate(spec);
312     }
313
314     protected static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException {
315         CertificateFactory factory = CertificateFactory.getInstance("X.509");
316
317         return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes));
318     }
319
320     public static String getAuthorizationHeaderValue(String username, String password) {
321         return "Basic " + new String(Base64.getEncoder().encode((username + ":" + password).getBytes()));
322     }
323
324     public void setTimeout(int timeout) {
325         this.timeout = timeout;
326     }
327
328     public static int getSslCertPcks() {
329         return SSLCERT_PCKS;
330     }
331
332     public static int getSslCertNone() {
333         return SSLCERT_NONE;
334     }
335
336     public static int getSslCertPEM() {
337         return SSLCERT_PEM;
338     }
339
340 }