2 * ============LICENSE_START=======================================================
3 * ONAP : ccsdk features
4 * ================================================================================
5 * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
22 package org.onap.ccsdk.features.sdnr.wt.common.http;
24 import java.io.ByteArrayInputStream;
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;
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;
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;
63 public class BaseHTTPClient {
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
74 private final boolean trustAll;
75 private String baseUrl;
77 private int timeout = DEFAULT_HTTP_TIMEOUT_MS;
78 private SSLContext sc = null;
80 public BaseHTTPClient(String base) {
84 public BaseHTTPClient(String base, boolean trustAllCerts) {
85 this(base, trustAllCerts, null, null, SSLCERT_NONE);
88 public BaseHTTPClient(String base, boolean trustAllCerts, String certFilename, String passphrase, int sslCertType) {
89 if (!base.endsWith("/")) {
93 this.trustAll = trustAllCerts;
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());
102 public void setBaseUrl(String base) {
103 if (!base.endsWith("/")) {
110 protected BaseHTTPResponse sendRequest(String uri, String method, String body, Map<String, String> headers)
112 return this.sendRequest(uri, method, body != null ? body.getBytes(CHARSET) : null, headers);
115 protected @Nonnull BaseHTTPResponse sendRequest(String uri, String method, byte[] body, Map<String, String> headers)
120 String surl = this.baseUrl;
121 if (!surl.endsWith("/") && uri.length() > 0) {
124 if (uri.startsWith("/")) {
125 uri = uri.substring(1);
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")) {
135 ((HttpsURLConnection) http).setSSLSocketFactory(sc.getSocketFactory());
137 LOG.debug("trusting all certs");
138 HostnameVerifier allHostsValid = (hostname, session) -> true;
139 ((HttpsURLConnection) http).setHostnameVerifier(allHostsValid);
141 } else // Should never happen
143 LOG.warn("No SSL context available");
144 return new BaseHTTPResponse(-1, "");
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));
155 byte[] buffer = new byte[BUFSIZE];
156 int len = 0, lensum = 0;
158 // Send the message to destination
159 if (!method.equals("GET") && body != null && body.length > 0) {
160 try (OutputStream output = http.getOutputStream()) {
165 int responseCode = ((HttpURLConnection) http).getResponseCode();
166 String sresponse = "";
167 InputStream response = null;
169 if (responseCode >= 200 && responseCode < 300) {
170 response = http.getInputStream();
172 response = ((HttpURLConnection) http).getErrorStream();
173 if (response == null) {
174 response = http.getInputStream();
177 if (response != null) {
179 len = response.read(buffer, 0, BUFSIZE);
184 sresponse += new String(buffer, 0, len, CHARSET);
187 LOG.debug("response is null");
189 } catch (Exception e) {
190 LOG.debug("No response. ", e);
192 if (response != null) {
196 LOG.debug("ResponseCode: " + responseCode);
197 LOG.trace("Response (len:{}): {}", String.valueOf(lensum), sresponse);
198 return new BaseHTTPResponse(responseCode, sresponse);
201 public static SSLContext setupSsl(boolean trustall)
202 throws NoSuchAlgorithmException, KeyManagementException, CertificateException, FileNotFoundException,
203 IOException, UnrecoverableKeyException, KeyStoreException, InvalidKeySpecException {
205 return setupSsl(trustall, null, null, SSLCERT_NONE);
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
221 * Setup of SSLContext
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
237 public static SSLContext setupSsl(boolean trustall, String certFilename, String passPhrase, int certType)
238 throws NoSuchAlgorithmException, KeyManagementException, CertificateException, FileNotFoundException,
239 IOException, UnrecoverableKeyException, KeyStoreException, InvalidKeySpecException {
241 SSLContext sc = SSLContext.getInstance(SSLCONTEXT);
242 TrustManager[] trustCerts = null;
244 trustCerts = new TrustManager[] {new javax.net.ssl.X509TrustManager() {
246 public java.security.cert.X509Certificate[] getAcceptedIssuers() {
251 public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
254 public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
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");
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");
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-----");
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});
287 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
288 kmf.init(keyStore, "changeit".toCharArray());
289 kms = kmf.getKeyManagers();
290 LOG.debug("successful");
293 // Init the SSLContext with a TrustManager[] and SecureRandom()
294 sc.init(kms, trustCerts, new java.security.SecureRandom());
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]);
305 protected static RSAPrivateKey generatePrivateKeyFromDER(byte[] keyBytes)
306 throws InvalidKeySpecException, NoSuchAlgorithmException {
307 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
309 KeyFactory factory = KeyFactory.getInstance("RSA");
311 return (RSAPrivateKey) factory.generatePrivate(spec);
314 protected static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException {
315 CertificateFactory factory = CertificateFactory.getInstance("X.509");
317 return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes));
320 public static String getAuthorizationHeaderValue(String username, String password) {
321 return "Basic " + new String(Base64.getEncoder().encode((username + ":" + password).getBytes()));
324 public void setTimeout(int timeout) {
325 this.timeout = timeout;
328 public static int getSslCertPcks() {
332 public static int getSslCertNone() {
336 public static int getSslCertPEM() {