2 * Copyright © 2017-2019 AT&T, Bell Canada
3 * Modifications Copyright © 2019 Huawei.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 package org.onap.ccsdk.cds.blueprintsprocessor.rest.service
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.BasicAuthRestClientProperties
27 import org.onap.ccsdk.cds.blueprintsprocessor.rest.RestClientProperties
28 import org.onap.ccsdk.cds.blueprintsprocessor.rest.RestLibConstants
29 import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLBasicAuthRestClientProperties
30 import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLRestClientProperties
31 import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLTokenAuthRestClientProperties
32 import org.onap.ccsdk.cds.blueprintsprocessor.rest.utils.WebClientUtils
33 import org.springframework.http.HttpHeaders
34 import org.springframework.http.MediaType
36 import java.io.FileInputStream
37 import java.security.KeyStore
38 import java.security.cert.X509Certificate
40 open class SSLRestClientService(private val restClientProperties: SSLRestClientProperties) :
41 BaseBlueprintWebClientService<SSLRestClientProperties>() {
43 var auth: BlueprintWebClientService? = null
46 auth = getAuthService()
49 override fun getRestClientProperties(): SSLRestClientProperties {
50 return restClientProperties
53 private fun getAuthService(): BaseBlueprintWebClientService<RestClientProperties>? {
54 // type,url and additional headers don't get carried over to TokenAuthRestClientProperties from SSLTokenAuthRestClientProperties
55 // set them in auth obj to be consistent. TODO: refactor
56 return when (restClientProperties) {
57 is SSLBasicAuthRestClientProperties -> {
58 val basicAuthProps = BasicAuthRestClientProperties()
59 basicAuthProps.username = restClientProperties.username
60 basicAuthProps.password = restClientProperties.password
61 basicAuthProps.additionalHeaders = restClientProperties.additionalHeaders
62 basicAuthProps.url = restClientProperties.url
63 basicAuthProps.type = restClientProperties.type
64 BasicAuthRestClientService(basicAuthProps)
66 is SSLTokenAuthRestClientProperties -> {
67 val token = restClientProperties.tokenAuth!!
68 token.additionalHeaders = restClientProperties.additionalHeaders
69 token.url = restClientProperties.url
70 token.type = restClientProperties.type
71 TokenAuthRestClientService(token)
74 // Returns null for No auth
80 override fun defaultHeaders(): Map<String, String> {
82 return auth!!.defaultHeaders()
84 return if (restClientProperties.type == RestLibConstants.TYPE_SSL_NO_DEF_HEADERS)
88 HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE,
89 HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE
93 override fun httpClient(): CloseableHttpClient {
95 val keystoreInstance = restClientProperties.keyStoreInstance
96 val sslKey = restClientProperties.sslKey
97 val sslKeyPwd = restClientProperties.sslKeyPassword
98 val sslTrust = restClientProperties.sslTrust
99 val sslTrustPwd = restClientProperties.sslTrustPassword
100 val sslTrustIgnoreHostname = restClientProperties.sslTrustIgnoreHostname
102 val acceptingTrustStrategy = { _: Array<X509Certificate>, _: String ->
105 val sslContext = SSLContextBuilder.create()
107 if (sslKey != null && sslKeyPwd != null) {
108 FileInputStream(sslKey).use { keyInput ->
109 val keyStore = KeyStore.getInstance(keystoreInstance)
110 keyStore.load(keyInput, sslKeyPwd.toCharArray())
111 sslContext.loadKeyMaterial(keyStore, sslKeyPwd.toCharArray())
115 sslContext.loadTrustMaterial(File(sslTrust), sslTrustPwd.toCharArray(), acceptingTrustStrategy)
116 var csf: SSLConnectionSocketFactory
117 if (sslTrustIgnoreHostname) {
118 csf = SSLConnectionSocketFactory(sslContext.build(), NoopHostnameVerifier())
120 csf = SSLConnectionSocketFactory(sslContext.build())
122 return HttpClients.custom()
123 .addInterceptorFirst(WebClientUtils.logRequest())
124 .addInterceptorLast(WebClientUtils.logResponse())
125 .setDefaultRequestConfig(getRequestConfig())
126 .setSSLSocketFactory(csf).build()
129 override fun convertToBasicHeaders(headers: Map<String, String>): Array<BasicHeader> {
130 val mergedDefaultAndSuppliedHeaders = defaultHeaders().plus(headers)
131 // During the initialization, getAuthService() sets the auth variable.
132 // If it's not null, then we have an authentication mechanism.
133 // If null - indicates no-auth used
135 return auth!!.convertToBasicHeaders(mergedDefaultAndSuppliedHeaders)
137 // inject additionalHeaders
138 return super.convertToBasicHeaders(
139 mergedDefaultAndSuppliedHeaders
140 .plus(verifyAdditionalHeaders(restClientProperties))