--- /dev/null
+/**\r
+ * ============LICENSE_START=======================================================\r
+ * RestClient\r
+ * ================================================================================\r
+ * Copyright © 2017 AT&T Intellectual Property.\r
+ * Copyright © 2017 Amdocs\r
+ * All rights reserved.\r
+ * ================================================================================\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * ============LICENSE_END=========================================================\r
+ *\r
+ * ECOMP and OpenECOMP are trademarks\r
+ * and service marks of AT&T Intellectual Property.\r
+ */\r
+package org.openecomp.restclient.rest;\r
+\r
+import com.sun.jersey.api.client.Client;\r
+import com.sun.jersey.api.client.config.ClientConfig;\r
+import com.sun.jersey.api.client.config.DefaultClientConfig;\r
+import com.sun.jersey.client.urlconnection.HTTPSProperties;\r
+\r
+import java.io.FileInputStream;\r
+import java.security.KeyStore;\r
+import java.security.cert.X509Certificate;\r
+\r
+import javax.net.ssl.HostnameVerifier;\r
+import javax.net.ssl.KeyManagerFactory;\r
+import javax.net.ssl.SSLContext;\r
+import javax.net.ssl.SSLSession;\r
+import javax.net.ssl.TrustManager;\r
+import javax.net.ssl.X509TrustManager;\r
+\r
+/**\r
+ * This is a generic REST Client builder with flexible security validation. Sometimes it's nice to\r
+ * be able to disable server chain cert validation and hostname validation to work-around lab\r
+ * issues, but at the same time be able to provide complete validation with client cert + hostname +\r
+ * server cert chain validation. \r
+ * I used the ModelLoader REST client as a base and merged in the TSUI client I wrote which also\r
+ * validates the server hostname and server certificate chain.\r
+ * \r
+ * @author DAVEA\r
+ *\r
+ */\r
+public class RestClientBuilder {\r
+\r
+ public static final boolean DEFAULT_VALIDATE_SERVER_HOST = false;\r
+ public static final boolean DEFAULT_VALIDATE_CERT_CHAIN = false;\r
+ public static final String DEFAULT_CLIENT_CERT_FILENAME = null;\r
+ public static final String DEFAULT_CERT_PASSWORD = null;\r
+ public static final String DEFAULT_TRUST_STORE_FILENAME = null;\r
+ public static final int DEFAULT_CONNECT_TIMEOUT_MS = 60000;\r
+ public static final int DEFAULT_READ_TIMEOUT_MS = 60000;\r
+\r
+ private static final String SSL_PROTOCOL = "TLS";\r
+ private static final String KEYSTORE_ALGORITHM = "SunX509";\r
+ private static final String KEYSTORE_TYPE = "PKCS12";\r
+\r
+ /*\r
+ * TODO: implement fluent interface?\r
+ */\r
+\r
+ private boolean validateServerHostname;\r
+ private boolean validateServerCertChain;\r
+ private String clientCertFileName;\r
+ private String clientCertPassword;\r
+ private String truststoreFilename;\r
+ private int connectTimeoutInMs;\r
+ private int readTimeoutInMs;\r
+\r
+ /**\r
+ * Rest Client Builder.\r
+ */\r
+ public RestClientBuilder() {\r
+ validateServerHostname = DEFAULT_VALIDATE_SERVER_HOST;\r
+ validateServerCertChain = DEFAULT_VALIDATE_CERT_CHAIN;\r
+ clientCertFileName = DEFAULT_CLIENT_CERT_FILENAME;\r
+ clientCertPassword = DEFAULT_CERT_PASSWORD;\r
+ truststoreFilename = DEFAULT_TRUST_STORE_FILENAME;\r
+ connectTimeoutInMs = DEFAULT_CONNECT_TIMEOUT_MS;\r
+ readTimeoutInMs = DEFAULT_READ_TIMEOUT_MS;\r
+ }\r
+\r
+ public boolean isValidateServerHostname() {\r
+ return validateServerHostname;\r
+ }\r
+\r
+ public void setValidateServerHostname(boolean validateServerHostname) {\r
+ this.validateServerHostname = validateServerHostname;\r
+ }\r
+\r
+ public boolean isValidateServerCertChain() {\r
+ return validateServerCertChain;\r
+ }\r
+\r
+ public void setValidateServerCertChain(boolean validateServerCertChain) {\r
+ this.validateServerCertChain = validateServerCertChain;\r
+ }\r
+\r
+ public String getClientCertFileName() {\r
+ return clientCertFileName;\r
+ }\r
+\r
+ public void setClientCertFileName(String clientCertFileName) {\r
+ this.clientCertFileName = clientCertFileName;\r
+ }\r
+\r
+ public String getClientCertPassword() {\r
+ return clientCertPassword;\r
+ }\r
+\r
+ public void setClientCertPassword(String clientCertPassword) {\r
+ this.clientCertPassword = clientCertPassword;\r
+ }\r
+\r
+ public String getTruststoreFilename() {\r
+ return truststoreFilename;\r
+ }\r
+\r
+ public void setTruststoreFilename(String truststoreFilename) {\r
+ this.truststoreFilename = truststoreFilename;\r
+ }\r
+\r
+ public int getConnectTimeoutInMs() {\r
+ return connectTimeoutInMs;\r
+ }\r
+\r
+ public void setConnectTimeoutInMs(int connectTimeoutInMs) {\r
+ this.connectTimeoutInMs = connectTimeoutInMs;\r
+ }\r
+\r
+ public int getReadTimeoutInMs() {\r
+ return readTimeoutInMs;\r
+ }\r
+\r
+ public void setReadTimeoutInMs(int readTimeoutInMs) {\r
+ this.readTimeoutInMs = readTimeoutInMs;\r
+ }\r
+\r
+ /**\r
+ * Returns Client.\r
+ */\r
+ public Client getClient() throws Exception {\r
+\r
+ ClientConfig clientConfig = new DefaultClientConfig();\r
+\r
+ // Check to see if we need to perform proper validation of\r
+ // the certificate chains.\r
+ TrustManager[] trustAllCerts = null;\r
+ if (validateServerCertChain) {\r
+ if (truststoreFilename != null) {\r
+ System.setProperty("javax.net.ssl.trustStore", truststoreFilename);\r
+ } else {\r
+ throw new IllegalArgumentException("Trust store filename must be set!");\r
+ }\r
+\r
+ } else {\r
+\r
+ // We aren't validating certificates, so create a trust manager that does\r
+ // not validate certificate chains.\r
+ trustAllCerts = new TrustManager[] {new X509TrustManager() {\r
+ public X509Certificate[] getAcceptedIssuers() {\r
+ return null;\r
+ }\r
+\r
+ public void checkClientTrusted(X509Certificate[] certs, String authType) {}\r
+\r
+ public void checkServerTrusted(X509Certificate[] certs, String authType) {}\r
+ }};\r
+ }\r
+\r
+ // Set up the SSL context, keystore, etc. to use for our connection\r
+ // to the AAI.\r
+ SSLContext ctx = SSLContext.getInstance(SSL_PROTOCOL);\r
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEYSTORE_ALGORITHM);\r
+ KeyStore ks = KeyStore.getInstance(KEYSTORE_TYPE);\r
+\r
+ char[] pwd = null;\r
+ if (clientCertPassword != null) {\r
+ pwd = clientCertPassword.toCharArray();\r
+ }\r
+\r
+ if (clientCertFileName != null) {\r
+ FileInputStream fin = new FileInputStream(clientCertFileName);\r
+\r
+ // Load the keystore and initialize the key manager factory.\r
+ ks.load(fin, pwd);\r
+ kmf.init(ks, pwd);\r
+\r
+ ctx.init(kmf.getKeyManagers(), trustAllCerts, null);\r
+ } else {\r
+ ctx.init(null, trustAllCerts, null);\r
+ }\r
+\r
+\r
+ // Are we performing validation of the server host name?\r
+ if (validateServerHostname) {\r
+ clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,\r
+ new HTTPSProperties(null, ctx));\r
+\r
+ } else {\r
+ clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,\r
+ new HTTPSProperties(new HostnameVerifier() {\r
+ @Override\r
+ public boolean verify(String str, SSLSession sslSession) {\r
+ return true;\r
+ }\r
+ }, ctx));\r
+ }\r
+\r
+ // Finally, create and initialize our client...\r
+ Client client = null;\r
+ client = Client.create(clientConfig);\r
+ client.setConnectTimeout(connectTimeoutInMs);\r
+ client.setReadTimeout(readTimeoutInMs);\r
+\r
+ // ...and return it to the caller.\r
+ return client;\r
+ }\r
+}\r