86e3ced0693a0ed2c4ed1925090df8e474c28743
[ccsdk/cds.git] /
1 /*
2  * Copyright © 2017-2019 AT&T, Bell Canada
3  * Modifications Copyright © 2019 Huawei.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 package org.onap.ccsdk.cds.blueprintsprocessor.rest.service
19
20 import org.apache.http.conn.ssl.NoopHostnameVerifier
21 import org.apache.http.conn.ssl.SSLConnectionSocketFactory
22 import org.apache.http.impl.client.CloseableHttpClient
23 import org.apache.http.impl.client.HttpClients
24 import org.apache.http.message.BasicHeader
25 import org.apache.http.ssl.SSLContextBuilder
26 import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLBasicAuthRestClientProperties
27 import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLRestClientProperties
28 import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLTokenAuthRestClientProperties
29 import org.onap.ccsdk.cds.blueprintsprocessor.rest.utils.WebClientUtils
30 import org.springframework.http.HttpHeaders
31 import org.springframework.http.MediaType
32 import java.io.File
33 import java.io.FileInputStream
34 import java.security.KeyStore
35 import java.security.cert.X509Certificate
36
37 class SSLRestClientService(private val restClientProperties: SSLRestClientProperties) :
38     BlueprintWebClientService {
39
40     var auth: BlueprintWebClientService? = null
41
42     init {
43         auth = getAuthService()
44     }
45
46     private fun getAuthService(): BlueprintWebClientService? {
47         // type,url and additional headers don't get carried over to TokenAuthRestClientProperties from SSLTokenAuthRestClientProperties
48         // set them in auth obj to be consistent. TODO: refactor
49         return when (restClientProperties) {
50             is SSLBasicAuthRestClientProperties -> {
51                 val basicAuthProps = restClientProperties.basicAuth!!
52                 basicAuthProps.additionalHeaders = restClientProperties.additionalHeaders
53                 basicAuthProps.url = restClientProperties.url
54                 basicAuthProps.type = restClientProperties.type
55                 BasicAuthRestClientService(basicAuthProps)
56             }
57             is SSLTokenAuthRestClientProperties -> {
58                 val token = restClientProperties.tokenAuth!!
59                 token.additionalHeaders = restClientProperties.additionalHeaders
60                 token.url = restClientProperties.url
61                 token.type = restClientProperties.type
62                 TokenAuthRestClientService(token)
63             }
64             else -> {
65                 // Returns null for No auth
66                 null
67             }
68         }
69     }
70
71     override fun defaultHeaders(): Map<String, String> {
72         if (auth != null) {
73             return auth!!.defaultHeaders()
74         }
75         return mapOf(
76             HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE,
77             HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE
78         )
79     }
80
81     override fun host(uri: String): String {
82         return restClientProperties.url + uri
83     }
84
85     override fun httpClient(): CloseableHttpClient {
86
87         val keystoreInstance = restClientProperties.keyStoreInstance
88         val sslKey = restClientProperties.sslKey
89         val sslKeyPwd = restClientProperties.sslKeyPassword
90         val sslTrust = restClientProperties.sslTrust
91         val sslTrustPwd = restClientProperties.sslTrustPassword
92         val sslTrustIgnoreHostname = restClientProperties.sslTrustIgnoreHostname
93
94         val acceptingTrustStrategy = { _: Array<X509Certificate>, _: String ->
95             true
96         }
97         val sslContext = SSLContextBuilder.create()
98
99         if (sslKey != null && sslKeyPwd != null) {
100             FileInputStream(sslKey).use { keyInput ->
101                 val keyStore = KeyStore.getInstance(keystoreInstance)
102                 keyStore.load(keyInput, sslKeyPwd.toCharArray())
103                 sslContext.loadKeyMaterial(keyStore, sslKeyPwd.toCharArray())
104             }
105         }
106
107         sslContext.loadTrustMaterial(File(sslTrust), sslTrustPwd.toCharArray(), acceptingTrustStrategy)
108         var csf: SSLConnectionSocketFactory
109         if (sslTrustIgnoreHostname) {
110             csf = SSLConnectionSocketFactory(sslContext.build(), NoopHostnameVerifier())
111         } else {
112             csf = SSLConnectionSocketFactory(sslContext.build())
113         }
114         return HttpClients.custom()
115             .addInterceptorFirst(WebClientUtils.logRequest())
116             .addInterceptorLast(WebClientUtils.logResponse())
117             .setSSLSocketFactory(csf).build()
118     }
119
120     // Non Blocking Rest Implementation
121     override suspend fun httpClientNB(): CloseableHttpClient {
122         return httpClient()
123     }
124
125     override fun convertToBasicHeaders(headers: Map<String, String>): Array<BasicHeader> {
126         val mergedDefaultAndSuppliedHeaders = defaultHeaders().plus(headers)
127         // During the initialization, getAuthService() sets the auth variable.
128         // If it's not null, then we have an authentication mechanism.
129         // If null - indicates no-auth used
130         if (auth != null) {
131             return auth!!.convertToBasicHeaders(mergedDefaultAndSuppliedHeaders)
132         }
133         // inject additionalHeaders
134         return super.convertToBasicHeaders(
135             mergedDefaultAndSuppliedHeaders
136                 .plus(verifyAdditionalHeaders(restClientProperties))
137         )
138     }
139 }