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(
46 BlueprintRestLibConfiguration::class, BlueprintPropertyConfiguration::class,
47 BlueprintPropertiesService::class
53 "blueprintsprocessor.restclient.sample.type=basic-auth",
54 "blueprintsprocessor.restclient.sample.url=http://localhost:8080",
55 "blueprintsprocessor.restclient.sample.userId=sampleuser",
56 "blueprintsprocessor.restclient.sslbasic.type=ssl-basic-auth",
57 "blueprintsprocessor.restclient.sslbasic.url=https://localhost:8443",
58 "blueprintsprocessor.restclient.sslbasic.username=admin",
59 "blueprintsprocessor.restclient.sslbasic.password=cds",
60 "blueprintsprocessor.restclient.sslbasic.keyStoreInstance=PKCS12",
61 "blueprintsprocessor.restclient.sslbasic.sslTrust=src/test/resources/keystore.p12",
62 "blueprintsprocessor.restclient.sslbasic.sslTrustPassword=changeit",
63 "blueprintsprocessor.restclient.ssltoken.type=ssl-token-auth",
64 "blueprintsprocessor.restclient.ssltoken.url=https://localhost:8443",
65 "blueprintsprocessor.restclient.ssltoken.token=72178473kjshdkjgvbsdkjv903274908",
66 "blueprintsprocessor.restclient.ssltoken.keyStoreInstance=PKCS12",
67 "blueprintsprocessor.restclient.ssltoken.sslTrust=src/test/resources/keystore.p12",
68 "blueprintsprocessor.restclient.ssltoken.sslTrustPassword=changeit",
69 "blueprintsprocessor.restclient.ssl.type=ssl-no-auth",
70 "blueprintsprocessor.restclient.ssl.url=https://localhost:8443",
71 "blueprintsprocessor.restclient.ssl.keyStoreInstance=PKCS12",
72 "blueprintsprocessor.restclient.ssl.sslTrust=src/test/resources/keystore.p12",
73 "blueprintsprocessor.restclient.ssl.sslTrustPassword=changeit",
74 "blueprintsprocessor.restclient.ssl.sslKey=src/test/resources/keystore.p12",
75 "blueprintsprocessor.restclient.ssl.sslKeyPassword=changeit"
78 class BlueprintRestLibPropertyServiceTest {
81 lateinit var bluePrintRestLibPropertyService: BlueprintRestLibPropertyService
84 fun testRestClientProperties() {
85 val properties = bluePrintRestLibPropertyService.restClientProperties(
86 "blueprintsprocessor.restclient.sample"
88 assertNotNull(properties, "failed to create property bean")
91 "failed to get url property in" +
97 fun testSSLBasicProperties() {
98 val properties = bluePrintRestLibPropertyService.restClientProperties(
99 "blueprintsprocessor.restclient.sslbasic"
101 assertNotNull(properties, "failed to create property bean")
102 val p: SSLBasicAuthRestClientProperties =
103 properties as SSLBasicAuthRestClientProperties
105 assertEquals(p.username, "admin")
106 assertEquals(p.password, "cds")
107 assertEquals(p.sslTrust, "src/test/resources/keystore.p12")
108 assertEquals(p.sslTrustPassword, "changeit")
109 assertEquals(p.keyStoreInstance, "PKCS12")
113 fun testSSLTokenProperties() {
114 val properties = bluePrintRestLibPropertyService.restClientProperties(
115 "blueprintsprocessor.restclient.ssltoken"
117 assertNotNull(properties, "failed to create property bean")
119 val p: SSLTokenAuthRestClientProperties =
120 properties as SSLTokenAuthRestClientProperties
122 assertEquals(p.tokenAuth!!.token!!, "72178473kjshdkjgvbsdkjv903274908")
123 assertEquals(p.sslTrust, "src/test/resources/keystore.p12")
124 assertEquals(p.sslTrustPassword, "changeit")
125 assertEquals(p.keyStoreInstance, "PKCS12")
129 fun testSSLNoAuthProperties() {
130 val properties = bluePrintRestLibPropertyService.restClientProperties(
131 "blueprintsprocessor.restclient.ssl"
133 assertNotNull(properties, "failed to create property bean")
135 val p: SSLRestClientProperties =
136 properties as SSLRestClientProperties
138 assertEquals(p.sslTrust, "src/test/resources/keystore.p12")
139 assertEquals(p.sslTrustPassword, "changeit")
140 assertEquals(p.keyStoreInstance, "PKCS12")
141 assertEquals(p.sslKey, "src/test/resources/keystore.p12")
142 assertEquals(p.sslKeyPassword, "changeit")
146 fun testSSLBasicPropertiesAsJson() {
147 val actualObj: JsonNode = defaultMapper.readTree(sslBasicAuthEndpointWithHeadersField())
148 val properties = bluePrintRestLibPropertyService.restClientProperties(
151 assertNotNull(properties, "failed to create property bean")
152 val p: SSLBasicAuthRestClientProperties = properties as SSLBasicAuthRestClientProperties
154 assertEquals("admin", p.username)
155 assertEquals("cds", p.password)
156 assertEquals("src/test/resources/keystore.p12", p.sslTrust)
157 assertEquals("changeit", p.sslTrustPassword)
158 assertEquals("PKCS12", p.keyStoreInstance)
159 assertEquals("ssl-basic-auth", p.type)
160 assertEquals("https://localhost:8443", p.url)
164 fun testSSLTokenPropertiesAsJson() {
165 val actualObj: JsonNode = defaultMapper.readTree(sslTokenAuthEndpointWithHeadersField())
167 bluePrintRestLibPropertyService.restClientProperties(actualObj)
168 assertNotNull(properties, "failed to create property bean")
170 val p: SSLTokenAuthRestClientProperties = properties as SSLTokenAuthRestClientProperties
172 assertEquals("72178473kjshdkjgvbsdkjv903274908", p.tokenAuth!!.token!!)
173 assertEquals("src/test/resources/keystore.p12", p.sslTrust)
174 assertEquals("changeit", p.sslTrustPassword)
175 assertEquals("PKCS12", p.keyStoreInstance)
176 assertEquals("ssl-token-auth", p.type)
177 assertEquals("https://localhost:8443", p.url)
181 fun testSSLNoAuthPropertiesAsJson() {
182 val actualObj: JsonNode = defaultMapper.readTree(sslNoAuthEndpointWithHeadersField())
183 val properties = bluePrintRestLibPropertyService.restClientProperties(
186 assertNotNull(properties, "failed to create property bean")
188 val p: SSLRestClientProperties =
189 properties as SSLRestClientProperties
191 assertEquals("src/test/resources/keystore.p12", p.sslTrust)
192 assertEquals("changeit", p.sslTrustPassword)
193 assertEquals("PKCS12", p.keyStoreInstance)
194 assertEquals("src/test/resources/keystore.p12", p.sslKey)
195 assertEquals("changeit", p.sslKeyPassword)
196 assertEquals("ssl-no-auth", p.type)
197 assertEquals("https://localhost:8443", p.url)
201 fun testBlueprintWebClientService() {
202 val blueprintWebClientService = bluePrintRestLibPropertyService
203 .blueprintWebClientService("sample")
205 blueprintWebClientService,
206 "failed to create blueprintWebClientService"
211 fun testBlueprintWebClientServiceWithJsonNode() {
212 val actualObj: JsonNode = defaultMapper.readTree(sslBasicAuthEndpointWithHeadersField())
213 val blueprintWebClientService = bluePrintRestLibPropertyService
214 .blueprintWebClientService(actualObj)
215 assertNotNull(blueprintWebClientService, "failed to create blueprintWebClientService")
218 // pass the result of $typeEndpointWithHeadersField() output with and without headers to compare.
219 private fun validateHeadersDidNotChangeWithEmptyAdditionalHeaders(noHeaders: String, withHeaders: String) {
220 val parsedObj: JsonNode = defaultMapper.readTree(noHeaders)
221 val bpWebClientService =
222 bluePrintRestLibPropertyService.blueprintWebClientService(parsedObj)
223 val extractedHeaders = bpWebClientService.convertToBasicHeaders(mapOf())
225 val parsedObjWithHeaders: JsonNode = defaultMapper.readTree(withHeaders)
226 val bpWebClientServiceWithHeaders =
227 bluePrintRestLibPropertyService.blueprintWebClientService(parsedObjWithHeaders)
228 val extractedHeadersWithAdditionalHeaders = bpWebClientServiceWithHeaders.convertToBasicHeaders(mapOf())
229 // Array<BasicHeader<>> -> Map<String,String>
230 val headersMap = extractedHeaders.map { it.name to it.value }.toMap()
231 val additionalHeadersMap = extractedHeadersWithAdditionalHeaders.map { it.name to it.value }.toMap()
232 assertEquals(headersMap, additionalHeadersMap)
236 fun `BasicAuth WebClientService with empty additionalHeaders does not modify headers`() {
237 val endPointJson = basicAuthEndpointWithHeadersField()
238 val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(emptyAdditionalHeaders)
239 validateHeadersDidNotChangeWithEmptyAdditionalHeaders(endPointJson, endPointWithHeadersJson)
242 private fun acceptsOneAdditionalHeadersTest(endPointWithHeadersJson: String) {
243 val parsedObj: JsonNode = defaultMapper.readTree(endPointWithHeadersJson)
244 val bpWebClientService =
245 bluePrintRestLibPropertyService.blueprintWebClientService(parsedObj)
246 val extractedHeaders = bpWebClientService.convertToBasicHeaders(mapOf())
247 assertEquals(1, extractedHeaders.filter { it.name == "key1" }.count())
251 fun `BasicAuth WebClientService accepts one additionalHeaders`() {
252 val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(oneAdditionalParameter)
253 acceptsOneAdditionalHeadersTest(endPointWithHeadersJson)
256 private fun acceptsMultipleAdditionalHeaders(endPointWithHeadersJson: String) {
257 val parsedObj: JsonNode = defaultMapper.readTree(endPointWithHeadersJson)
258 val bpWebClientService =
259 bluePrintRestLibPropertyService.blueprintWebClientService(parsedObj)
260 val extractedHeaders = bpWebClientService.convertToBasicHeaders(mapOf())
261 assertEquals(1, extractedHeaders.filter { it.name == "key1" }.count())
262 assertEquals(1, extractedHeaders.filter { it.name == "key2" }.count())
263 assertEquals(1, extractedHeaders.filter { it.name == "key3" }.count())
267 fun `BasicAuth WebClientService accepts multiple additionalHeaders`() {
268 val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(threeAdditionalHeaders)
269 acceptsMultipleAdditionalHeaders(endPointWithHeadersJson)
272 private fun additionalHeadersChangedContentTypeToAPPLICATION_XML(endPointWithHeadersJson: String) {
273 val parsedObj: JsonNode = defaultMapper.readTree(endPointWithHeadersJson)
274 val bpWebClientService =
275 bluePrintRestLibPropertyService.blueprintWebClientService(parsedObj)
276 val extractedHeaders = bpWebClientService.convertToBasicHeaders(mapOf())
278 MediaType.APPLICATION_XML.toString(),
279 extractedHeaders.filter { it.name == HttpHeaders.CONTENT_TYPE }[0].value!!
284 fun `BasicAuth WebClientService additionalHeaders can overwrite default Content-Type`() {
285 // default content type is application/json
286 val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(contentTypeAdditionalHeader)
287 additionalHeadersChangedContentTypeToAPPLICATION_XML(endPointWithHeadersJson)
290 // called from within "assertFailsWith(exceptionClass = BlueprintProcessorException::class) {"
291 private fun attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson: String) {
292 val parsedObj: JsonNode = defaultMapper.readTree(endPointWithHeadersJson)
293 val bpWebClientService =
294 bluePrintRestLibPropertyService.blueprintWebClientService(parsedObj)
295 bpWebClientService.convertToBasicHeaders(mapOf())
299 fun `BasicAuth WebClientService throws BlueprintProcessorException if additionalHeaders contain Authorization`() {
300 assertFailsWith(exceptionClass = BlueprintProcessorException::class) {
301 val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(additionalHeadersWithAuth)
302 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
304 // spec says headers are case insensitive...
305 assertFailsWith(exceptionClass = BlueprintProcessorException::class) {
306 val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(additionalHeadersWithAuthLowercased)
307 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
312 fun `TokenAuth WebClientService with empty additionalHeaders does not modify headers`() {
313 val endPointJson = sslTokenAuthEndpointWithHeadersField()
314 val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(emptyAdditionalHeaders)
315 validateHeadersDidNotChangeWithEmptyAdditionalHeaders(endPointJson, endPointWithHeadersJson)
319 fun `TokenAuth WebClientService accepts one additionalHeaders`() {
320 val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(oneAdditionalParameter)
321 acceptsOneAdditionalHeadersTest(endPointWithHeadersJson)
325 fun `TokenAuth WebClientService accepts multiple additionalHeaders`() {
326 val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(threeAdditionalHeaders)
327 acceptsMultipleAdditionalHeaders(endPointWithHeadersJson)
331 fun `TokenAuth WebClientService additionalHeaders can overwrite default Content-Type`() {
332 // default content type is application/json
333 val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(contentTypeAdditionalHeader)
334 additionalHeadersChangedContentTypeToAPPLICATION_XML(endPointWithHeadersJson)
338 fun `TokenAuth WebClientService throws BlueprintProcessorException if additionalHeaders contain Authorization`() {
339 assertFailsWith(exceptionClass = BlueprintProcessorException::class) {
340 val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(additionalHeadersWithAuth)
341 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
343 // spec says headers are case insensitive...
344 assertFailsWith(exceptionClass = BlueprintProcessorException::class) {
345 val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(additionalHeadersWithAuthLowercased)
346 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
350 // TESTS FOR SSL BASIC AUTH headers
352 fun `SSLBasicAuth WebClientService with empty additionalHeaders does not modify headers`() {
353 val endPointJson = sslBasicAuthEndpointWithHeadersField()
354 val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(emptyAdditionalHeaders)
355 validateHeadersDidNotChangeWithEmptyAdditionalHeaders(endPointJson, endPointWithHeadersJson)
359 fun `SSLBasicAuth WebClientService accepts one additionalHeaders`() {
360 val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(oneAdditionalParameter)
361 acceptsOneAdditionalHeadersTest(endPointWithHeadersJson)
365 fun `SSLBasicAuth WebClientService accepts multiple additionalHeaders`() {
366 val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(threeAdditionalHeaders)
367 acceptsMultipleAdditionalHeaders(endPointWithHeadersJson)
371 fun `SSLBasicAuth WebClientService additionalHeaders can overwrite default Content-Type`() {
372 // default content type is application/json
373 val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(contentTypeAdditionalHeader)
374 additionalHeadersChangedContentTypeToAPPLICATION_XML(endPointWithHeadersJson)
378 fun `SSLBasicAuth WebClientService throws BlueprintProcessorException if additionalHeaders contain Authorization`() {
379 assertFailsWith(exceptionClass = BlueprintProcessorException::class) {
380 val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(additionalHeadersWithAuth)
381 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
383 // spec says headers are case insensitive...
384 assertFailsWith(exceptionClass = BlueprintProcessorException::class) {
385 val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(additionalHeadersWithAuthLowercased)
386 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
390 // SSL-NO-AUTH headers tests
392 fun `SSLNoAuth WebClientService with empty additionalHeaders does not modify headers`() {
393 val endPointJson = sslNoAuthEndpointWithHeadersField()
394 val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(emptyAdditionalHeaders)
395 validateHeadersDidNotChangeWithEmptyAdditionalHeaders(endPointJson, endPointWithHeadersJson)
399 fun `SSLNoAuth WebClientService accepts one additionalHeaders`() {
400 val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(oneAdditionalParameter)
401 acceptsOneAdditionalHeadersTest(endPointWithHeadersJson)
405 fun `SSLNoAuth WebClientService accepts multiple additionalHeaders`() {
406 val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(threeAdditionalHeaders)
407 acceptsMultipleAdditionalHeaders(endPointWithHeadersJson)
411 fun `SSLNoAuth WebClientService additionalHeaders can overwrite default Content-Type`() {
412 // default content type is application/json
413 val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(contentTypeAdditionalHeader)
414 additionalHeadersChangedContentTypeToAPPLICATION_XML(endPointWithHeadersJson)
418 fun `SSLNoAuth WebClientService throws BlueprintProcessorException if additionalHeaders contain Authorization`() {
419 assertFailsWith(exceptionClass = BlueprintProcessorException::class) {
420 val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(additionalHeadersWithAuth)
421 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
423 // spec says headers are case insensitive...
424 assertFailsWith(exceptionClass = BlueprintProcessorException::class) {
425 val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(additionalHeadersWithAuthLowercased)
426 attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
430 companion object BlueprintRestLibPropertyServiceTest {
432 val defaultMapper = ObjectMapper()
433 val expectedTokenAuthDefaultHeaders = mapOf<String, String>(
434 "Content-Type" to "application/json",
435 "Accept" to "application/json",
436 "Authorization" to "72178473kjshdkjgvbsdkjv903274908"
439 val endPointWithHeadersJsonWithBasicAuthHeader = basicAuthEndpointWithHeadersField(
441 "additionalHeaders" : {
442 "authorization": "Basic aGF2ZTphbmljZWRheQo="
447 private fun sslTokenAuthEndpointWithHeadersField(headers: String = ""): String =
449 "type" : "ssl-token-auth",
450 "url" : "https://localhost:8443",
451 "keyStoreInstance" : "PKCS12",
452 "sslTrust" : "src/test/resources/keystore.p12",
453 "sslTrustPassword" : "changeit",
455 "token" : "72178473kjshdkjgvbsdkjv903274908"
460 private fun sslBasicAuthEndpointWithHeadersField(headers: String = ""): String =
462 "type" : "ssl-basic-auth",
463 "url" : "https://localhost:8443",
464 "keyStoreInstance" : "PKCS12",
465 "sslTrust" : "src/test/resources/keystore.p12",
466 "sslTrustPassword" : "changeit",
467 "username" : "admin",
468 "password" : "cds"$headers
472 private fun sslNoAuthEndpointWithHeadersField(headers: String = ""): String = """{
473 "type" : "ssl-no-auth",
474 "url" : "https://localhost:8443",
475 "keyStoreInstance" : "PKCS12",
476 "sslTrust" : "src/test/resources/keystore.p12",
477 "sslTrustPassword" : "changeit",
478 "sslKey" : "src/test/resources/keystore.p12",
479 "sslKeyPassword" : "changeit"$headers
483 // Don't forget to supply "," as the first char to make valid JSON
484 private fun basicAuthEndpointWithHeadersField(headers: String = ""): String =
486 "type": "basic-auth",
487 "url": "http://127.0.0.1:8000",
489 "password": "pass"$headers
493 private val emptyAdditionalHeaders = """,
494 "additionalHeaders" : {
498 private val oneAdditionalParameter = """,
499 "additionalHeaders" : {
504 private val threeAdditionalHeaders = """,
505 "additionalHeaders" : {
512 private val contentTypeAdditionalHeader = """,
513 "additionalHeaders" : {
514 "${HttpHeaders.CONTENT_TYPE}": "${MediaType.APPLICATION_XML}"
518 private val additionalHeadersWithAuth = """,
519 "additionalHeaders" : {
520 "Authorization": "Basic aGF2ZTphbmljZWRheQo="
524 private val additionalHeadersWithAuthLowercased = """,
525 "additionalHeaders" : {
526 "authorization": "Basic aGF2ZTphbmljZWRheQo="