Renaming openecomp to onap
[aai/rest-client.git] / src / main / java / org / onap / aai / restclient / rest / RestClientBuilder.java
diff --git a/src/main/java/org/onap/aai/restclient/rest/RestClientBuilder.java b/src/main/java/org/onap/aai/restclient/rest/RestClientBuilder.java
new file mode 100644 (file)
index 0000000..f446f27
--- /dev/null
@@ -0,0 +1,312 @@
+/**\r
+ * ============LICENSE_START=======================================================\r
+ * org.onap.aai\r
+ * ================================================================================\r
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
+ * Copyright © 2017 Amdocs\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 is a trademark and service mark of AT&T Intellectual Property.\r
+ */\r
+package org.onap.aai.restclient.rest;\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
+import org.onap.aai.restclient.enums.RestAuthenticationMode;\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
+/**\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. I used the ModelLoader REST client as a base and merged in the TSUI\r
+ * client I wrote which also validates the server hostname and server certificate chain.\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
+  public static final RestAuthenticationMode DEFAULT_AUTH_MODE = RestAuthenticationMode.SSL_CERT;\r
+  public static final String DEFAULT_BASIC_AUTH_USERNAME = "";\r
+  public static final String DEFAULT_BASIC_AUTH_PASSWORD = "";\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
+  private static final String TRUST_STORE_PROPERTY = "javax.net.ssl.trustStore";\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
+  private RestAuthenticationMode authenticationMode;\r
+  private String basicAuthUsername;\r
+  private String basicAuthPassword;\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
+    authenticationMode = DEFAULT_AUTH_MODE;\r
+    basicAuthUsername = DEFAULT_BASIC_AUTH_USERNAME;\r
+    basicAuthPassword = DEFAULT_BASIC_AUTH_PASSWORD;\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
+\r
+  public RestAuthenticationMode getAuthenticationMode() {\r
+    return authenticationMode;\r
+  }\r
+\r
+  public void setAuthenticationMode(RestAuthenticationMode authenticationMode) {\r
+    this.authenticationMode = authenticationMode;\r
+  }\r
+\r
+  public String getBasicAuthUsername() {\r
+    return basicAuthUsername;\r
+  }\r
+\r
+  public void setBasicAuthUsername(String basicAuthUsername) {\r
+    this.basicAuthUsername = basicAuthUsername;\r
+  }\r
+\r
+  public String getBasicAuthPassword() {\r
+    return basicAuthPassword;\r
+  }\r
+\r
+  public void setBasicAuthPassword(String basicAuthPassword) {\r
+    this.basicAuthPassword = basicAuthPassword;\r
+  }\r
+\r
+  /**\r
+   * Returns Client configured for SSL\r
+   */\r
+  public Client getClient() throws Exception {\r
+\r
+    switch (authenticationMode) {\r
+      case SSL_BASIC:\r
+      case SSL_CERT:\r
+        return getClient(true);\r
+\r
+      default:\r
+        // return basic non-authenticating HTTP client\r
+        return getClient(false);\r
+    }\r
+\r
+  }\r
+\r
+  protected void setupSecureSocketLayerClientConfig(ClientConfig clientConfig) throws Exception {\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(TRUST_STORE_PROPERTY, 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
+    // 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
+\r
+\r
+  /**\r
+   * Returns client instance\r
+   * \r
+   * @param useSsl - used to configure the client with an ssl-context or just plain http\r
+   */\r
+  protected Client getClient(boolean useSsl) throws Exception {\r
+\r
+    ClientConfig clientConfig = new DefaultClientConfig();\r
+\r
+    if (useSsl) {\r
+      setupSecureSocketLayerClientConfig(clientConfig);\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
+  public String getBasicAuthenticationCredentials() {\r
+\r
+    String usernameAndPassword = getBasicAuthUsername() + ":" + getBasicAuthPassword();\r
+    return "Basic " + java.util.Base64.getEncoder().encodeToString(usernameAndPassword.getBytes());\r
+  }\r
+\r
+  /* \r
+   * Added a little bit of logic to obfuscate passwords that could be logged out\r
+   * (non-Javadoc)\r
+   * @see java.lang.Object#toString()\r
+   */\r
+  @Override\r
+  public String toString() {\r
+    return "RestClientBuilder [validateServerHostname=" + validateServerHostname\r
+        + ", validateServerCertChain=" + validateServerCertChain + ", "\r
+        + (clientCertFileName != null ? "clientCertFileName=" + clientCertFileName + ", " : "")\r
+        + (clientCertPassword != null\r
+            ? "clientCertPassword="\r
+                + java.util.Base64.getEncoder().encodeToString(clientCertPassword.getBytes()) + ", "\r
+            : "")\r
+        + (truststoreFilename != null ? "truststoreFilename=" + truststoreFilename + ", " : "")\r
+        + "connectTimeoutInMs=" + connectTimeoutInMs + ", readTimeoutInMs=" + readTimeoutInMs + ", "\r
+        + (authenticationMode != null ? "authenticationMode=" + authenticationMode + ", " : "")\r
+        + (basicAuthUsername != null ? "basicAuthUsername=" + basicAuthUsername + ", " : "")\r
+        + (basicAuthPassword != null ? "basicAuthPassword="\r
+            + java.util.Base64.getEncoder().encodeToString(basicAuthPassword.getBytes()) : "")\r
+        + "]";\r
+  }\r
+\r
+}\r