Merge "Revert "Use ProcessPool rather than ThreadPool Executor""
[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.SSLConnectionSocketFactory
21 import org.apache.http.impl.client.CloseableHttpClient
22 import org.apache.http.impl.client.HttpClients
23 import org.apache.http.message.BasicHeader
24 import org.apache.http.ssl.SSLContextBuilder
25 import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLBasicAuthRestClientProperties
26 import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLRestClientProperties
27 import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLTokenAuthRestClientProperties
28 import org.onap.ccsdk.cds.blueprintsprocessor.rest.utils.WebClientUtils
29 import org.springframework.http.HttpHeaders
30 import org.springframework.http.MediaType
31 import java.io.File
32 import java.io.FileInputStream
33 import java.security.KeyStore
34 import java.security.cert.X509Certificate
35
36 class SSLRestClientService(private val restClientProperties: SSLRestClientProperties) :
37     BlueprintWebClientService {
38
39     var auth: BlueprintWebClientService? = null
40
41     init {
42         auth = getAuthService()
43     }
44
45     private fun getAuthService(): BlueprintWebClientService? {
46         //type,url and additional headers don't get carried over to TokenAuthRestClientProperties from SSLTokenAuthRestClientProperties
47         //set them in auth obj to be consistent. TODO: refactor
48         return when (restClientProperties) {
49             is SSLBasicAuthRestClientProperties -> {
50                 val basicAuthProps = restClientProperties.basicAuth!!
51                 basicAuthProps.additionalHeaders = restClientProperties.additionalHeaders
52                 basicAuthProps.url = restClientProperties.url
53                 basicAuthProps.type = restClientProperties.type
54                 BasicAuthRestClientService(basicAuthProps)
55             }
56             is SSLTokenAuthRestClientProperties -> {
57                 val token = restClientProperties.tokenAuth!!
58                 token.additionalHeaders = restClientProperties.additionalHeaders
59                 token.url = restClientProperties.url
60                 token.type = restClientProperties.type
61                 TokenAuthRestClientService(token)
62             }
63             else -> {
64                 //Returns null for No auth
65                 null
66             }
67         }
68     }
69
70     override fun defaultHeaders(): Map<String, String> {
71         if (auth != null) {
72             return auth!!.defaultHeaders()
73         }
74         return mapOf(
75             HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE,
76             HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE)
77     }
78
79     override fun host(uri: String): String {
80         return restClientProperties.url + uri
81     }
82
83     override fun httpClient(): CloseableHttpClient {
84
85         val keystoreInstance = restClientProperties.keyStoreInstance
86         val sslKey = restClientProperties.sslKey
87         val sslKeyPwd = restClientProperties.sslKeyPassword
88         val sslTrust = restClientProperties.sslTrust
89         val sslTrustPwd = restClientProperties.sslTrustPassword
90
91         val acceptingTrustStrategy = { _: Array<X509Certificate>, _: String ->
92             true
93         }
94         val sslContext = SSLContextBuilder.create()
95
96         if (sslKey != null && sslKeyPwd != null) {
97             FileInputStream(sslKey).use { keyInput ->
98                 val keyStore = KeyStore.getInstance(keystoreInstance)
99                 keyStore.load(keyInput, sslKeyPwd.toCharArray())
100                 sslContext.loadKeyMaterial(keyStore, sslKeyPwd.toCharArray())
101             }
102         }
103
104         sslContext.loadTrustMaterial(File(sslTrust), sslTrustPwd.toCharArray(),
105             acceptingTrustStrategy)
106         val csf = SSLConnectionSocketFactory(sslContext.build())
107         return HttpClients.custom()
108             .addInterceptorFirst(WebClientUtils.logRequest())
109             .addInterceptorLast(WebClientUtils.logResponse())
110             .setSSLSocketFactory(csf).build()
111     }
112
113     // Non Blocking Rest Implementation
114     override suspend fun httpClientNB(): CloseableHttpClient {
115         return httpClient()
116     }
117
118     override fun convertToBasicHeaders(headers: Map<String, String>): Array<BasicHeader> {
119         val mergedDefaultAndSuppliedHeaders = defaultHeaders().plus(headers)
120         //During the initialization, getAuthService() sets the auth variable.
121         //If it's not null, then we have an authentication mechanism.
122         //If null - indicates no-auth used
123         if (auth != null) {
124             return auth!!.convertToBasicHeaders(mergedDefaultAndSuppliedHeaders)
125         }
126         //inject additionalHeaders
127         return super.convertToBasicHeaders(mergedDefaultAndSuppliedHeaders
128             .plus(verifyAdditionalHeaders(restClientProperties)))
129     }
130 }