2 * ============LICENSE_START=======================================================
\r
4 * ================================================================================
\r
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
\r
6 * Copyright © 2017-2018 Amdocs
\r
7 * ================================================================================
\r
8 * Licensed under the Apache License, Version 2.0 (the "License");
\r
9 * you may not use this file except in compliance with the License.
\r
10 * You may obtain a copy of the License at
\r
12 * http://www.apache.org/licenses/LICENSE-2.0
\r
14 * Unless required by applicable law or agreed to in writing, software
\r
15 * distributed under the License is distributed on an "AS IS" BASIS,
\r
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
17 * See the License for the specific language governing permissions and
\r
18 * limitations under the License.
\r
19 * ============LICENSE_END=========================================================
\r
21 package org.onap.aai.restclient.rest;
\r
23 import java.io.FileInputStream;
\r
24 import java.security.KeyStore;
\r
25 import java.security.cert.X509Certificate;
\r
27 import javax.net.ssl.HostnameVerifier;
\r
28 import javax.net.ssl.KeyManagerFactory;
\r
29 import javax.net.ssl.SSLContext;
\r
30 import javax.net.ssl.SSLSession;
\r
31 import javax.net.ssl.TrustManager;
\r
32 import javax.net.ssl.X509TrustManager;
\r
34 import org.onap.aai.restclient.enums.RestAuthenticationMode;
\r
36 import com.sun.jersey.api.client.Client;
\r
37 import com.sun.jersey.api.client.config.ClientConfig;
\r
38 import com.sun.jersey.api.client.config.DefaultClientConfig;
\r
39 import com.sun.jersey.client.urlconnection.HTTPSProperties;
\r
42 * This is a generic REST Client builder with flexible security validation. Sometimes it's nice to
\r
43 * be able to disable server chain cert validation and hostname validation to work-around lab
\r
44 * issues, but at the same time be able to provide complete validation with client cert + hostname +
\r
45 * server cert chain validation. I used the ModelLoader REST client as a base and merged in the TSUI
\r
46 * client I wrote which also validates the server hostname and server certificate chain.
\r
48 public class RestClientBuilder {
\r
50 public static final boolean DEFAULT_VALIDATE_SERVER_HOST = false;
\r
51 public static final boolean DEFAULT_VALIDATE_CERT_CHAIN = false;
\r
52 public static final String DEFAULT_CLIENT_CERT_FILENAME = null;
\r
53 public static final String DEFAULT_CERT_PASSWORD = null;
\r
54 public static final String DEFAULT_TRUST_STORE_FILENAME = null;
\r
55 public static final int DEFAULT_CONNECT_TIMEOUT_MS = 60000;
\r
56 public static final int DEFAULT_READ_TIMEOUT_MS = 60000;
\r
57 public static final RestAuthenticationMode DEFAULT_AUTH_MODE = RestAuthenticationMode.SSL_CERT;
\r
58 public static final String DEFAULT_BASIC_AUTH_USERNAME = "";
\r
59 public static final String DEFAULT_BASIC_AUTH_PASSWORD = "";
\r
60 public static final String DEFAULT_SSL_PROTOCOL = "TLS";
\r
62 private static final String KEYSTORE_ALGORITHM = "SunX509";
\r
63 private static final String KEYSTORE_TYPE = "PKCS12";
\r
64 private static final String TRUST_STORE_PROPERTY = "javax.net.ssl.trustStore";
\r
66 private boolean validateServerHostname;
\r
67 private boolean validateServerCertChain;
\r
68 private String clientCertFileName;
\r
69 private String clientCertPassword;
\r
70 private String truststoreFilename;
\r
71 private int connectTimeoutInMs;
\r
72 private int readTimeoutInMs;
\r
73 private RestAuthenticationMode authenticationMode;
\r
74 private String basicAuthUsername;
\r
75 private String basicAuthPassword;
\r
76 private String sslProtocol;
\r
79 * Rest Client Builder.
\r
81 public RestClientBuilder() {
\r
82 validateServerHostname = DEFAULT_VALIDATE_SERVER_HOST;
\r
83 validateServerCertChain = DEFAULT_VALIDATE_CERT_CHAIN;
\r
84 clientCertFileName = DEFAULT_CLIENT_CERT_FILENAME;
\r
85 clientCertPassword = DEFAULT_CERT_PASSWORD;
\r
86 truststoreFilename = DEFAULT_TRUST_STORE_FILENAME;
\r
87 connectTimeoutInMs = DEFAULT_CONNECT_TIMEOUT_MS;
\r
88 readTimeoutInMs = DEFAULT_READ_TIMEOUT_MS;
\r
89 authenticationMode = DEFAULT_AUTH_MODE;
\r
90 basicAuthUsername = DEFAULT_BASIC_AUTH_USERNAME;
\r
91 basicAuthPassword = DEFAULT_BASIC_AUTH_PASSWORD;
\r
92 sslProtocol = DEFAULT_SSL_PROTOCOL;
\r
95 public boolean isValidateServerHostname() {
\r
96 return validateServerHostname;
\r
99 public void setValidateServerHostname(boolean validateServerHostname) {
\r
100 this.validateServerHostname = validateServerHostname;
\r
103 public boolean isValidateServerCertChain() {
\r
104 return validateServerCertChain;
\r
107 public void setValidateServerCertChain(boolean validateServerCertChain) {
\r
108 this.validateServerCertChain = validateServerCertChain;
\r
111 public String getClientCertFileName() {
\r
112 return clientCertFileName;
\r
115 public void setClientCertFileName(String clientCertFileName) {
\r
116 this.clientCertFileName = clientCertFileName;
\r
119 public String getClientCertPassword() {
\r
120 return clientCertPassword;
\r
123 public void setClientCertPassword(String clientCertPassword) {
\r
124 this.clientCertPassword = clientCertPassword;
\r
127 public String getTruststoreFilename() {
\r
128 return truststoreFilename;
\r
131 public void setTruststoreFilename(String truststoreFilename) {
\r
132 this.truststoreFilename = truststoreFilename;
\r
135 public int getConnectTimeoutInMs() {
\r
136 return connectTimeoutInMs;
\r
139 public void setConnectTimeoutInMs(int connectTimeoutInMs) {
\r
140 this.connectTimeoutInMs = connectTimeoutInMs;
\r
143 public int getReadTimeoutInMs() {
\r
144 return readTimeoutInMs;
\r
147 public void setReadTimeoutInMs(int readTimeoutInMs) {
\r
148 this.readTimeoutInMs = readTimeoutInMs;
\r
151 public RestAuthenticationMode getAuthenticationMode() {
\r
152 return authenticationMode;
\r
155 public void setAuthenticationMode(RestAuthenticationMode authenticationMode) {
\r
156 this.authenticationMode = authenticationMode;
\r
159 public String getBasicAuthUsername() {
\r
160 return basicAuthUsername;
\r
163 public void setBasicAuthUsername(String basicAuthUsername) {
\r
164 this.basicAuthUsername = basicAuthUsername;
\r
167 public String getBasicAuthPassword() {
\r
168 return basicAuthPassword;
\r
171 public void setBasicAuthPassword(String basicAuthPassword) {
\r
172 this.basicAuthPassword = basicAuthPassword;
\r
175 public String getSslProtocol() {
\r
176 return sslProtocol;
\r
179 public void setSslProtocol(String sslProtocol) {
\r
180 this.sslProtocol = sslProtocol;
\r
184 * Returns Client configured for SSL
\r
186 public Client getClient() throws Exception {
\r
188 switch (authenticationMode) {
\r
191 return getClient(true);
\r
194 // return basic non-authenticating HTTP client
\r
195 return getClient(false);
\r
200 protected void setupSecureSocketLayerClientConfig(ClientConfig clientConfig) throws Exception {
\r
201 // Check to see if we need to perform proper validation of
\r
202 // the certificate chains.
\r
203 TrustManager[] trustAllCerts = null;
\r
204 if (validateServerCertChain) {
\r
205 if (truststoreFilename != null) {
\r
206 System.setProperty(TRUST_STORE_PROPERTY, truststoreFilename);
\r
208 throw new IllegalArgumentException("Trust store filename must be set!");
\r
213 // We aren't validating certificates, so create a trust manager that does
\r
214 // not validate certificate chains.
\r
215 trustAllCerts = new TrustManager[] {new X509TrustManager() {
\r
216 public X509Certificate[] getAcceptedIssuers() {
\r
220 public void checkClientTrusted(X509Certificate[] certs, String authType) {}
\r
222 public void checkServerTrusted(X509Certificate[] certs, String authType) {}
\r
226 // Set up the SSL context, keystore, etc. to use for our connection
\r
228 SSLContext ctx = SSLContext.getInstance(sslProtocol);
\r
229 KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEYSTORE_ALGORITHM);
\r
230 KeyStore ks = KeyStore.getInstance(KEYSTORE_TYPE);
\r
233 if (clientCertPassword != null) {
\r
234 pwd = clientCertPassword.toCharArray();
\r
237 if (clientCertFileName != null) {
\r
238 FileInputStream fin = new FileInputStream(clientCertFileName);
\r
240 // Load the keystore and initialize the key manager factory.
\r
244 ctx.init(kmf.getKeyManagers(), trustAllCerts, null);
\r
246 ctx.init(null, trustAllCerts, null);
\r
249 // Are we performing validation of the server host name?
\r
250 if (validateServerHostname) {
\r
251 clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
\r
252 new HTTPSProperties(null, ctx));
\r
255 clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
\r
256 new HTTPSProperties(new HostnameVerifier() {
\r
258 public boolean verify(String str, SSLSession sslSession) {
\r
267 * Returns client instance
\r
269 * @param useSsl - used to configure the client with an ssl-context or just plain http
\r
271 protected Client getClient(boolean useSsl) throws Exception {
\r
273 ClientConfig clientConfig = new DefaultClientConfig();
\r
276 setupSecureSocketLayerClientConfig(clientConfig);
\r
279 // Finally, create and initialize our client...
\r
280 Client client = null;
\r
281 client = Client.create(clientConfig);
\r
282 client.setConnectTimeout(connectTimeoutInMs);
\r
283 client.setReadTimeout(readTimeoutInMs);
\r
285 // ...and return it to the caller.
\r
289 public String getBasicAuthenticationCredentials() {
\r
291 String usernameAndPassword = getBasicAuthUsername() + ":" + getBasicAuthPassword();
\r
292 return "Basic " + java.util.Base64.getEncoder().encodeToString(usernameAndPassword.getBytes());
\r
296 * Added a little bit of logic to obfuscate passwords that could be logged out
\r
298 * @see java.lang.Object#toString()
\r
301 public String toString() {
\r
302 return "RestClientBuilder [validateServerHostname=" + validateServerHostname
\r
303 + ", validateServerCertChain=" + validateServerCertChain + ", "
\r
304 + (clientCertFileName != null ? "clientCertFileName=" + clientCertFileName + ", " : "")
\r
305 + (clientCertPassword != null
\r
306 ? "clientCertPassword="
\r
307 + java.util.Base64.getEncoder().encodeToString(clientCertPassword.getBytes()) + ", "
\r
309 + (truststoreFilename != null ? "truststoreFilename=" + truststoreFilename + ", " : "")
\r
310 + "connectTimeoutInMs=" + connectTimeoutInMs + ", readTimeoutInMs=" + readTimeoutInMs + ", "
\r
311 + (authenticationMode != null ? "authenticationMode=" + authenticationMode + ", " : "")
\r
312 + (basicAuthUsername != null ? "basicAuthUsername=" + basicAuthUsername + ", " : "")
\r
313 + (basicAuthPassword != null ? "basicAuthPassword="
\r
314 + java.util.Base64.getEncoder().encodeToString(basicAuthPassword.getBytes()) : "")
\r