Add Rest client that do not add any default headers
[ccsdk/cds.git] / ms / blueprintsprocessor / modules / commons / rest-lib / src / main / kotlin / org / onap / ccsdk / cds / blueprintsprocessor / rest / service / SSLRestClientService.kt
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.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
35 import java.io.File
36 import java.io.FileInputStream
37 import java.security.KeyStore
38 import java.security.cert.X509Certificate
39
40 open class SSLRestClientService(private val restClientProperties: SSLRestClientProperties) :
41     BaseBlueprintWebClientService<SSLRestClientProperties>() {
42
43     var auth: BlueprintWebClientService? = null
44
45     init {
46         auth = getAuthService()
47     }
48
49     override fun getRestClientProperties(): SSLRestClientProperties {
50         return restClientProperties
51     }
52
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)
65             }
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)
72             }
73             else -> {
74                 // Returns null for No auth
75                 null
76             }
77         }
78     }
79
80     override fun defaultHeaders(): Map<String, String> {
81         if (auth != null) {
82             return auth!!.defaultHeaders()
83         }
84         return if (restClientProperties.type == RestLibConstants.TYPE_SSL_NO_DEF_HEADERS)
85             mapOf()
86         else
87             mapOf(
88                 HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE,
89                 HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE
90             )
91     }
92
93     override fun httpClient(): CloseableHttpClient {
94
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
101
102         val acceptingTrustStrategy = { _: Array<X509Certificate>, _: String ->
103             true
104         }
105         val sslContext = SSLContextBuilder.create()
106
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())
112             }
113         }
114
115         sslContext.loadTrustMaterial(File(sslTrust), sslTrustPwd.toCharArray(), acceptingTrustStrategy)
116         var csf: SSLConnectionSocketFactory
117         if (sslTrustIgnoreHostname) {
118             csf = SSLConnectionSocketFactory(sslContext.build(), NoopHostnameVerifier())
119         } else {
120             csf = SSLConnectionSocketFactory(sslContext.build())
121         }
122         return HttpClients.custom()
123             .addInterceptorFirst(WebClientUtils.logRequest())
124             .addInterceptorLast(WebClientUtils.logResponse())
125             .setDefaultRequestConfig(getRequestConfig())
126             .setSSLSocketFactory(csf).build()
127     }
128
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
134         if (auth != null) {
135             return auth!!.convertToBasicHeaders(mergedDefaultAndSuppliedHeaders)
136         }
137         // inject additionalHeaders
138         return super.convertToBasicHeaders(
139             mergedDefaultAndSuppliedHeaders
140                 .plus(verifyAdditionalHeaders(restClientProperties))
141         )
142     }
143 }