Implement Basic Auth rest client service.
authorMuthuramalingam, Brinda Santh(bs2796) <bs2796@att.com>
Tue, 18 Dec 2018 21:11:09 +0000 (16:11 -0500)
committerMuthuramalingam, Brinda Santh(bs2796) <bs2796@att.com>
Tue, 18 Dec 2018 21:11:09 +0000 (16:11 -0500)
Change-Id: Ic8113f718f542aa6864943dc627b2171fccccca2
Issue-ID: CCSDK-699
Signed-off-by: Muthuramalingam, Brinda Santh(bs2796) <bs2796@att.com>
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/resource/resolutionprocessor/ResourceAssignmentProcessor.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/BluePrintRestLibData.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/BlueprintWebClientService.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/DME2ProxyRestClientService.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/SSLBasicAuthRestClientService.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/utils/WebClientUtils.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/RestClientServiceTest.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/services/execution/AbstractComponentFunction.kt

index faf4fd4..41e4545 100644 (file)
@@ -23,10 +23,11 @@ open class RestClientProperties {
 }
 
 open class BasicAuthRestClientProperties : RestClientProperties() {
-    var passwd: String? = null
+    var token: String? = null
 }
 
 open class SSLBasicAuthRestClientProperties : RestClientProperties() {
+    lateinit var keyStoreInstance: String // JKS, PKCS12
     lateinit var sslTrust: String
     lateinit var sslTrustPasswd: String
     lateinit var sslKey: String
index b79034b..130706d 100644 (file)
 
 package org.onap.ccsdk.apps.blueprintsprocessor.rest.service
 
-import org.onap.ccsdk.apps.blueprintsprocessor.rest.RestClientProperties
+import org.onap.ccsdk.apps.blueprintsprocessor.rest.BasicAuthRestClientProperties
+import org.onap.ccsdk.apps.blueprintsprocessor.rest.utils.WebClientUtils
+import org.springframework.http.HttpHeaders
+import org.springframework.http.MediaType
+import org.springframework.web.reactive.function.BodyInserters
+import org.springframework.web.reactive.function.client.ExchangeFilterFunctions
 import org.springframework.web.reactive.function.client.WebClient
 
 
-class BasicAuthRestClientService(restClientProperties: RestClientProperties) : BlueprintWebClientService {
+class BasicAuthRestClientService(private val restClientProperties: BasicAuthRestClientProperties) : BlueprintWebClientService {
+
+    private var webClient: WebClient? = null
 
     override fun webClient(): WebClient {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+        if (webClient == null) {
+            webClient = WebClient.builder()
+                    .baseUrl(restClientProperties.url)
+                    .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
+                    .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
+                    .filter(ExchangeFilterFunctions
+                            .basicAuthentication(restClientProperties.userId, restClientProperties.token))
+                    .filter(WebClientUtils.logRequest())
+                    .filter(WebClientUtils.logResponse())
+                    .build()
+        }
+        return webClient!!
     }
 
     override fun <T> getResource(path: String, responseType: Class<T>): T {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+        return getResource(path, null, responseType)
+    }
+
+    override fun <T> getResource(path: String, headers: Map<String, String>?, responseType: Class<T>): T {
+        return webClient().get()
+                .uri(path)
+                .headers { httpHeaders ->
+                    headers?.forEach {
+                        httpHeaders.set(it.key, it.value)
+                    }
+                }
+                .retrieve()
+                .bodyToMono(responseType).block()!!
     }
 
     override fun <T> postResource(path: String, request: Any, responseType: Class<T>): T {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+        return postResource(path, null, request, responseType)
+    }
+
+    override fun <T> postResource(path: String, headers: Map<String, String>?, request: Any, responseType: Class<T>): T {
+        return webClient().post()
+                .uri(path)
+                .headers { httpHeaders ->
+                    headers?.forEach {
+                        httpHeaders.set(it.key, it.value)
+                    }
+                }
+                .body(BodyInserters.fromObject(request))
+                .retrieve().bodyToMono(responseType).block()!!
     }
 
     override fun <T> exchangeResource(methodType: String, path: String, request: Any, responseType: Class<T>): T {
index 232f4bb..8106c07 100644 (file)
@@ -24,8 +24,12 @@ interface BlueprintWebClientService {
 
     fun <T> getResource(path: String, responseType: Class<T>): T
 
+    fun <T> getResource(path: String, headers: Map<String, String>?, responseType: Class<T>): T
+
     fun <T> postResource(path: String, request: Any, responseType: Class<T>): T
 
+    fun <T> postResource(path: String, headers: Map<String, String>?, request: Any, responseType: Class<T>): T
+
     fun <T> exchangeResource(methodType: String, path: String, request: Any, responseType: Class<T>): T
 
 }
index bd46ced..27dbe6f 100644 (file)
@@ -28,10 +28,18 @@ class DME2ProxyRestClientService(restClientProperties: RestClientProperties) : B
         TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
     }
 
+    override fun <T> getResource(path: String, headers: Map<String, String>?, responseType: Class<T>): T {
+        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+    }
+
     override fun <T> postResource(path: String, request: Any, responseType: Class<T>): T {
         TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
     }
 
+    override fun <T> postResource(path: String, headers: Map<String, String>?, request: Any, responseType: Class<T>): T {
+        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+    }
+
     override fun <T> exchangeResource(methodType: String, path: String, request: Any, responseType: Class<T>): T {
         TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
     }
index 8b4add1..71727b9 100644 (file)
 
 package org.onap.ccsdk.apps.blueprintsprocessor.rest.service
 
-import org.onap.ccsdk.apps.blueprintsprocessor.rest.RestClientProperties
+import io.netty.handler.ssl.SslContextBuilder
+import org.onap.ccsdk.apps.blueprintsprocessor.rest.SSLBasicAuthRestClientProperties
+import org.onap.ccsdk.apps.blueprintsprocessor.rest.utils.WebClientUtils
+import org.springframework.http.HttpHeaders
+import org.springframework.http.MediaType
+import org.springframework.http.client.reactive.ReactorClientHttpConnector
+import org.springframework.web.reactive.function.BodyInserters
 import org.springframework.web.reactive.function.client.WebClient
+import reactor.netty.http.client.HttpClient
+import java.io.File
+import java.security.KeyStore
+import java.security.cert.X509Certificate
+
+
+class SSLBasicAuthRestClientService(private val restClientProperties: SSLBasicAuthRestClientProperties) : BlueprintWebClientService {
 
-class SSLBasicAuthRestClientService(restClientProperties: RestClientProperties) : BlueprintWebClientService {
     override fun webClient(): WebClient {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+
+        // Load the Keystore Information
+        val ketInputStream = File(restClientProperties.sslKey).inputStream()
+        val ks = KeyStore.getInstance(restClientProperties.keyStoreInstance)
+        ks.load(ketInputStream, restClientProperties.sslKeyPasswd.toCharArray())
+
+        // Manage Trust Store
+        val trustCertCollection = ks.aliases().toList().map { alias ->
+            ks.getCertificate(alias) as X509Certificate
+        }.toTypedArray()
+        val sslContext = SslContextBuilder
+                .forClient()
+                .trustManager(*trustCertCollection)
+                .build()
+
+        // Create Http Client
+        val httpClient = HttpClient.create().secure { t -> t.sslContext(sslContext) }
+
+        return WebClient.builder()
+                .baseUrl(restClientProperties.url)
+                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
+                .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
+                .filter(WebClientUtils.logRequest())
+                .clientConnector(ReactorClientHttpConnector(httpClient)).build()
     }
 
     override fun <T> getResource(path: String, responseType: Class<T>): T {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+        return getResource(path, null, responseType)
+    }
+
+    override fun <T> getResource(path: String, headers: Map<String, String>?, responseType: Class<T>): T {
+        return webClient().get()
+                .uri(path)
+                .headers { httpHeaders ->
+                    headers?.forEach {
+                        httpHeaders.set(it.key, it.value)
+                    }
+                }
+                .retrieve()
+                .bodyToMono(responseType).block()!!
     }
 
     override fun <T> postResource(path: String, request: Any, responseType: Class<T>): T {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+        return postResource(path, null, request, responseType)
+    }
+
+    override fun <T> postResource(path: String, headers: Map<String, String>?, request: Any, responseType: Class<T>): T {
+        return webClient().post()
+                .uri(path)
+                .headers { httpHeaders ->
+                    headers?.forEach {
+                        httpHeaders.set(it.key, it.value)
+                    }
+                }
+                .body(BodyInserters.fromObject(request))
+                .retrieve().bodyToMono(responseType).block()!!
     }
 
     override fun <T> exchangeResource(methodType: String, path: String, request: Any, responseType: Class<T>): T {
diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/utils/WebClientUtils.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/utils/WebClientUtils.kt
new file mode 100644 (file)
index 0000000..40d6ba6
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2017-2018 AT&T Intellectual Property.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onap.ccsdk.apps.blueprintsprocessor.rest.utils
+
+import org.slf4j.LoggerFactory
+import org.springframework.web.reactive.function.client.ExchangeFilterFunction
+import reactor.core.publisher.Mono
+
+
+class WebClientUtils {
+    companion object {
+
+        val log = LoggerFactory.getLogger(WebClientUtils::class.java)!!
+
+        fun logRequest(): ExchangeFilterFunction {
+
+            return ExchangeFilterFunction.ofRequestProcessor { clientRequest ->
+                log.info("Rest request method(${clientRequest.method()}), url(${clientRequest.url()})")
+                Mono.just(clientRequest)
+            }
+        }
+
+        fun logResponse(): ExchangeFilterFunction {
+            return ExchangeFilterFunction.ofResponseProcessor { clientResponse ->
+                log.info("Response status(${clientResponse.statusCode()})")
+                Mono.just(clientResponse)
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/RestClientServiceTest.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/RestClientServiceTest.kt
new file mode 100644 (file)
index 0000000..502758a
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2017-2018 AT&T Intellectual Property.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onap.ccsdk.apps.blueprintsprocessor.rest.service
+
+import org.junit.runner.RunWith
+import org.onap.ccsdk.apps.blueprintsprocessor.core.BluePrintProperties
+import org.onap.ccsdk.apps.blueprintsprocessor.core.BlueprintPropertyConfiguration
+import org.onap.ccsdk.apps.blueprintsprocessor.rest.BluePrintRestLibConfiguration
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.ContextConfiguration
+import org.springframework.test.context.TestPropertySource
+import org.springframework.test.context.junit4.SpringRunner
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+import kotlin.test.Test
+import kotlin.test.assertNotNull
+
+@EnableAutoConfiguration
+@RunWith(SpringRunner::class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
+@ContextConfiguration(classes = [BluePrintRestLibConfiguration::class, BlueprintPropertyConfiguration::class,
+    SampleController::class, BluePrintProperties::class])
+@TestPropertySource(properties =
+["server.port=9111",
+    "blueprintsprocessor.restclient.sample.type=basic-auth",
+    "blueprintsprocessor.restclient.sample.url=http://127.0.0.1:9111",
+    "blueprintsprocessor.restclient.sample.userId=sampleuser",
+    "blueprintsprocessor.restclient.sample.token=sampletoken"])
+class RestClientServiceTest {
+
+    @Autowired
+    lateinit var bluePrintRestLibPropertyService: BluePrintRestLibPropertyService
+
+    @Test
+    fun testBaseAuth() {
+
+        val restClientService = bluePrintRestLibPropertyService.blueprintWebClientService("sample")
+        val headers = mutableMapOf<String, String>()
+        headers["X-Transaction-Id"] = "1234"
+        val response = restClientService.getResource("/sample/name", headers, String::class.java)
+        assertNotNull(response, "failed to get response")
+    }
+
+}
+
+@RestController
+@RequestMapping("/sample")
+open class SampleController {
+    @GetMapping("/name")
+    fun getName(): String = "Sample Controller"
+}
+
index 363899e..c9e147b 100644 (file)
@@ -120,4 +120,8 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic
         return operationInputs[key]\r
                 ?: throw BluePrintProcessorException("couldn't get the operation input($key) value.")\r
     }\r
+\r
+    fun setAttribute(key: String, value: JsonNode) {\r
+        bluePrintRuntimeService.setNodeTemplateAttributeValue(nodeTemplateName, key, value)\r
+    }\r
 }
\ No newline at end of file