diff options
Diffstat (limited to 'ms/blueprintsprocessor/modules')
15 files changed, 851 insertions, 205 deletions
diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintProcessorData.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintProcessorData.kt index fb6a0832a..badd70065 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintProcessorData.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintProcessorData.kt @@ -86,7 +86,7 @@ open class Status { @get:ApiModelProperty(required = true) var code: Int = 200 @get:ApiModelProperty(required = true) - var eventType: String = "EVENT-ACTION-RESPONSE" + var eventType: String = "" @get:ApiModelProperty(required = true, example = "2012-04-23T18:25:43.511Z") @get:JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") var timestamp: Date = Date() diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/pom.xml b/ms/blueprintsprocessor/modules/commons/rest-lib/pom.xml index 054f2386e..6809e7968 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/pom.xml @@ -2,6 +2,7 @@ <!-- ~ Copyright © 2017-2018 AT&T Intellectual Property. ~ Modifications Copyright © 2018 IBM. + ~ Modifications Copyright © 2019 Huawei. ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. @@ -41,6 +42,16 @@ <artifactId>httpclient</artifactId> <version>${apache.httpcomponents.client.version}</version> </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-security</artifactId> + <scope>test</scope> + </dependency> </dependencies> </project> diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/BluePrintRestLibConfiguration.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/BluePrintRestLibConfiguration.kt index 05143f3d8..fa4ff231d 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/BluePrintRestLibConfiguration.kt +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/BluePrintRestLibConfiguration.kt @@ -1,6 +1,7 @@ /* * Copyright © 2017-2018 AT&T Intellectual Property. * Modifications Copyright © 2019 IBM. + * Modifications Copyright © 2019 Huawei. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,6 +34,8 @@ class RestLibConstants { const val TYPE_TOKEN_AUTH = "token-auth" const val TYPE_BASIC_AUTH = "basic-auth" const val TYPE_SSL_BASIC_AUTH = "ssl-basic-auth" + const val TYPE_SSL_TOKEN_AUTH = "ssl-token-auth" + const val TYPE_SSL_NO_AUTH = "ssl-no-auth" const val TYPE_DME2_PROXY = "dme2-proxy" const val TYPE_POLICY_MANAGER = "policy-manager" } diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/BluePrintRestLibData.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/BluePrintRestLibData.kt index 4e6e62efb..70ec9501a 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/BluePrintRestLibData.kt +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/BluePrintRestLibData.kt @@ -1,5 +1,6 @@ /* * Copyright © 2017-2018 AT&T Intellectual Property. + * Modifications Copyright © 2019 Huawei. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +22,22 @@ open class RestClientProperties { lateinit var url: String } +open class SSLRestClientProperties : RestClientProperties() { + lateinit var keyStoreInstance: String // JKS, PKCS12 + lateinit var sslTrust: String + lateinit var sslTrustPassword: String + var sslKey: String? = null + var sslKeyPassword: String? = null +} + +open class SSLBasicAuthRestClientProperties : SSLRestClientProperties() { + var basicAuth: BasicAuthRestClientProperties? = null +} + +open class SSLTokenAuthRestClientProperties : SSLRestClientProperties() { + var tokenAuth: TokenAuthRestClientProperties? = null +} + open class BasicAuthRestClientProperties : RestClientProperties() { lateinit var password: String lateinit var username: String @@ -30,14 +47,6 @@ open class TokenAuthRestClientProperties : RestClientProperties() { var token: String? = null } -open class SSLBasicAuthRestClientProperties : RestClientProperties() { - lateinit var keyStoreInstance: String // JKS, PKCS12 - lateinit var sslTrust: String - lateinit var sslTrustPassword: String - lateinit var sslKey: String - lateinit var sslKeyPassword: String -} - open class DME2RestClientProperties : RestClientProperties() { lateinit var service: String lateinit var subContext: String diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt index 67dbd0d72..3190cd1c6 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt @@ -23,11 +23,14 @@ import org.springframework.http.MediaType import java.nio.charset.Charset import java.util.* -class BasicAuthRestClientService(private val restClientProperties: BasicAuthRestClientProperties) : - BlueprintWebClientService { +class BasicAuthRestClientService(private val restClientProperties: + BasicAuthRestClientProperties) : + BlueprintWebClientService { override fun defaultHeaders(): Map<String, String> { - val encodedCredentials = setBasicAuth(restClientProperties.username, restClientProperties.password) + + val encodedCredentials = setBasicAuth(restClientProperties.username, + restClientProperties.password) return mapOf( HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE, HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE, @@ -38,18 +41,25 @@ class BasicAuthRestClientService(private val restClientProperties: BasicAuthRest return restClientProperties.url + uri } - override fun convertToBasicHeaders(headers: Map<String, String>): Array<BasicHeader> { + override fun convertToBasicHeaders(headers: Map<String, String>): + Array<BasicHeader> { + val customHeaders: MutableMap<String, String> = headers.toMutableMap() if (!headers.containsKey(HttpHeaders.AUTHORIZATION)) { - val encodedCredentials = setBasicAuth(restClientProperties.username, restClientProperties.password) - customHeaders[HttpHeaders.AUTHORIZATION] = "Basic $encodedCredentials" + val encodedCredentials = setBasicAuth( + restClientProperties.username, + restClientProperties.password) + customHeaders[HttpHeaders.AUTHORIZATION] = + "Basic $encodedCredentials" } return super.convertToBasicHeaders(customHeaders) } private fun setBasicAuth(username: String, password: String): String { + val credentialsString = "$username:$password" - return Base64.getEncoder().encodeToString(credentialsString.toByteArray(Charset.defaultCharset())) + return Base64.getEncoder().encodeToString( + credentialsString.toByteArray(Charset.defaultCharset())) } diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BluePrintRestLibPropertyService.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BluePrintRestLibPropertyService.kt index dc974468b..a6bbc39d8 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BluePrintRestLibPropertyService.kt +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BluePrintRestLibPropertyService.kt @@ -1,6 +1,7 @@ /* * Copyright © 2017-2019 AT&T, Bell Canada * Modifications Copyright © 2019 IBM. + * Modifications Copyright © 2019 Huawei. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,15 +26,19 @@ import org.onap.ccsdk.cds.blueprintsprocessor.rest.PolicyManagerRestClientProper import org.onap.ccsdk.cds.blueprintsprocessor.rest.RestClientProperties import org.onap.ccsdk.cds.blueprintsprocessor.rest.RestLibConstants import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLBasicAuthRestClientProperties +import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLRestClientProperties +import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLTokenAuthRestClientProperties import org.onap.ccsdk.cds.blueprintsprocessor.rest.TokenAuthRestClientProperties import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.springframework.stereotype.Service @Service(RestLibConstants.SERVICE_BLUEPRINT_REST_LIB_PROPERTY) -open class BluePrintRestLibPropertyService(private var bluePrintProperties: BluePrintProperties) { +open class BluePrintRestLibPropertyService(private var bluePrintProperties: + BluePrintProperties) { - fun blueprintWebClientService(jsonNode: JsonNode): BlueprintWebClientService { + fun blueprintWebClientService(jsonNode: JsonNode): + BlueprintWebClientService { val restClientProperties = restClientProperties(jsonNode) return blueprintWebClientService(restClientProperties) } @@ -45,7 +50,8 @@ open class BluePrintRestLibPropertyService(private var bluePrintProperties: Blue } fun restClientProperties(prefix: String): RestClientProperties { - val type = bluePrintProperties.propertyBeanType("$prefix.type", String::class.java) + val type = bluePrintProperties.propertyBeanType( + "$prefix.type", String::class.java) return when (type) { RestLibConstants.TYPE_BASIC_AUTH -> { basicAuthRestClientProperties(prefix) @@ -53,6 +59,12 @@ open class BluePrintRestLibPropertyService(private var bluePrintProperties: Blue RestLibConstants.TYPE_SSL_BASIC_AUTH -> { sslBasicAuthRestClientProperties(prefix) } + RestLibConstants.TYPE_SSL_TOKEN_AUTH -> { + sslTokenAuthRestClientProperties(prefix) + } + RestLibConstants.TYPE_SSL_NO_AUTH -> { + sslNoAuthRestClientProperties(prefix) + } RestLibConstants.TYPE_DME2_PROXY -> { dme2ProxyClientProperties(prefix) } @@ -60,69 +72,123 @@ open class BluePrintRestLibPropertyService(private var bluePrintProperties: Blue policyManagerRestClientProperties(prefix) } else -> { - throw BluePrintProcessorException("Rest adaptor($type) is not supported") + throw BluePrintProcessorException("Rest adaptor($type) is" + + " not supported") } } } - private fun restClientProperties(jsonNode: JsonNode): RestClientProperties { + fun restClientProperties(jsonNode: JsonNode): RestClientProperties { + val type = jsonNode.get("type").textValue() return when (type) { RestLibConstants.TYPE_TOKEN_AUTH -> { - JacksonUtils.readValue(jsonNode, TokenAuthRestClientProperties::class.java)!! + JacksonUtils.readValue(jsonNode, + TokenAuthRestClientProperties::class.java)!! } RestLibConstants.TYPE_BASIC_AUTH -> { - JacksonUtils.readValue(jsonNode, BasicAuthRestClientProperties::class.java)!! - } - RestLibConstants.TYPE_SSL_BASIC_AUTH -> { - JacksonUtils.readValue(jsonNode, SSLBasicAuthRestClientProperties::class.java)!! + JacksonUtils.readValue(jsonNode, + BasicAuthRestClientProperties::class.java)!! } RestLibConstants.TYPE_DME2_PROXY -> { - JacksonUtils.readValue(jsonNode, DME2RestClientProperties::class.java)!! + JacksonUtils.readValue(jsonNode, + DME2RestClientProperties::class.java)!! } RestLibConstants.TYPE_POLICY_MANAGER -> { - JacksonUtils.readValue(jsonNode, PolicyManagerRestClientProperties::class.java)!! + JacksonUtils.readValue(jsonNode, + PolicyManagerRestClientProperties::class.java)!! + } + RestLibConstants.TYPE_SSL_BASIC_AUTH -> { + JacksonUtils.readValue(jsonNode, + SSLBasicAuthRestClientProperties::class.java)!! + } + RestLibConstants.TYPE_SSL_TOKEN_AUTH -> { + JacksonUtils.readValue(jsonNode, + SSLTokenAuthRestClientProperties::class.java)!! + } + RestLibConstants.TYPE_SSL_NO_AUTH -> { + JacksonUtils.readValue( + jsonNode, SSLRestClientProperties::class.java)!! } else -> { - throw BluePrintProcessorException("Rest adaptor($type) is not supported") + throw BluePrintProcessorException("Rest adaptor($type) is" + + " not supported") } } } + + private fun blueprintWebClientService( + restClientProperties: RestClientProperties): + BlueprintWebClientService { - private fun blueprintWebClientService(restClientProperties: RestClientProperties): BlueprintWebClientService { when (restClientProperties) { + is SSLRestClientProperties -> { + return SSLRestClientService(restClientProperties) + } is TokenAuthRestClientProperties -> { return TokenAuthRestClientService(restClientProperties) } is BasicAuthRestClientProperties -> { return BasicAuthRestClientService(restClientProperties) } - is SSLBasicAuthRestClientProperties -> { - return SSLBasicAuthRestClientService(restClientProperties) - } is DME2RestClientProperties -> { return DME2ProxyRestClientService(restClientProperties) } else -> { - throw BluePrintProcessorException("couldn't get rest service for") + throw BluePrintProcessorException("couldn't get rest " + + "service for") } } } - private fun basicAuthRestClientProperties(prefix: String): BasicAuthRestClientProperties { - return bluePrintProperties.propertyBeanType(prefix, BasicAuthRestClientProperties::class.java) + private fun basicAuthRestClientProperties(prefix: String): + BasicAuthRestClientProperties { + return bluePrintProperties.propertyBeanType( + prefix, BasicAuthRestClientProperties::class.java) + } + + private fun sslBasicAuthRestClientProperties(prefix: String): + SSLRestClientProperties { + + val sslProps: SSLBasicAuthRestClientProperties = + bluePrintProperties.propertyBeanType( + prefix, SSLBasicAuthRestClientProperties::class.java) + val basicProps : BasicAuthRestClientProperties = + bluePrintProperties.propertyBeanType( + prefix, BasicAuthRestClientProperties::class.java) + sslProps.basicAuth = basicProps + return sslProps + } + + private fun sslTokenAuthRestClientProperties(prefix: String): + SSLRestClientProperties { + + val sslProps: SSLTokenAuthRestClientProperties = + bluePrintProperties.propertyBeanType(prefix, + SSLTokenAuthRestClientProperties::class.java) + val basicProps : TokenAuthRestClientProperties = + bluePrintProperties.propertyBeanType(prefix, + TokenAuthRestClientProperties::class.java) + sslProps.tokenAuth = basicProps + return sslProps } - private fun sslBasicAuthRestClientProperties(prefix: String): SSLBasicAuthRestClientProperties { - return bluePrintProperties.propertyBeanType(prefix, SSLBasicAuthRestClientProperties::class.java) + private fun sslNoAuthRestClientProperties(prefix: String): + SSLRestClientProperties { + return bluePrintProperties.propertyBeanType( + prefix, SSLRestClientProperties::class.java) } - private fun dme2ProxyClientProperties(prefix: String): DME2RestClientProperties { - return bluePrintProperties.propertyBeanType(prefix, DME2RestClientProperties::class.java) + private fun dme2ProxyClientProperties(prefix: String): + DME2RestClientProperties { + return bluePrintProperties.propertyBeanType( + prefix, DME2RestClientProperties::class.java) } - private fun policyManagerRestClientProperties(prefix: String): PolicyManagerRestClientProperties { - return bluePrintProperties.propertyBeanType(prefix, PolicyManagerRestClientProperties::class.java) + private fun policyManagerRestClientProperties(prefix: String): + PolicyManagerRestClientProperties { + return bluePrintProperties.propertyBeanType( + prefix, PolicyManagerRestClientProperties::class.java) } } diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BlueprintWebClientService.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BlueprintWebClientService.kt index 1c1d510fc..d6d02b330 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BlueprintWebClientService.kt +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BlueprintWebClientService.kt @@ -1,6 +1,7 @@ /* * Copyright © 2017-2019 AT&T, Bell Canada, Nordix Foundation * Modifications Copyright © 2018-2019 IBM. + * Modifications Copyright © 2019 Huawei. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +22,11 @@ import com.fasterxml.jackson.databind.JsonNode import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.apache.commons.io.IOUtils -import org.apache.http.client.methods.* +import org.apache.http.client.methods.HttpDelete +import org.apache.http.client.methods.HttpGet +import org.apache.http.client.methods.HttpPatch +import org.apache.http.client.methods.HttpPost +import org.apache.http.client.methods.HttpPut import org.apache.http.entity.StringEntity import org.apache.http.impl.client.CloseableHttpClient import org.apache.http.impl.client.HttpClients @@ -30,6 +35,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.rest.utils.WebClientUtils import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.springframework.http.HttpMethod +import java.io.InputStream import java.nio.charset.Charset interface BlueprintWebClientService { @@ -45,19 +51,24 @@ interface BlueprintWebClientService { .build() } - fun exchangeResource(methodType: String, path: String, request: String): String { - return this.exchangeResource(methodType, path, request, defaultHeaders()) + fun exchangeResource(methodType: String, path: String, request: String): + String { + return this.exchangeResource(methodType, path, request, + defaultHeaders()) } - fun exchangeResource(methodType: String, path: String, request: String, headers: Map<String, String>): String { - val convertedHeaders: Array<BasicHeader> = convertToBasicHeaders(headers) + fun exchangeResource(methodType: String, path: String, request: String, + headers: Map<String, String>): String { + val convertedHeaders: Array<BasicHeader> = convertToBasicHeaders( + headers) return when (HttpMethod.resolve(methodType)) { HttpMethod.DELETE -> delete(path, convertedHeaders) HttpMethod.GET -> get(path, convertedHeaders) HttpMethod.POST -> post(path, request, convertedHeaders) HttpMethod.PUT -> put(path, request, convertedHeaders) HttpMethod.PATCH -> patch(path, request, convertedHeaders) - else -> throw BluePrintProcessorException("Unsupported methodType($methodType)") + else -> throw BluePrintProcessorException("Unsupported met" + + "hodType($methodType)") } } @@ -81,7 +92,8 @@ interface BlueprintWebClientService { } } - fun post(path: String, request: String, headers: Array<BasicHeader>): String { + fun post(path: String, request: String, headers: Array<BasicHeader>): + String { val httpPost = HttpPost(host(path)) val entity = StringEntity(request) httpPost.entity = entity @@ -91,7 +103,8 @@ interface BlueprintWebClientService { } } - fun put(path: String, request: String, headers: Array<BasicHeader>): String { + fun put(path: String, request: String, headers: Array<BasicHeader>): + String { val httpPut = HttpPut(host(path)) val entity = StringEntity(request) httpPut.entity = entity @@ -101,7 +114,8 @@ interface BlueprintWebClientService { } } - fun patch(path: String, request: String, headers: Array<BasicHeader>): String { + fun patch(path: String, request: String, headers: Array<BasicHeader>): + String { val httpPatch = HttpPatch(host(path)) val entity = StringEntity(request) httpPatch.entity = entity @@ -111,28 +125,23 @@ interface BlueprintWebClientService { } } - // Non Blocking Rest Implementation - suspend fun httpClientNB(): CloseableHttpClient { - return HttpClients.custom() - .addInterceptorFirst(WebClientUtils.logRequest()) - .addInterceptorLast(WebClientUtils.logResponse()) - .build() - } suspend fun getNB(path: String): String { return getNB(path, null, String::class.java) } - suspend fun getNB(path: String, additionalHeaders: Map<String, String>?): String { + suspend fun getNB(path: String, additionalHeaders: Map<String, String>?): + String { return getNB(path, additionalHeaders, String::class.java) } suspend fun <T> getNB(path: String, additionalHeaders: Map<String, String>?, - responseType: Class<T>): T = withContext(Dispatchers.IO) { + responseType: Class<T>): T = + withContext(Dispatchers.IO) { val httpGet = HttpGet(host(path)) httpGet.setHeaders(basicHeaders(additionalHeaders)) httpClientNB().execute(httpGet).entity.content.use { - JacksonUtils.readValue(it, responseType)!! + getResponse(it, responseType) } } @@ -140,18 +149,20 @@ interface BlueprintWebClientService { return postNB(path, request, null, String::class.java) } - suspend fun postNB(path: String, request: Any, additionalHeaders: Map<String, String>?): String { + suspend fun postNB(path: String, request: Any, + additionalHeaders: Map<String, String>?): String { return postNB(path, request, additionalHeaders, String::class.java) } - suspend fun <T> postNB(path: String, request: Any, additionalHeaders: Map<String, String>?, + suspend fun <T> postNB(path: String, request: Any, + additionalHeaders: Map<String, String>?, responseType: Class<T>): T = withContext(Dispatchers.IO) { val httpPost = HttpPost(host(path)) httpPost.entity = StringEntity(strRequest(request)) httpPost.setHeaders(basicHeaders(additionalHeaders)) httpClientNB().execute(httpPost).entity.content.use { - JacksonUtils.readValue(it, responseType)!! + getResponse(it, responseType) } } @@ -159,17 +170,20 @@ interface BlueprintWebClientService { return putNB(path, request, null, String::class.java) } - suspend fun putNB(path: String, request: Any, additionalHeaders: Map<String, String>?): String { + suspend fun putNB(path: String, request: Any, + additionalHeaders: Map<String, String>?): String { return putNB(path, request, additionalHeaders, String::class.java) } - suspend fun <T> putNB(path: String, request: Any, additionalHeaders: Map<String, String>?, - responseType: Class<T>): T = withContext(Dispatchers.IO) { + suspend fun <T> putNB(path: String, request: Any, + additionalHeaders: Map<String, String>?, + responseType: Class<T>): T = + withContext(Dispatchers.IO) { val httpPut = HttpPut(host(path)) httpPut.entity = StringEntity(strRequest(request)) httpPut.setHeaders(basicHeaders(additionalHeaders)) httpClientNB().execute(httpPut).entity.content.use { - JacksonUtils.readValue(it, responseType)!! + getResponse(it, responseType) } } @@ -177,46 +191,61 @@ interface BlueprintWebClientService { return deleteNB(path, null, String::class.java) } - suspend fun <T> deleteNB(path: String, additionalHeaders: Map<String, String>?): String { + suspend fun <T> deleteNB(path: String, + additionalHeaders: Map<String, String>?): String { return deleteNB(path, additionalHeaders, String::class.java) } - suspend fun <T> deleteNB(path: String, additionalHeaders: Map<String, String>?, responseType: Class<T>): T = + suspend fun <T> deleteNB(path: String, + additionalHeaders: Map<String, String>?, + responseType: Class<T>): T = withContext(Dispatchers.IO) { - val httpDelete = HttpDelete(host(path)) - httpDelete.setHeaders(basicHeaders(additionalHeaders)) - httpClient().execute(httpDelete).entity.content.use { - JacksonUtils.readValue(it, responseType)!! - } - } + val httpDelete = HttpDelete(host(path)) + httpDelete.setHeaders(basicHeaders(additionalHeaders)) + httpClient().execute(httpDelete).entity.content.use { + getResponse(it, responseType) + } + } - suspend fun <T> patchNB(path: String, request: Any, additionalHeaders: Map<String, String>?, - responseType: Class<T>): T = withContext(Dispatchers.IO) { + suspend fun <T> patchNB(path: String, request: Any, + additionalHeaders: Map<String, String>?, + responseType: Class<T>): T = + withContext(Dispatchers.IO) { val httpPatch = HttpPatch(host(path)) httpPatch.entity = StringEntity(strRequest(request)) httpPatch.setHeaders(basicHeaders(additionalHeaders)) httpClient().execute(httpPatch).entity.content.use { - JacksonUtils.readValue(it, responseType)!! + getResponse(it, responseType) } } - suspend fun exchangeNB(methodType: String, path: String, request: Any): String { - return exchangeNB(methodType, path, request, hashMapOf(), String::class.java) + suspend fun exchangeNB(methodType: String, path: String, request: Any): + String { + return exchangeNB(methodType, path, request, hashMapOf(), + String::class.java) } - suspend fun exchangeNB(methodType: String, path: String, request: Any, additionalHeaders: Map<String, String>?): String { - return exchangeNB(methodType, path, request, additionalHeaders, String::class.java) + suspend fun exchangeNB(methodType: String, path: String, request: Any, + additionalHeaders: Map<String, String>?): String { + return exchangeNB(methodType, path, request, additionalHeaders, + String::class.java) } - suspend fun <T> exchangeNB(methodType: String, path: String, request: Any, additionalHeaders: Map<String, String>?, + suspend fun <T> exchangeNB(methodType: String, path: String, request: Any, + additionalHeaders: Map<String, String>?, responseType: Class<T>): T { + return when (HttpMethod.resolve(methodType)) { HttpMethod.GET -> getNB(path, additionalHeaders, responseType) - HttpMethod.POST -> postNB(path, request, additionalHeaders, responseType) + HttpMethod.POST -> postNB(path, request, additionalHeaders, + responseType) HttpMethod.DELETE -> deleteNB(path, additionalHeaders, responseType) - HttpMethod.PUT -> putNB(path, request, additionalHeaders, responseType) - HttpMethod.PATCH -> patchNB(path, request, additionalHeaders, responseType) - else -> throw BluePrintProcessorException("Unsupported methodType($methodType)") + HttpMethod.PUT -> putNB(path, request, additionalHeaders, + responseType) + HttpMethod.PATCH -> patchNB(path, request, additionalHeaders, + responseType) + else -> throw BluePrintProcessorException("Unsupported method" + + "Type($methodType)") } } @@ -228,7 +257,17 @@ interface BlueprintWebClientService { } } - private fun basicHeaders(headers: Map<String, String>?): Array<BasicHeader> { + private fun <T> getResponse(it: InputStream, responseType: Class<T>): T { + return if (responseType == String::class.java) { + IOUtils.toString(it, Charset.defaultCharset()) as T + } else { + JacksonUtils.readValue(it, responseType)!! + } + } + + private fun basicHeaders(headers: Map<String, String>?): + Array<BasicHeader> { + val basicHeaders = mutableListOf<BasicHeader>() defaultHeaders().forEach { name, value -> basicHeaders.add(BasicHeader(name, value)) @@ -238,4 +277,12 @@ interface BlueprintWebClientService { } return basicHeaders.toTypedArray() } + + // Non Blocking Rest Implementation + suspend fun httpClientNB(): CloseableHttpClient { + return HttpClients.custom() + .addInterceptorFirst(WebClientUtils.logRequest()) + .addInterceptorLast(WebClientUtils.logResponse()) + .build() + } }
\ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/SSLBasicAuthRestClientService.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/SSLBasicAuthRestClientService.kt deleted file mode 100644 index 3d3b0a57e..000000000 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/SSLBasicAuthRestClientService.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright © 2017-2019 AT&T, Bell Canada - * - * 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.cds.blueprintsprocessor.rest.service - -import org.apache.http.conn.ssl.SSLConnectionSocketFactory -import org.apache.http.impl.client.CloseableHttpClient -import org.apache.http.impl.client.HttpClients -import org.apache.http.ssl.SSLContextBuilder -import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLBasicAuthRestClientProperties -import org.onap.ccsdk.cds.blueprintsprocessor.rest.utils.WebClientUtils -import org.springframework.http.HttpHeaders -import org.springframework.http.MediaType -import java.io.File -import java.io.FileInputStream -import java.security.KeyStore -import java.security.cert.X509Certificate - -class SSLBasicAuthRestClientService(private val restClientProperties: SSLBasicAuthRestClientProperties) : - BlueprintWebClientService { - - override fun defaultHeaders(): Map<String, String> { - return mapOf( - HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE, - HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE) - } - - override fun host(uri: String): String { - return restClientProperties.url + uri - } - - override fun httpClient(): CloseableHttpClient { - - val keystoreInstance = restClientProperties.keyStoreInstance - val sslKey = restClientProperties.sslKey - val sslKeyPwd = restClientProperties.sslKeyPassword - val sslTrust = restClientProperties.sslTrust - val sslTrustPwd = restClientProperties.sslTrustPassword - - val acceptingTrustStrategy = { chain: Array<X509Certificate>, authType: String -> true } - - FileInputStream(sslKey).use { keyInput -> - val keyStore = KeyStore.getInstance(keystoreInstance) - keyStore.load(keyInput, sslKeyPwd.toCharArray()) - - val sslContext = - SSLContextBuilder.create() - .loadKeyMaterial(keyStore, sslKeyPwd.toCharArray()) - .loadTrustMaterial(File(sslTrust), sslTrustPwd.toCharArray(), acceptingTrustStrategy).build() - - val csf = SSLConnectionSocketFactory(sslContext!!) - - return HttpClients.custom() - .addInterceptorFirst(WebClientUtils.logRequest()) - .addInterceptorLast(WebClientUtils.logResponse()) - .setSSLSocketFactory(csf).build() - } - } -}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/SSLRestClientService.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/SSLRestClientService.kt new file mode 100644 index 000000000..30dd49018 --- /dev/null +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/SSLRestClientService.kt @@ -0,0 +1,125 @@ +/* + * Copyright © 2017-2019 AT&T, Bell Canada + * Modifications Copyright © 2019 Huawei. + * + * 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.cds.blueprintsprocessor.rest.service + +import org.apache.http.conn.ssl.SSLConnectionSocketFactory +import org.apache.http.impl.client.CloseableHttpClient +import org.apache.http.impl.client.HttpClients +import org.apache.http.message.BasicHeader +import org.apache.http.ssl.SSLContextBuilder +import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLBasicAuthRestClientProperties +import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLRestClientProperties +import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLTokenAuthRestClientProperties +import org.onap.ccsdk.cds.blueprintsprocessor.rest.utils.WebClientUtils +import org.springframework.http.HttpHeaders +import org.springframework.http.MediaType +import java.io.File +import java.io.FileInputStream +import java.security.KeyStore +import java.security.cert.X509Certificate + +class SSLRestClientService(private val restClientProperties: + SSLRestClientProperties) : + BlueprintWebClientService { + + var auth: BlueprintWebClientService? = null + + init { + auth = getAuthService() + } + + private fun getAuthService() : BlueprintWebClientService? { + + return when(restClientProperties) { + is SSLBasicAuthRestClientProperties -> { + val basic = restClientProperties.basicAuth!! + BasicAuthRestClientService(basic) + } + is SSLTokenAuthRestClientProperties -> { + val token = restClientProperties.tokenAuth!! + TokenAuthRestClientService(token) + } + else -> { + //Returns null for No auth + null + } + } + } + + + override fun defaultHeaders(): Map<String, String> { + + if (auth != null) { + return auth!!.defaultHeaders() + } + return mapOf( + HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE, + HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE) + } + + override fun host(uri: String): String { + + return restClientProperties.url + uri + } + + override fun httpClient(): CloseableHttpClient { + + val keystoreInstance = restClientProperties.keyStoreInstance + val sslKey = restClientProperties.sslKey + val sslKeyPwd = restClientProperties.sslKeyPassword + val sslTrust = restClientProperties.sslTrust + val sslTrustPwd = restClientProperties.sslTrustPassword + + val acceptingTrustStrategy = { chain: Array<X509Certificate>, + authType: String -> true } + val sslContext = SSLContextBuilder.create() + + if (sslKey != null && sslKeyPwd != null) { + FileInputStream(sslKey).use { keyInput -> + val keyStore = KeyStore.getInstance(keystoreInstance) + keyStore.load(keyInput, sslKeyPwd.toCharArray()) + sslContext.loadKeyMaterial(keyStore, sslKeyPwd.toCharArray()) + } + } + + sslContext.loadTrustMaterial(File(sslTrust), sslTrustPwd.toCharArray(), + acceptingTrustStrategy) + val csf = SSLConnectionSocketFactory(sslContext.build()) + return HttpClients.custom() + .addInterceptorFirst(WebClientUtils.logRequest()) + .addInterceptorLast(WebClientUtils.logResponse()) + .setSSLSocketFactory(csf).build() + + } + + // Non Blocking Rest Implementation + override suspend fun httpClientNB(): CloseableHttpClient { + return httpClient() + } + + override fun convertToBasicHeaders(headers: Map<String, String>): Array<BasicHeader> { + var head1: Map<String, String> = defaultHeaders() + var head2: MutableMap<String, String> = head1.toMutableMap() + head2.putAll(headers) + if (auth != null) { + return auth!!.convertToBasicHeaders(head2) + } + return super.convertToBasicHeaders(head2) + } + +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/TokenAuthRestClientService.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/TokenAuthRestClientService.kt index 6f81ee1a8..82446994c 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/TokenAuthRestClientService.kt +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/TokenAuthRestClientService.kt @@ -21,17 +21,21 @@ import org.onap.ccsdk.cds.blueprintsprocessor.rest.TokenAuthRestClientProperties import org.springframework.http.HttpHeaders import org.springframework.http.MediaType -class TokenAuthRestClientService(private val restClientProperties: TokenAuthRestClientProperties) : - BlueprintWebClientService { +class TokenAuthRestClientService(private val restClientProperties: + TokenAuthRestClientProperties) : + BlueprintWebClientService { override fun defaultHeaders(): Map<String, String> { + return mapOf( HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE, HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE, HttpHeaders.AUTHORIZATION to restClientProperties.token!!) } - override fun convertToBasicHeaders(headers: Map<String, String>): Array<BasicHeader> { + override fun convertToBasicHeaders(headers: Map<String, String>): + Array<BasicHeader> { + val customHeaders: MutableMap<String, String> = headers.toMutableMap() if (!headers.containsKey(HttpHeaders.AUTHORIZATION)) { customHeaders[HttpHeaders.AUTHORIZATION] = restClientProperties.token!! diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BluePrintRestLibPropertyServiceTest.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BluePrintRestLibPropertyServiceTest.kt index c57745713..280dd0d40 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BluePrintRestLibPropertyServiceTest.kt +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BluePrintRestLibPropertyServiceTest.kt @@ -1,6 +1,7 @@ /* * Copyright © 2017-2018 AT&T Intellectual Property. * Modifications Copyright © 2018 IBM. + * Modifications Copyright © 2019 Huawei. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,24 +18,50 @@ package org.onap.ccsdk.cds.blueprintsprocessor.rest.service +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.ObjectMapper import org.junit.Test import org.junit.runner.RunWith import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintProperties import org.onap.ccsdk.cds.blueprintsprocessor.core.BlueprintPropertyConfiguration import org.onap.ccsdk.cds.blueprintsprocessor.rest.BluePrintRestLibConfiguration +import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLBasicAuthRestClientProperties +import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLRestClientProperties +import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLTokenAuthRestClientProperties import org.springframework.beans.factory.annotation.Autowired import org.springframework.test.context.ContextConfiguration import org.springframework.test.context.TestPropertySource import org.springframework.test.context.junit4.SpringRunner +import kotlin.test.assertEquals import kotlin.test.assertNotNull - @RunWith(SpringRunner::class) @ContextConfiguration(classes = [BluePrintRestLibConfiguration::class, BlueprintPropertyConfiguration::class, BluePrintProperties::class]) @TestPropertySource(properties = ["blueprintsprocessor.restclient.sample.type=basic-auth", "blueprintsprocessor.restclient.sample.url=http://localhost:8080", - "blueprintsprocessor.restclient.sample.userId=sampleuser"]) + "blueprintsprocessor.restclient.sample.userId=sampleuser", + "blueprintsprocessor.restclient.sslbasic.type=ssl-basic-auth", + "blueprintsprocessor.restclient.sslbasic.url=https://localhost:8443", + "blueprintsprocessor.restclient.sslbasic.username=admin", + "blueprintsprocessor.restclient.sslbasic.password=cds", + "blueprintsprocessor.restclient.sslbasic.keyStoreInstance=PKCS12", + "blueprintsprocessor.restclient.sslbasic.sslTrust=src/test/resources/keystore.p12", + "blueprintsprocessor.restclient.sslbasic.sslTrustPassword=changeit", + "blueprintsprocessor.restclient.ssltoken.type=ssl-token-auth", + "blueprintsprocessor.restclient.ssltoken.url=https://localhost:8443", + "blueprintsprocessor.restclient.ssltoken.token=72178473kjshdkjgvbsdkjv903274908", + "blueprintsprocessor.restclient.ssltoken.keyStoreInstance=PKCS12", + "blueprintsprocessor.restclient.ssltoken.sslTrust=src/test/resources/keystore.p12", + "blueprintsprocessor.restclient.ssltoken.sslTrustPassword=changeit", + "blueprintsprocessor.restclient.ssl.type=ssl-no-auth", + "blueprintsprocessor.restclient.ssl.url=https://localhost:8443", + "blueprintsprocessor.restclient.ssl.keyStoreInstance=PKCS12", + "blueprintsprocessor.restclient.ssl.sslTrust=src/test/resources/keystore.p12", + "blueprintsprocessor.restclient.ssl.sslTrustPassword=changeit", + "blueprintsprocessor.restclient.ssl.sslKey=src/test/resources/keystore.p12", + "blueprintsprocessor.restclient.ssl.sslKeyPassword=changeit" +]) class BluePrintRestLibPropertyServiceTest { @@ -43,15 +70,148 @@ class BluePrintRestLibPropertyServiceTest { @Test fun testRestClientProperties() { - val properties = bluePrintRestLibPropertyService.restClientProperties("blueprintsprocessor.restclient.sample") + val properties = bluePrintRestLibPropertyService.restClientProperties( + "blueprintsprocessor.restclient.sample") + assertNotNull(properties, "failed to create property bean") + assertNotNull(properties.url, "failed to get url property in" + + " property bean") + } + + @Test + fun testSSLBasicProperties() { + val properties = bluePrintRestLibPropertyService.restClientProperties( + "blueprintsprocessor.restclient.sslbasic") + assertNotNull(properties, "failed to create property bean") + val p: SSLBasicAuthRestClientProperties = + properties as SSLBasicAuthRestClientProperties + + assertEquals(p.basicAuth!!.username, "admin") + assertEquals(p.basicAuth!!.password, "cds") + assertEquals(p.sslTrust, "src/test/resources/keystore.p12") + assertEquals(p.sslTrustPassword, "changeit") + assertEquals(p.keyStoreInstance, "PKCS12") + } + + @Test + fun testSSLTokenProperties() { + val properties = bluePrintRestLibPropertyService.restClientProperties( + "blueprintsprocessor.restclient.ssltoken") + assertNotNull(properties, "failed to create property bean") + + val p: SSLTokenAuthRestClientProperties = + properties as SSLTokenAuthRestClientProperties + + assertEquals(p.tokenAuth!!.token!!, "72178473kjshdkjgvbsdkjv903274908") + assertEquals(p.sslTrust, "src/test/resources/keystore.p12") + assertEquals(p.sslTrustPassword, "changeit") + assertEquals(p.keyStoreInstance, "PKCS12") + } + + @Test + fun testSSLNoAuthProperties() { + val properties = bluePrintRestLibPropertyService.restClientProperties( + "blueprintsprocessor.restclient.ssl") + assertNotNull(properties, "failed to create property bean") + + val p: SSLRestClientProperties = + properties as SSLRestClientProperties + + assertEquals(p.sslTrust, "src/test/resources/keystore.p12") + assertEquals(p.sslTrustPassword, "changeit") + assertEquals(p.keyStoreInstance, "PKCS12") + assertEquals(p.sslKey, "src/test/resources/keystore.p12") + assertEquals(p.sslKeyPassword, "changeit") + } + + + @Test + fun testSSLBasicPropertiesAsJson() { + val json: String = "{\n" + + " \"type\" : \"ssl-basic-auth\",\n" + + " \"url\" : \"https://localhost:8443\",\n" + + " \"keyStoreInstance\" : \"PKCS12\",\n" + + " \"sslTrust\" : \"src/test/resources/keystore.p12\",\n" + + " \"sslTrustPassword\" : \"changeit\",\n" + + " \"basicAuth\" : {\n" + + " \"username\" : \"admin\",\n" + + " \"password\" : \"cds\"\n" + + " }\n" + + "}" + val mapper = ObjectMapper() + val actualObj: JsonNode = mapper.readTree(json) + val properties = bluePrintRestLibPropertyService.restClientProperties( + actualObj) + assertNotNull(properties, "failed to create property bean") + val p: SSLBasicAuthRestClientProperties = + properties as SSLBasicAuthRestClientProperties + + assertEquals(p.basicAuth!!.username, "admin") + assertEquals(p.basicAuth!!.password, "cds") + assertEquals(p.sslTrust, "src/test/resources/keystore.p12") + assertEquals(p.sslTrustPassword, "changeit") + assertEquals(p.keyStoreInstance, "PKCS12") + } + + @Test + fun testSSLTokenPropertiesAsJson() { + val json: String = "{\n" + + " \"type\" : \"ssl-token-auth\",\n" + + " \"url\" : \"https://localhost:8443\",\n" + + " \"keyStoreInstance\" : \"PKCS12\",\n" + + " \"sslTrust\" : \"src/test/resources/keystore.p12\",\n" + + " \"sslTrustPassword\" : \"changeit\",\n" + + " \"tokenAuth\" : {\n" + + " \"token\" : \"72178473kjshdkjgvbsdkjv903274908\"\n" + + " }\n" + + "}" + val mapper = ObjectMapper() + val actualObj: JsonNode = mapper.readTree(json) + val properties = bluePrintRestLibPropertyService.restClientProperties( + actualObj) assertNotNull(properties, "failed to create property bean") - assertNotNull(properties.url, "failed to get url property in property bean") + + val p: SSLTokenAuthRestClientProperties = + properties as SSLTokenAuthRestClientProperties + + assertEquals(p.tokenAuth!!.token!!, "72178473kjshdkjgvbsdkjv903274908") + assertEquals(p.sslTrust, "src/test/resources/keystore.p12") + assertEquals(p.sslTrustPassword, "changeit") + assertEquals(p.keyStoreInstance, "PKCS12") + } + + @Test + fun testSSLNoAuthPropertiesAsJson() { + val json: String = "{\n" + + " \"type\" : \"ssl-basic-auth\",\n" + + " \"url\" : \"https://localhost:8443\",\n" + + " \"keyStoreInstance\" : \"PKCS12\",\n" + + " \"sslTrust\" : \"src/test/resources/keystore.p12\",\n" + + " \"sslTrustPassword\" : \"changeit\",\n" + + " \"sslKey\" : \"src/test/resources/keystore.p12\",\n" + + " \"sslKeyPassword\" : \"changeit\"\n" + + "}" + val mapper = ObjectMapper() + val actualObj: JsonNode = mapper.readTree(json) + val properties = bluePrintRestLibPropertyService.restClientProperties( + actualObj) + assertNotNull(properties, "failed to create property bean") + + val p: SSLRestClientProperties = + properties as SSLRestClientProperties + + assertEquals(p.sslTrust, "src/test/resources/keystore.p12") + assertEquals(p.sslTrustPassword, "changeit") + assertEquals(p.keyStoreInstance, "PKCS12") + assertEquals(p.sslKey, "src/test/resources/keystore.p12") + assertEquals(p.sslKeyPassword, "changeit") } @Test fun testBlueprintWebClientService() { - val blueprintWebClientService = bluePrintRestLibPropertyService.blueprintWebClientService("sample") - assertNotNull(blueprintWebClientService, "failed to create blueprintWebClientService") + val blueprintWebClientService = bluePrintRestLibPropertyService + .blueprintWebClientService("sample") + assertNotNull(blueprintWebClientService, "failed to create blu" + + "eprintWebClientService") } } diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestClientServiceTest.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestClientServiceTest.kt index a02a8083b..98cdfc0f2 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestClientServiceTest.kt +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestClientServiceTest.kt @@ -1,6 +1,7 @@ /* * Copyright © 2017-2018 AT&T Intellectual Property. * Copyright (C) 2019 Nordix Foundation + * Modifications Copyright © 2019 Huawei. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +18,13 @@ package org.onap.ccsdk.cds.blueprintsprocessor.rest.service +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.ObjectMapper +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.async +import kotlinx.coroutines.runBlocking +import org.apache.catalina.connector.Connector +import org.junit.Test import org.junit.runner.RunWith import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintProperties import org.onap.ccsdk.cds.blueprintsprocessor.core.BlueprintPropertyConfiguration @@ -25,57 +33,330 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.EnableAutoConfiguration import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration import org.springframework.boot.test.context.SpringBootTest +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory +import org.springframework.boot.web.servlet.server.ServletWebServerFactory +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration import org.springframework.http.HttpMethod +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder +import org.springframework.security.config.annotation.web.builders.HttpSecurity +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder +import org.springframework.security.crypto.password.PasswordEncoder +import org.springframework.stereotype.Component 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.DeleteMapping import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PatchMapping +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.PutMapping +import org.springframework.web.bind.annotation.RequestHeader import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController -import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNotNull @RunWith(SpringRunner::class) @EnableAutoConfiguration(exclude = [DataSourceAutoConfiguration::class]) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@ContextConfiguration(classes = [BluePrintRestLibConfiguration::class, BlueprintPropertyConfiguration::class, - SampleController::class, BluePrintProperties::class, BluePrintProperties::class]) +@ContextConfiguration(classes = [BluePrintRestLibConfiguration::class, + BlueprintPropertyConfiguration::class, + SampleController::class, BluePrintProperties::class, + BluePrintProperties::class]) @TestPropertySource(properties = -["blueprintsprocessor.restclient.sample.type=basic-auth", +[ + "server.port=8443", + "server.ssl.enabled=true", + "server.ssl.key-store=classpath:keystore.p12", + "server.ssl.key-store-password=changeit", + "server.ssl.keyStoreType=PKCS12", + "server.ssl.keyAlias=tomcat", + "blueprintsprocessor.restclient.sample.type=basic-auth", "blueprintsprocessor.restclient.sample.url=http://127.0.0.1:8080", - "blueprintsprocessor.restclient.sample.username=sampleuser", - "blueprintsprocessor.restclient.sample.password=sampletoken"]) + "blueprintsprocessor.restclient.sample.username=admin", + "blueprintsprocessor.restclient.sample.password=jans", + "blueprintsprocessor.restclient.test.type=ssl-basic-auth", + "blueprintsprocessor.restclient.test.url=https://localhost:8443", + "blueprintsprocessor.restclient.test.username=admin", + "blueprintsprocessor.restclient.test.password=jans", + "blueprintsprocessor.restclient.test.keyStoreInstance=PKCS12", + "blueprintsprocessor.restclient.test.sslTrust=src/test/resources/keystore.p12", + "blueprintsprocessor.restclient.test.sslTrustPassword=changeit" +]) class RestClientServiceTest { @Autowired lateinit var bluePrintRestLibPropertyService: BluePrintRestLibPropertyService @Test + fun testPatch() { + val restClientService = bluePrintRestLibPropertyService + .blueprintWebClientService("sample") + val response = restClientService.exchangeResource( + HttpMethod.PATCH.name, "/sample/name", "") + assertEquals("Patch request successful", response, + "failed to get patch response") + } + + @Test fun testBaseAuth() { - val restClientService = bluePrintRestLibPropertyService.blueprintWebClientService("sample") + val restClientService = bluePrintRestLibPropertyService + .blueprintWebClientService("sample") val headers = mutableMapOf<String, String>() headers["X-Transaction-Id"] = "1234" - val response = restClientService.exchangeResource(HttpMethod.GET.name, "/sample/name", "") + val response = restClientService.exchangeResource(HttpMethod.GET.name, + "/sample/name", "") assertNotNull(response, "failed to get response") } @Test - fun testPatch() { - val restClientService = bluePrintRestLibPropertyService.blueprintWebClientService("sample") - val response = restClientService.exchangeResource(HttpMethod.PATCH.name, "/sample/name", "") - assertEquals("Patch request successful", response, "failed to get patch response") + fun testSimpleBasicAuth() { + val json: String = "{\n" + + " \"type\" : \"basic-auth\",\n" + + " \"url\" : \"http://localhost:8080\",\n" + + " \"username\" : \"admin\",\n" + + " \"password\" : \"jans\"\n" + + "}" + val mapper = ObjectMapper() + val actualObj: JsonNode = mapper.readTree(json) + val restClientService = bluePrintRestLibPropertyService + .blueprintWebClientService(actualObj) + lateinit var res:String + runBlocking { + val get = async(start = CoroutineStart.LAZY) { + restClientService.exchangeNB(HttpMethod.GET.name, + "/sample/basic", "")} + get.start() + res = get.await() + } + assertNotNull(res, "failed to get response") + assertEquals(res, "Basic request arrived successfully") } + @Test + fun testSampleAaiReq() { + val restClientService = bluePrintRestLibPropertyService + .blueprintWebClientService("test") + val headers = mutableMapOf<String, String>() + headers["X-TransactionId"] = "9999" + headers["X-FromAppId"] = "AAI" + val post1 = "{\n" + + " \"customer\": {\n" + + " \"global-customer-id\": \"ONSDEMOBJHKCustomer\",\n" + + " \"subscriber-name\": \"ONSDEMOBJHKCustomer\",\n" + + " \"subscriber-type\": \"CUST\",\n" + + " \"resource-version\": \"1552985011163\"\n" + + " }\n" + + "}" + lateinit var res1: Customer + lateinit var res2: Customer + lateinit var res3: String + lateinit var res4: String + lateinit var res5: String + lateinit var res6: String + runBlocking { + val get1 = async(start = CoroutineStart.LAZY) { + restClientService.exchangeNB(HttpMethod.GET.name, + "/sample/aai/v14/business/customers", "", headers, + Customer::class.java)} + + val get2 = async(start = CoroutineStart.LAZY) { + restClientService.exchangeNB(HttpMethod.GET.name, + "/sample/aai/v14/business/customers", "", headers, + Customer::class.java)} + + val post = async(start = CoroutineStart.LAZY) { + restClientService.exchangeNB(HttpMethod.POST.name, + "/sample/aai/v14/business/customers", post1, headers, + String::class.java)} + + val put = async(start = CoroutineStart.LAZY) { + restClientService.exchangeNB(HttpMethod.PUT.name, + "/sample/aai/v14/business/customers", post1, headers, + String::class.java)} + + val patch = async(start = CoroutineStart.LAZY) { + restClientService.exchangeNB(HttpMethod.PATCH.name, + "/sample/aai/v14/business/customers", post1, headers, + String::class.java)} + + val delete = async(start = CoroutineStart.LAZY) { + restClientService.exchangeNB(HttpMethod.DELETE.name, + "/sample/aai/v14/business/customers", "", headers, + String::class.java)} + + get1.start() + get2.start() + post.start() + put.start() + patch.start() + delete.start() + res1 = get1.await() + res2 = get2.await() + res3 = post.await() + res4 = put.await() + res5 = patch.await() + res6 = delete.await() + } + assertNotNull(res1, "failed to get response") + assertNotNull(res2, "failed to get response") + assertEquals(res1.id, "ONSDEMOBJHKCustomer") + assertEquals(res1.name, "ONSDEMOBJHKCustomer") + assertEquals(res1.type, "CUST") + assertEquals(res1.resource, "1552985011163") + assertEquals(res2.id, "ONSDEMOBJHKCustomer") + assertEquals(res2.name, "ONSDEMOBJHKCustomer") + assertEquals(res2.type, "CUST") + assertEquals(res2.resource, "1552985011163") + assertEquals(res3, "The message is successfully posted") + assertEquals(res4, "The put request is success") + assertEquals(res5, "The patch request is success") + assertEquals(res6, "The message is successfully deleted") + } } +/** + * Sample controller code for testing both http and https requests. + */ @RestController @RequestMapping("/sample") open class SampleController { + @GetMapping("/name") fun getName(): String = "Sample Controller" + @PatchMapping("/name") fun patchName(): String = "Patch request successful" + + @GetMapping("/basic") + fun getBasic(): String = "Basic request arrived successfully" + + + @GetMapping("/aai/v14/business/customers") + fun getAaiCustomers( + @RequestHeader(name = "X-TransactionId", required = true) + transId: String, + @RequestHeader(name = "X-FromAppId", required = true) + appId: String) : String { + if (transId != "9999" || appId != "AAI") { + return "" + } + return "{\n" + + " \"id\": \"ONSDEMOBJHKCustomer\",\n" + + " \"name\": \"ONSDEMOBJHKCustomer\",\n" + + " \"type\": \"CUST\",\n" + + " \"resource\": \"1552985011163\"\n" + + "}" + } + + @PostMapping("/aai/v14/business/customers") + fun postAaiCustomers( + @RequestHeader(name = "X-TransactionId", required = true) + transId: String, + @RequestHeader(name = "X-FromAppId", required = true) + appId: String) : String { + if (transId != "9999" || appId != "AAI") { + return "" + } + return "The message is successfully posted" + } + + + @PutMapping("/aai/v14/business/customers") + fun putAaiCustomers( + @RequestHeader(name = "X-TransactionId", required = true) + transId: String, + @RequestHeader(name = "X-FromAppId", required = true) + appId: String) : String { + if (transId != "9999" || appId != "AAI") { + return "" + } + return "The put request is success" + } + + @PatchMapping("/aai/v14/business/customers") + fun patchAaiCustomers( + @RequestHeader(name = "X-TransactionId", required = true) + transId: String, + @RequestHeader(name = "X-FromAppId", required = true) + appId: String) : String { + if (transId != "9999" || appId != "AAI") { + return "" + } + return "The patch request is success" + } + + @DeleteMapping("/aai/v14/business/customers") + fun deleteAaiCustomers( + @RequestHeader(name = "X-TransactionId", required = true) + transId: String, + @RequestHeader(name = "X-FromAppId", required = true) + appId: String) : String { + if (transId != "9999" || appId != "AAI") { + return "" + } + return "The message is successfully deleted" + } } +/** + * Security configuration required for basic authentication with username and + * password for any request in the server. + */ +@Configuration +@EnableWebSecurity +open class SecurityConfig : WebSecurityConfigurerAdapter() { + + @Throws(Exception::class) + override fun configure(http: HttpSecurity) { + http + .csrf().disable() + .authorizeRequests().anyRequest().authenticated() + .and() + .httpBasic() + } + + @Autowired + @Throws(Exception::class) + open fun configureGlobal(auth: AuthenticationManagerBuilder) { + auth.inMemoryAuthentication() + .withUser("admin") + .password(passwordEncoder().encode("jans")) + .roles("USER") + } + + @Bean + open fun passwordEncoder(): PasswordEncoder { + return BCryptPasswordEncoder() + } +} + +/** + * Http server required for http request to be processed along with the https + * server. + */ +@Component +class HttpServer { + @Bean + fun servletContainer(): ServletWebServerFactory { + + val connector = Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL) + connector.setPort(8080) + + val tomcat = TomcatServletWebServerFactory() + tomcat.addAdditionalTomcatConnectors(connector) + return tomcat + } +} + +/** + * Data class required for response + */ +data class Customer( + val id: String, + val name: String, + val type: String, + val resource: String)
\ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/resources/keystore.p12 b/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/resources/keystore.p12 Binary files differnew file mode 100644 index 000000000..96b0d3ac3 --- /dev/null +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/resources/keystore.p12 diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandler.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandler.kt index 274346917..1e09bee8d 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandler.kt @@ -62,7 +62,7 @@ class ExecutionServiceHandler(private val bluePrintPathConfiguration: BluePrintP return bluePrintCatalogService.saveToDatabase(saveId, compressedFile, true) } catch (e: IOException) { throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value, - "Error in Upload CBA: ${e.message}", e) + "Error in Upload CBA: ${e.message}", e) } finally { deleteNBDir(blueprintArchive) deleteNBDir(blueprintWorking) @@ -90,41 +90,42 @@ class ExecutionServiceHandler(private val bluePrintPathConfiguration: BluePrintP responseObserver.onCompleted() } else -> responseObserver.onNext(response(executionServiceInput, - "Failed to process request, 'actionIdentifiers.mode' not specified. Valid value are: 'sync' or 'async'.", - true).toProto()); + "Failed to process request, 'actionIdentifiers.mode' not specified. Valid value are: 'sync' or 'async'.", + true).toProto()); } } suspend fun doProcess(executionServiceInput: ExecutionServiceInput): ExecutionServiceOutput { val requestId = executionServiceInput.commonHeader.requestId log.info("processing request id $requestId") - val actionIdentifiers = executionServiceInput.actionIdentifiers - val blueprintName = actionIdentifiers.blueprintName val blueprintVersion = actionIdentifiers.blueprintVersion + try { + val basePath = bluePrintCatalogService.getFromDatabase(blueprintName, blueprintVersion) + log.info("blueprint base path $basePath") - val basePath = bluePrintCatalogService.getFromDatabase(blueprintName, blueprintVersion) - log.info("blueprint base path $basePath") - - val blueprintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(requestId, basePath.toString()) + val blueprintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(requestId, basePath.toString()) - val output = bluePrintWorkflowExecutionService.executeBluePrintWorkflow(blueprintRuntimeService, + val output = bluePrintWorkflowExecutionService.executeBluePrintWorkflow(blueprintRuntimeService, executionServiceInput, hashMapOf()) - val errors = blueprintRuntimeService.getBluePrintError().errors - if (errors.isNotEmpty()) { - val errorMessage = errors.stream().map { it.toString() }.collect(Collectors.joining(", ")) - setErrorStatus(errorMessage, output.status) + val errors = blueprintRuntimeService.getBluePrintError().errors + if (errors.isNotEmpty()) { + val errorMessage = errors.stream().map { it.toString() }.collect(Collectors.joining(", ")) + setErrorStatus(errorMessage, output.status) + } + return output + } catch (e: Exception) { + log.error("fail processing request id $requestId", e) + return response(executionServiceInput, e.localizedMessage, true) } - - return output } private suspend fun copyFromFilePart(filePart: FilePart, targetFile: File): File { return filePart.transferTo(targetFile) - .thenReturn(targetFile) - .awaitSingle() + .thenReturn(targetFile) + .awaitSingle() } private fun setErrorStatus(errorMessage: String, status: Status) { @@ -139,10 +140,10 @@ class ExecutionServiceHandler(private val bluePrintPathConfiguration: BluePrintP val executionServiceOutput = ExecutionServiceOutput() executionServiceOutput.commonHeader = executionServiceInput.commonHeader executionServiceOutput.actionIdentifiers = executionServiceInput.actionIdentifiers - executionServiceOutput.payload = JsonNodeFactory.instance.objectNode() val status = Status() if (failure) { + executionServiceOutput.payload = JsonNodeFactory.instance.objectNode() setErrorStatus(errorMessage, status) } else { status.eventType = EventType.EVENT_COMPONENT_PROCESSING.name diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt index e78e87523..14feb28bf 100644 --- a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt @@ -22,6 +22,7 @@ import com.fasterxml.jackson.databind.JsonNode import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutput import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.Status +import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.asObjectNode @@ -97,7 +98,7 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic log.info("Preparing Response...") executionServiceOutput.commonHeader = executionServiceInput.commonHeader executionServiceOutput.actionIdentifiers = executionServiceInput.actionIdentifiers - var status: Status? + var status = Status() try { // Resolve the Output Expression val stepOutputs = bluePrintRuntimeService @@ -105,12 +106,12 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic bluePrintRuntimeService.put("$stepName-step-outputs", stepOutputs.asObjectNode()) // Set the Default Step Status - status = Status() + status.eventType = EventType.EVENT_COMPONENT_EXECUTED.name } catch (e: Exception) { - status = Status() status.message = BluePrintConstants.STATUS_FAILURE + status.eventType = EventType.EVENT_COMPONENT_FAILURE.name } - executionServiceOutput.status = status!! + executionServiceOutput.status = status return this.executionServiceOutput } |