2 * Copyright © 2017-2018 AT&T Intellectual Property.
3 * Modifications Copyright © 2018 IBM.
4 * Modifications Copyright © 2019 Huawei.
5 * Modifications Copyright © 2019 Bell Canada.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 package org.onap.ccsdk.cds.blueprintsprocessor.rest.service
22 import com.fasterxml.jackson.databind.JsonNode
23 import com.fasterxml.jackson.databind.ObjectMapper
25 import org.junit.runner.RunWith
26 import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertiesService
27 import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertyConfiguration
28 import org.onap.ccsdk.cds.blueprintsprocessor.rest.BluePrintRestLibConfiguration
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.controllerblueprints.core.BluePrintProcessorException
33 import org.springframework.beans.factory.annotation.Autowired
34 import org.springframework.http.HttpHeaders
35 import org.springframework.http.MediaType
36 import org.springframework.test.context.ContextConfiguration
37 import org.springframework.test.context.TestPropertySource
38 import org.springframework.test.context.junit4.SpringRunner
39 import kotlin.test.assertEquals
40 import kotlin.test.assertFailsWith
41 import kotlin.test.assertNotNull
43 @RunWith(SpringRunner::class)
44 @ContextConfiguration(
45 classes = [BluePrintRestLibConfiguration::class, BluePrintPropertyConfiguration::class,
46 BluePrintPropertiesService::class]
50 ["blueprintsprocessor.restclient.sample.type=basic-auth",
51 "blueprintsprocessor.restclient.sample.url=http://localhost:8080",
52 "blueprintsprocessor.restclient.sample.userId=sampleuser",
53 "blueprintsprocessor.restclient.sslbasic.type=ssl-basic-auth",
54 "blueprintsprocessor.restclient.sslbasic.url=https://localhost:8443",
55 "blueprintsprocessor.restclient.sslbasic.username=admin",
56 "blueprintsprocessor.restclient.sslbasic.password=cds",
57 "blueprintsprocessor.restclient.sslbasic.keyStoreInstance=PKCS12",
58 "blueprintsprocessor.restclient.sslbasic.sslTrust=src/test/resources/keystore.p12",
59 "blueprintsprocessor.restclient.sslbasic.sslTrustPassword=changeit",
60 "blueprintsprocessor.restclient.ssltoken.type=ssl-token-auth",
61 "blueprintsprocessor.restclient.ssltoken.url=https://localhost:8443",
62 "blueprintsprocessor.restclient.ssltoken.token=72178473kjshdkjgvbsdkjv903274908",
63 "blueprintsprocessor.restclient.ssltoken.keyStoreInstance=PKCS12",
64 "blueprintsprocessor.restclient.ssltoken.sslTrust=src/test/resources/keystore.p12",
65 "blueprintsprocessor.restclient.ssltoken.sslTrustPassword=changeit",
66 "blueprintsprocessor.restclient.ssl.type=ssl-no-auth",
67 "blueprintsprocessor.restclient.ssl.url=https://localhost:8443",
68 "blueprintsprocessor.restclient.ssl.keyStoreInstance=PKCS12",
69 "blueprintsprocessor.restclient.ssl.sslTrust=src/test/resources/keystore.p12",
70 "blueprintsprocessor.restclient.ssl.sslTrustPassword=changeit",
71 "blueprintsprocessor.restclient.ssl.sslKey=src/test/resources/keystore.p12",
72 "blueprintsprocessor.restclient.ssl.sslKeyPassword=changeit"
75 class BluePrintRestLibPropertyServiceTest {
78 lateinit var bluePrintRestLibPropertyService: BluePrintRestLibPropertyService
81 fun testRestClientProperties() {
82 val properties = bluePrintRestLibPropertyService.restClientProperties(
83 "blueprintsprocessor.restclient.sample"
85 assertNotNull(properties, "failed to create property bean")
87 properties.url, "failed to get url property in" +
93 fun testSSLBasicProperties() {
94 val properties = bluePrintRestLibPropertyService.restClientProperties(
95 "blueprintsprocessor.restclient.sslbasic"
97 assertNotNull(properties, "failed to create property bean")
98 val p: SSLBasicAuthRestClientProperties =
99 properties as SSLBasicAuthRestClientProperties
101 assertEquals(p.basicAuth!!.username, "admin")
102 assertEquals(p.basicAuth!!.password, "cds")
103 assertEquals(p.sslTrust, "src/test/resources/keystore.p12")
104 assertEquals(p.sslTrustPassword, "changeit")
105 assertEquals(p.keyStoreInstance, "PKCS12")
109 fun testSSLTokenProperties() {
110 val properties = bluePrintRestLibPropertyService.restClientProperties(
111 "blueprintsprocessor.restclient.ssltoken"
113 assertNotNull(properties, "failed to create property bean")
115 val p: SSLTokenAuthRestClientProperties =
116 properties as SSLTokenAuthRestClientProperties
118 assertEquals(p.tokenAuth!!.token!!, "72178473kjshdkjgvbsdkjv903274908")
119 assertEquals(p.sslTrust, "src/test/resources/keystore.p12")
120 assertEquals(p.sslTrustPassword, "changeit")
121 assertEquals(p.keyStoreInstance, "PKCS12")
125 fun testSSLNoAuthProperties() {
126 val properties = bluePrintRestLibPropertyService.restClientProperties(
127 "blueprintsprocessor.restclient.ssl"
129 assertNotNull(properties, "failed to create property bean")
131 val p: SSLRestClientProperties =
132 properties as SSLRestClientProperties
134 assertEquals(p.sslTrust, "src/test/resources/keystore.p12")
135 assertEquals(p.sslTrustPassword, "changeit")
136 assertEquals(p.keyStoreInstance, "PKCS12")
137 assertEquals(p.sslKey, "src/test/resources/keystore.p12")
138 assertEquals(p.sslKeyPassword, "changeit")
142 fun testSSLBasicPropertiesAsJson() {
143 val actualObj: JsonNode = defaultMapper.readTree(sslBasicAuthEndpointWithHeadersField())
144 val properties = bluePrintRestLibPropertyService.restClientProperties(
147 assertNotNull(properties, "failed to create property bean")
148 val p: SSLBasicAuthRestClientProperties = properties as SSLBasicAuthRestClientProperties
150 assertEquals("admin", p.basicAuth!!.username)
151 assertEquals("cds", p.basicAuth!!.password)
152 assertEquals("src/test/resources/keystore.p12", p.sslTrust)
153 assertEquals("changeit", p.sslTrustPassword)
154 assertEquals("PKCS12", p.keyStoreInstance)
155 assertEquals("ssl-basic-auth", p.type)
156 assertEquals("https://localhost:8443", p.url)
160 fun testSSLTokenPropertiesAsJson() {
161 val actualObj: JsonNode = defaultMapper.readTree(sslTokenAuthEndpointWithHeadersField())
163 bluePrintRestLibPropertyService.restClientProperties(actualObj)
164 assertNotNull(properties, "failed to create property bean")
166 val p: SSLTokenAuthRestClientProperties = properties as SSLTokenAuthRestClientProperties
168 assertEquals("72178473kjshdkjgvbsdkjv903274908", p.tokenAuth!!.token!!)
169 assertEquals("src/test/resources/keystore.p12", p.sslTrust)
170 assertEquals("changeit", p.sslTrustPassword)
171 assertEquals("PKCS12", p.keyStoreInstance)
172 assertEquals("ssl-token-auth", p.type)
173 assertEquals("https://localhost:8443", p.url)
177 fun testSSLNoAuthPropertiesAsJson() {
178 val actualObj: JsonNode = defaultMapper.readTree(sslNoAuthEndpointWithHeadersField())
179 val properties = bluePrintRestLibPropertyService.restClientProperties(
182 assertNotNull(properties, "failed to create property bean")
184 val p: SSLRestClientProperties =
185 properties as SSLRestClientProperties
187 assertEquals("src/test/resources/keystore.p12", p.sslTrust)
188 assertEquals("changeit", p.sslTrustPassword)
189 assertEquals("PKCS12", p.keyStoreInstance)
190 assertEquals("src/test/resources/keystore.p12", p.sslKey)
191 assertEquals("changeit", p.sslKeyPassword)
192 assertEquals("ssl-no-auth", p.type)
193 assertEquals("https://localhost:8443", p.url)
197 fun testBlueprintWebClientService() {
198 val blueprintWebClientService = bluePrintRestLibPropertyService
199 .blueprintWebClientService("sample")
201 blueprintWebClientService,
202 "failed to create blueprintWebClientService"
207 fun testBlueprintWebClientServiceWithJsonNode() {
208 val actualObj: JsonNode = defaultMapper.readTree(sslBasicAuthEndpointWithHeadersField())
209 val blueprintWebClientService = bluePrintRestLibPropertyService
210 .blueprintWebClientService(actualObj)
211 assertNotNull(blueprintWebClientService, "failed to create blueprintWebClientService")
214 // pass the result of $typeEndpointWithHeadersField() output with and without headers to compare.
215 private fun validateHeadersDidNotChangeWithEmptyAdditionalHeaders(noHeaders: String, withHeaders: String) {
216 val parsedObj: JsonNode = defaultMapper.readTree(noHeaders)
217 val bpWebClientService =
218 bluePrintRestLibPropertyService.blueprintWebClientService(parsedObj)
219 val extractedHeaders = bpWebClientService.convertToBasicHeaders(mapOf())
221 val parsedObjWithHeaders: JsonNode = defaultMapper.readTree(withHeaders)
222 val bpWebClientServiceWithHeaders =
223 bluePrintRestLibPropertyService.blueprintWebClientService(parsedObjWithHeaders)
224 val extractedHeadersWithAdditionalHeaders = bpWebClientServiceWithHeaders.convertToBasicHeaders(mapOf())
225 // Array<BasicHeader<>> -> Map<String,String>
226 val headersMap = extractedHeaders.map { it.name to it.value }.toMap()
227 val additionalHeadersMap = extractedHeadersWithAdditionalHeaders.map { it.name to it.value }.toMap()
228 assertEquals(headersMap, additionalHeadersMap)
232 fun `BasicAuth WebClientService with empty additionalHeaders does not modify headers`() {
233 val endPointJson = basicAuthEndpointWithHeadersField()
234 val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(emptyAdditionalHeaders)
235 validateHeadersDidNotChangeWithEmptyAdditionalHeaders(endPointJson, endPointWithHeadersJson)
238 private fun acceptsOneAdditionalHeadersTest(endPointWithHeadersJson: String) {
239 val parsedObj: JsonNode = defaultMapper.readTree(endPointWithHeadersJson)
240 val bpWebClientService =
241 bluePrintRestLibPropertyService.blueprintWebClientService(parsedObj)
242 val extractedHeaders = bpWebClientService.convertToBasicHeaders(mapOf())
243 assertEquals(1, extractedHeaders.filter { it.name == "key1" }.count())
247 fun `BasicAuth WebClientService accepts one additionalHeaders`() {
248 val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(oneAdditionalParameter)
249 acceptsOneAdditionalHeadersTest(endPointWithHeadersJson)
252 private fun acceptsMultipleAdditionalHeaders(endPointWithHeadersJson: String) {
253 val parsedObj: JsonNode = defaultMapper.readTree(endPointWithHeadersJson)
254 val bpWebClientService =
255 bluePrintRestLibPropertyService.blueprintWebClientService(parsedObj)
256 val extractedHeaders = bpWebClientService.convertToBasicHeaders(mapOf())
257 assertEquals(1, extractedHeaders.filter { it.name == "key1" }.count())
258 assertEquals(1, extractedHeaders.filter { it.name == "key2" }.count())
259 assertEquals(1, extractedHeaders.filter { it.name == "key3" }.count())
263 fun `BasicAuth WebClientService accepts multiple additionalHeaders`() {
264 val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(threeAdditionalHeaders)
265 acceptsMultipleAdditionalHeaders(endPointWithHeadersJson)
268 private fun additionalHeadersChangedContentTypeToAPPLICATION_XML(endPointWithHeadersJson: String) {
269 val parsedObj: JsonNode = defaultMapper.readTree(endPointWithHeadersJson)
270 val bpWebClientService =
271 bluePrintRestLibPropertyService.blueprintWebClientService(parsedObj)
272 val extractedHeaders = bpWebClientService.convertToBasicHeaders(mapOf())
274 MediaType.APPLICATION_XML.toString(),
275 extractedHeaders.filter { it.name == HttpHeaders.CONTENT_TYPE }[0].value!!
280 fun `BasicAuth WebClientService additionalHeaders can overwrite default Content-Type`() {
281 // default content type is application/json
282 val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(contentTypeAdditionalHeader)
283 additionalHeadersChangedContentTypeToAPPLICATION_XML(endPointWithHeadersJson)
286 // called from within "assertFailsWith(exceptionClass = BluePrintProcessorException::class) {"
287 private fun attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson: String) {
288 val parsedObj: JsonNode = defaultMapper.readTree(endPointWithHeadersJson)
289 val bpWebClientService =
290 bluePrintRestLibPropertyService.blueprintWebClientService(parsedObj)
291 bpWebClientService.convertToBasicHeaders(mapOf())
295 fun `BasicAuth WebClientService throws BlueprintProcessorException if additionalHeaders contain Authorization`() {
296 assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
297 val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(additionalHeadersWithAuth)
298 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
300 // spec says headers are case insensitive...
301 assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
302 val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(additionalHeadersWithAuthLowercased)
303 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
308 fun `TokenAuth WebClientService with empty additionalHeaders does not modify headers`() {
309 val endPointJson = sslTokenAuthEndpointWithHeadersField()
310 val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(emptyAdditionalHeaders)
311 validateHeadersDidNotChangeWithEmptyAdditionalHeaders(endPointJson, endPointWithHeadersJson)
315 fun `TokenAuth WebClientService accepts one additionalHeaders`() {
316 val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(oneAdditionalParameter)
317 acceptsOneAdditionalHeadersTest(endPointWithHeadersJson)
321 fun `TokenAuth WebClientService accepts multiple additionalHeaders`() {
322 val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(threeAdditionalHeaders)
323 acceptsMultipleAdditionalHeaders(endPointWithHeadersJson)
327 fun `TokenAuth WebClientService additionalHeaders can overwrite default Content-Type`() {
328 // default content type is application/json
329 val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(contentTypeAdditionalHeader)
330 additionalHeadersChangedContentTypeToAPPLICATION_XML(endPointWithHeadersJson)
334 fun `TokenAuth WebClientService throws BlueprintProcessorException if additionalHeaders contain Authorization`() {
335 assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
336 val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(additionalHeadersWithAuth)
337 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
339 // spec says headers are case insensitive...
340 assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
341 val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(additionalHeadersWithAuthLowercased)
342 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
346 // TESTS FOR SSL BASIC AUTH headers
348 fun `SSLBasicAuth WebClientService with empty additionalHeaders does not modify headers`() {
349 val endPointJson = sslBasicAuthEndpointWithHeadersField()
350 val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(emptyAdditionalHeaders)
351 validateHeadersDidNotChangeWithEmptyAdditionalHeaders(endPointJson, endPointWithHeadersJson)
355 fun `SSLBasicAuth WebClientService accepts one additionalHeaders`() {
356 val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(oneAdditionalParameter)
357 acceptsOneAdditionalHeadersTest(endPointWithHeadersJson)
361 fun `SSLBasicAuth WebClientService accepts multiple additionalHeaders`() {
362 val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(threeAdditionalHeaders)
363 acceptsMultipleAdditionalHeaders(endPointWithHeadersJson)
367 fun `SSLBasicAuth WebClientService additionalHeaders can overwrite default Content-Type`() {
368 // default content type is application/json
369 val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(contentTypeAdditionalHeader)
370 additionalHeadersChangedContentTypeToAPPLICATION_XML(endPointWithHeadersJson)
374 fun `SSLBasicAuth WebClientService throws BlueprintProcessorException if additionalHeaders contain Authorization`() {
375 assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
376 val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(additionalHeadersWithAuth)
377 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
379 // spec says headers are case insensitive...
380 assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
381 val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(additionalHeadersWithAuthLowercased)
382 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
386 // SSL-NO-AUTH headers tests
388 fun `SSLNoAuth WebClientService with empty additionalHeaders does not modify headers`() {
389 val endPointJson = sslNoAuthEndpointWithHeadersField()
390 val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(emptyAdditionalHeaders)
391 validateHeadersDidNotChangeWithEmptyAdditionalHeaders(endPointJson, endPointWithHeadersJson)
395 fun `SSLNoAuth WebClientService accepts one additionalHeaders`() {
396 val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(oneAdditionalParameter)
397 acceptsOneAdditionalHeadersTest(endPointWithHeadersJson)
401 fun `SSLNoAuth WebClientService accepts multiple additionalHeaders`() {
402 val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(threeAdditionalHeaders)
403 acceptsMultipleAdditionalHeaders(endPointWithHeadersJson)
407 fun `SSLNoAuth WebClientService additionalHeaders can overwrite default Content-Type`() {
408 // default content type is application/json
409 val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(contentTypeAdditionalHeader)
410 additionalHeadersChangedContentTypeToAPPLICATION_XML(endPointWithHeadersJson)
414 fun `SSLNoAuth WebClientService throws BlueprintProcessorException if additionalHeaders contain Authorization`() {
415 assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
416 val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(additionalHeadersWithAuth)
417 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
419 // spec says headers are case insensitive...
420 assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
421 val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(additionalHeadersWithAuthLowercased)
422 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
426 companion object BluePrintRestLibPropertyServiceTest {
427 val defaultMapper = ObjectMapper()
428 val expectedTokenAuthDefaultHeaders = mapOf<String, String>(
429 "Content-Type" to "application/json",
430 "Accept" to "application/json",
431 "Authorization" to "72178473kjshdkjgvbsdkjv903274908"
434 val endPointWithHeadersJsonWithBasicAuthHeader = basicAuthEndpointWithHeadersField(
436 "additionalHeaders" : {
437 "authorization": "Basic aGF2ZTphbmljZWRheQo="
441 private fun sslTokenAuthEndpointWithHeadersField(headers: String = ""): String =
443 "type" : "ssl-token-auth",
444 "url" : "https://localhost:8443",
445 "keyStoreInstance" : "PKCS12",
446 "sslTrust" : "src/test/resources/keystore.p12",
447 "sslTrustPassword" : "changeit",
449 "token" : "72178473kjshdkjgvbsdkjv903274908"
454 private fun sslBasicAuthEndpointWithHeadersField(headers: String = ""): String =
456 "type" : "ssl-basic-auth",
457 "url" : "https://localhost:8443",
458 "keyStoreInstance" : "PKCS12",
459 "sslTrust" : "src/test/resources/keystore.p12",
460 "sslTrustPassword" : "changeit",
462 "username" : "admin",
467 private fun sslNoAuthEndpointWithHeadersField(headers: String = ""): String = """{
468 "type" : "ssl-no-auth",
469 "url" : "https://localhost:8443",
470 "keyStoreInstance" : "PKCS12",
471 "sslTrust" : "src/test/resources/keystore.p12",
472 "sslTrustPassword" : "changeit",
473 "sslKey" : "src/test/resources/keystore.p12",
474 "sslKeyPassword" : "changeit"$headers
477 // Don't forget to supply "," as the first char to make valid JSON
478 private fun basicAuthEndpointWithHeadersField(headers: String = ""): String =
480 "type": "basic-auth",
481 "url": "http://127.0.0.1:8000",
483 "password": "pass"$headers
486 private val emptyAdditionalHeaders = """,
487 "additionalHeaders" : {
490 private val oneAdditionalParameter = """,
491 "additionalHeaders" : {
495 private val threeAdditionalHeaders = """,
496 "additionalHeaders" : {
502 private val contentTypeAdditionalHeader = """,
503 "additionalHeaders" : {
504 "${HttpHeaders.CONTENT_TYPE}": "${MediaType.APPLICATION_XML}"
507 private val additionalHeadersWithAuth = """,
508 "additionalHeaders" : {
509 "Authorization": "Basic aGF2ZTphbmljZWRheQo="
512 private val additionalHeadersWithAuthLowercased = """,
513 "additionalHeaders" : {
514 "authorization": "Basic aGF2ZTphbmljZWRheQo="