3d546fe650726e4f072628ebb7062d09fb5b269e
[aai/rest-client.git] / src / main / java / org / openecomp / restclient / rest / RestClientBuilder.java
1 /**\r
2  * ============LICENSE_START=======================================================\r
3  * RestClient\r
4  * ================================================================================\r
5  * Copyright © 2017 AT&T Intellectual Property.\r
6  * Copyright © 2017 Amdocs\r
7  * All rights reserved.\r
8  * ================================================================================\r
9  * Licensed under the Apache License, Version 2.0 (the "License");\r
10  * you may not use this file except in compliance with the License.\r
11  * You may obtain a copy of the License at\r
12  *\r
13  *    http://www.apache.org/licenses/LICENSE-2.0\r
14  *\r
15  * Unless required by applicable law or agreed to in writing, software\r
16  * distributed under the License is distributed on an "AS IS" BASIS,\r
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
18  * See the License for the specific language governing permissions and\r
19  * limitations under the License.\r
20  * ============LICENSE_END=========================================================\r
21  *\r
22  * ECOMP and OpenECOMP are trademarks\r
23  * and service marks of AT&T Intellectual Property.\r
24  */\r
25 package org.openecomp.restclient.rest;\r
26 \r
27 import com.sun.jersey.api.client.Client;\r
28 import com.sun.jersey.api.client.config.ClientConfig;\r
29 import com.sun.jersey.api.client.config.DefaultClientConfig;\r
30 import com.sun.jersey.client.urlconnection.HTTPSProperties;\r
31 \r
32 import java.io.FileInputStream;\r
33 import java.security.KeyStore;\r
34 import java.security.cert.X509Certificate;\r
35 \r
36 import javax.net.ssl.HostnameVerifier;\r
37 import javax.net.ssl.KeyManagerFactory;\r
38 import javax.net.ssl.SSLContext;\r
39 import javax.net.ssl.SSLSession;\r
40 import javax.net.ssl.TrustManager;\r
41 import javax.net.ssl.X509TrustManager;\r
42 \r
43 /**\r
44  * This is a generic REST Client builder with flexible security validation. Sometimes it's nice to\r
45  * be able to disable server chain cert validation and hostname validation to work-around lab\r
46  * issues, but at the same time be able to provide complete validation with client cert + hostname +\r
47  * server cert chain validation.  \r
48  * I used the ModelLoader REST client as a base and merged in the TSUI client I wrote which also\r
49  * validates the server hostname and server certificate chain.\r
50  * \r
51  * @author DAVEA\r
52  *\r
53  */\r
54 public class RestClientBuilder {\r
55 \r
56   public static final boolean DEFAULT_VALIDATE_SERVER_HOST = false;\r
57   public static final boolean DEFAULT_VALIDATE_CERT_CHAIN = false;\r
58   public static final String DEFAULT_CLIENT_CERT_FILENAME = null;\r
59   public static final String DEFAULT_CERT_PASSWORD = null;\r
60   public static final String DEFAULT_TRUST_STORE_FILENAME = null;\r
61   public static final int DEFAULT_CONNECT_TIMEOUT_MS = 60000;\r
62   public static final int DEFAULT_READ_TIMEOUT_MS = 60000;\r
63 \r
64   private static final String SSL_PROTOCOL = "TLS";\r
65   private static final String KEYSTORE_ALGORITHM = "SunX509";\r
66   private static final String KEYSTORE_TYPE = "PKCS12";\r
67 \r
68   /*\r
69    * TODO: implement fluent interface?\r
70    */\r
71 \r
72   private boolean validateServerHostname;\r
73   private boolean validateServerCertChain;\r
74   private String clientCertFileName;\r
75   private String clientCertPassword;\r
76   private String truststoreFilename;\r
77   private int connectTimeoutInMs;\r
78   private int readTimeoutInMs;\r
79 \r
80   /**\r
81    * Rest Client Builder.\r
82    */\r
83   public RestClientBuilder() {\r
84     validateServerHostname = DEFAULT_VALIDATE_SERVER_HOST;\r
85     validateServerCertChain = DEFAULT_VALIDATE_CERT_CHAIN;\r
86     clientCertFileName = DEFAULT_CLIENT_CERT_FILENAME;\r
87     clientCertPassword = DEFAULT_CERT_PASSWORD;\r
88     truststoreFilename = DEFAULT_TRUST_STORE_FILENAME;\r
89     connectTimeoutInMs = DEFAULT_CONNECT_TIMEOUT_MS;\r
90     readTimeoutInMs = DEFAULT_READ_TIMEOUT_MS;\r
91   }\r
92 \r
93   public boolean isValidateServerHostname() {\r
94     return validateServerHostname;\r
95   }\r
96 \r
97   public void setValidateServerHostname(boolean validateServerHostname) {\r
98     this.validateServerHostname = validateServerHostname;\r
99   }\r
100 \r
101   public boolean isValidateServerCertChain() {\r
102     return validateServerCertChain;\r
103   }\r
104 \r
105   public void setValidateServerCertChain(boolean validateServerCertChain) {\r
106     this.validateServerCertChain = validateServerCertChain;\r
107   }\r
108 \r
109   public String getClientCertFileName() {\r
110     return clientCertFileName;\r
111   }\r
112 \r
113   public void setClientCertFileName(String clientCertFileName) {\r
114     this.clientCertFileName = clientCertFileName;\r
115   }\r
116 \r
117   public String getClientCertPassword() {\r
118     return clientCertPassword;\r
119   }\r
120 \r
121   public void setClientCertPassword(String clientCertPassword) {\r
122     this.clientCertPassword = clientCertPassword;\r
123   }\r
124 \r
125   public String getTruststoreFilename() {\r
126     return truststoreFilename;\r
127   }\r
128 \r
129   public void setTruststoreFilename(String truststoreFilename) {\r
130     this.truststoreFilename = truststoreFilename;\r
131   }\r
132 \r
133   public int getConnectTimeoutInMs() {\r
134     return connectTimeoutInMs;\r
135   }\r
136 \r
137   public void setConnectTimeoutInMs(int connectTimeoutInMs) {\r
138     this.connectTimeoutInMs = connectTimeoutInMs;\r
139   }\r
140 \r
141   public int getReadTimeoutInMs() {\r
142     return readTimeoutInMs;\r
143   }\r
144 \r
145   public void setReadTimeoutInMs(int readTimeoutInMs) {\r
146     this.readTimeoutInMs = readTimeoutInMs;\r
147   }\r
148 \r
149   /**\r
150    * Returns Client.\r
151    */\r
152   public Client getClient() throws Exception {\r
153 \r
154     ClientConfig clientConfig = new DefaultClientConfig();\r
155 \r
156     // Check to see if we need to perform proper validation of\r
157     // the certificate chains.\r
158     TrustManager[] trustAllCerts = null;\r
159     if (validateServerCertChain) {\r
160       if (truststoreFilename != null) {\r
161         System.setProperty("javax.net.ssl.trustStore", truststoreFilename);\r
162       } else {\r
163         throw new IllegalArgumentException("Trust store filename must be set!");\r
164       }\r
165 \r
166     } else {\r
167 \r
168       // We aren't validating certificates, so create a trust manager that does\r
169       // not validate certificate chains.\r
170       trustAllCerts = new TrustManager[] {new X509TrustManager() {\r
171         public X509Certificate[] getAcceptedIssuers() {\r
172           return null;\r
173         }\r
174 \r
175         public void checkClientTrusted(X509Certificate[] certs, String authType) {}\r
176 \r
177         public void checkServerTrusted(X509Certificate[] certs, String authType) {}\r
178       }};\r
179     }\r
180 \r
181     // Set up the SSL context, keystore, etc. to use for our connection\r
182     // to the AAI.\r
183     SSLContext ctx = SSLContext.getInstance(SSL_PROTOCOL);\r
184     KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEYSTORE_ALGORITHM);\r
185     KeyStore ks = KeyStore.getInstance(KEYSTORE_TYPE);\r
186 \r
187     char[] pwd = null;\r
188     if (clientCertPassword != null) {\r
189       pwd = clientCertPassword.toCharArray();\r
190     }\r
191 \r
192     if (clientCertFileName != null) {\r
193       FileInputStream fin = new FileInputStream(clientCertFileName);\r
194 \r
195       // Load the keystore and initialize the key manager factory.\r
196       ks.load(fin, pwd);\r
197       kmf.init(ks, pwd);\r
198 \r
199       ctx.init(kmf.getKeyManagers(), trustAllCerts, null);\r
200     } else {\r
201       ctx.init(null, trustAllCerts, null);\r
202     }\r
203 \r
204 \r
205     // Are we performing validation of the server host name?\r
206     if (validateServerHostname) {\r
207       clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,\r
208           new HTTPSProperties(null, ctx));\r
209 \r
210     } else {\r
211       clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,\r
212           new HTTPSProperties(new HostnameVerifier() {\r
213             @Override\r
214             public boolean verify(String str, SSLSession sslSession) {\r
215               return true;\r
216             }\r
217           }, ctx));\r
218     }\r
219 \r
220     // Finally, create and initialize our client...\r
221     Client client = null;\r
222     client = Client.create(clientConfig);\r
223     client.setConnectTimeout(connectTimeoutInMs);\r
224     client.setReadTimeout(readTimeoutInMs);\r
225 \r
226     // ...and return it to the caller.\r
227     return client;\r
228   }\r
229 }\r