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