aboutsummaryrefslogtreecommitdiffstats
path: root/src/test/java
diff options
context:
space:
mode:
authorandrzejszukuc <andrzej.szukuc@nokia.com>2018-11-07 12:51:05 +0100
committerandrzejszukuc <andrzej.szukuc@nokia.com>2018-11-27 16:54:25 +0100
commit1afc93ddb4afc226562043822f6c5e9dc0ed4b2a (patch)
tree96f022e83da4c708b99b6d4ef1bc2ea465a526de /src/test/java
parent174e08b4c4942eaa70cea889b4819334145216b9 (diff)
TLS mutual authentication has been added.
Change-Id: I60ebe8e1b06d72413940935396cb7a56af437c0d Issue-ID: DCAEGEN2-959 Signed-off-by: ANDRZEJ SZUKUC <andrzej.szukuc@nokia.com>
Diffstat (limited to 'src/test/java')
-rw-r--r--src/test/java/org/onap/dcae/TLSTest.java138
-rw-r--r--src/test/java/org/onap/dcae/TLSTestBase.java152
-rw-r--r--src/test/java/org/onap/dcae/TestingUtilities.java57
3 files changed, 344 insertions, 3 deletions
diff --git a/src/test/java/org/onap/dcae/TLSTest.java b/src/test/java/org/onap/dcae/TLSTest.java
new file mode 100644
index 00000000..63099b7d
--- /dev/null
+++ b/src/test/java/org/onap/dcae/TLSTest.java
@@ -0,0 +1,138 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.dcaegen2.collectors.ves
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcae;
+
+import io.vavr.collection.HashMap;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.Import;
+import org.springframework.http.HttpStatus;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.when;
+import static org.onap.dcae.TLSTest.HttpsConfiguration.USERNAME;
+import static org.onap.dcae.TLSTest.HttpsConfiguration.PASSWORD;
+
+public class TLSTest extends TLSTestBase {
+
+ @Nested
+ @Import(HttpConfiguration.class)
+ class HttpTest extends TestClassBase {
+
+ @Test
+ public void shouldHttpRequestSucceed() {
+ assertEquals(HttpStatus.OK, makeHttpRequest().getStatusCode());
+ }
+
+ @Test
+ public void shouldHttpsRequestFail() {
+ assertThrows(Exception.class, this::makeHttpsRequest);
+ }
+ }
+
+ @Nested
+ @Import(HttpsConfiguration.class)
+ class HttpsTest extends TestClassBase {
+
+
+ @Test
+ public void shouldHttpsRequestWithoutBasicAuthFail() {
+ assertThrows(Exception.class, this::makeHttpsRequest);
+ }
+
+ @Test
+ public void shouldHttpsRequestWithBasicAuthSucceed() {
+ assertEquals(HttpStatus.OK, makeHttpsRequestWithBasicAuth(USERNAME, PASSWORD).getStatusCode());
+ }
+ }
+
+ @Nested
+ @Import(HttpsConfigurationWithTLSAuthentication.class)
+ class HttpsWithTLSAuthenticationTest extends TestClassBase {
+
+ @Test
+ public void shouldHttpsRequestWithoutCertificateFail() {
+ assertThrows(Exception.class, this::makeHttpsRequest);
+ }
+
+ @Test
+ public void shouldHttpsRequestWithCertificateSucceed() {
+ assertEquals(HttpStatus.OK, makeHttpsRequestWithClientCert().getStatusCode());
+ }
+ }
+
+ @Nested
+ @Import(HttpsConfigurationWithTLSAuthenticationAndBasicAuth.class)
+ class HttpsWithTLSAuthenticationAndBasicAuthTest extends TestClassBase {
+
+ @Test
+ public void shouldHttpsRequestWithoutBasicAuthFail() {
+ assertThrows(Exception.class, this::makeHttpsRequestWithClientCert);
+ }
+
+ @Test
+ public void shouldHttpsRequestWithBasicAuthSucceed() {
+ assertEquals(HttpStatus.OK, makeHttpsRequestWithClientCertAndBasicAuth(USERNAME, PASSWORD).getStatusCode());
+ }
+ }
+
+ // ApplicationSettings configurations
+ static class HttpConfiguration extends TLSTestBase.ConfigurationBase {
+ @Override
+ protected void configureSettings(ApplicationSettings settings) {
+ }
+ }
+
+ static class HttpsConfiguration extends TLSTestBase.ConfigurationBase {
+ public static final String USERNAME = "TestUser";
+ public static final String PASSWORD = "TestPassword";
+
+ @Override
+ protected void configureSettings(ApplicationSettings settings) {
+ when(settings.keystoreAlias()).thenReturn(KEYSTORE_ALIAS);
+ when(settings.keystoreFileLocation()).thenReturn(KEYSTORE.toString());
+ when(settings.keystorePasswordFileLocation()).thenReturn(KEYSTORE_PASSWORD_FILE.toString());
+ when(settings.authorizationEnabled()).thenReturn(true);
+ when(settings.validAuthorizationCredentials()).thenReturn(HashMap.of(USERNAME, PASSWORD));
+ }
+ }
+
+ static class HttpsConfigurationWithTLSAuthentication extends HttpsConfiguration {
+ @Override
+ protected void configureSettings(ApplicationSettings settings) {
+ super.configureSettings(settings);
+ when(settings.authorizationEnabled()).thenReturn(false);
+ when(settings.clientTlsAuthenticationEnabled()).thenReturn(true);
+ when(settings.truststoreFileLocation()).thenReturn(TRUSTSTORE.toString());
+ when(settings.truststorePasswordFileLocation()).thenReturn(TRUSTSTORE_PASSWORD_FILE.toString());
+ }
+ }
+
+ static class HttpsConfigurationWithTLSAuthenticationAndBasicAuth extends HttpsConfigurationWithTLSAuthentication {
+ @Override
+ protected void configureSettings(ApplicationSettings settings) {
+ super.configureSettings(settings);
+ when(settings.authorizationEnabled()).thenReturn(true);
+ }
+ }
+}
diff --git a/src/test/java/org/onap/dcae/TLSTestBase.java b/src/test/java/org/onap/dcae/TLSTestBase.java
new file mode 100644
index 00000000..8b486ec7
--- /dev/null
+++ b/src/test/java/org/onap/dcae/TLSTestBase.java
@@ -0,0 +1,152 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.dcaegen2.collectors.ves
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcae;
+
+import org.json.JSONObject;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.support.BasicAuthenticationInterceptor;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.web.client.RestTemplate;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import static org.onap.dcae.TestingUtilities.*;
+
+@Configuration
+@ExtendWith(SpringExtension.class)
+public class TLSTestBase {
+ protected static final String KEYSTORE_ALIAS = "localhost";
+ protected static final Path RESOURCES = Paths.get("src", "test", "resources");
+ protected static final Path KEYSTORE = Paths.get(RESOURCES.toString(), "keystore");
+ protected static final Path KEYSTORE_PASSWORD_FILE = Paths.get(RESOURCES.toString(), "passwordfile");
+ protected static final Path TRUSTSTORE = Paths.get(RESOURCES.toString(), "truststore");
+ protected static final Path TRUSTSTORE_PASSWORD_FILE = Paths.get(RESOURCES.toString(), "trustpasswordfile");
+
+ protected static abstract class ConfigurationBase {
+ protected final ApplicationSettings settings = Mockito.mock(ApplicationSettings.class);
+
+ @Bean
+ @Primary
+ public ApplicationSettings settings() {
+ configureSettings(settings);
+ return settings;
+ }
+
+ protected abstract void configureSettings(final ApplicationSettings settings);
+ }
+
+ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+ protected abstract class TestClassBase {
+ @MockBean
+ @Qualifier("inputQueue")
+ protected LinkedBlockingQueue<JSONObject> queue;
+
+ @LocalServerPort
+ private int port;
+
+ private final String keyStorePassword;
+ private final String trustStorePassword;
+
+ public TestClassBase() {
+ keyStorePassword = readFile(KEYSTORE_PASSWORD_FILE);
+ trustStorePassword = readFile(TRUSTSTORE_PASSWORD_FILE);
+ }
+
+ private String getURL(final String protocol, final String uri) {
+ return protocol + "://localhost:" + port + uri;
+ }
+
+ private RestTemplate addBasicAuth(final RestTemplate template, final String username, final String password) {
+ template.getInterceptors()
+ .add(new BasicAuthenticationInterceptor(username, password));
+
+ return template;
+ }
+
+ public String createHttpURL(String uri) {
+ return getURL("http", uri);
+ }
+
+ public String createHttpsURL(String uri) {
+ return getURL("https", uri);
+ }
+
+ public RestTemplate createHttpRestTemplate() {
+ return new RestTemplate();
+ }
+
+ public RestTemplate createHttpsRestTemplate() {
+ return rethrow(() ->
+ createRestTemplateWithSsl(
+ sslBuilderWithTrustStore(KEYSTORE, keyStorePassword).build()
+ ));
+ }
+
+ public RestTemplate createHttpsRestTemplateWithKeyStore() {
+ return rethrow(() ->
+ createRestTemplateWithSsl(
+ configureKeyStore(
+ sslBuilderWithTrustStore(KEYSTORE, keyStorePassword),
+ TRUSTSTORE,
+ trustStorePassword
+ ).build())
+ );
+ }
+
+ public ResponseEntity<String> makeHttpRequest() {
+ return createHttpRestTemplate().getForEntity(createHttpURL("/"), String.class);
+ }
+
+ public ResponseEntity<String> makeHttpsRequest() {
+ return createHttpsRestTemplate().getForEntity(createHttpsURL("/"), String.class);
+ }
+
+
+ public ResponseEntity<String> makeHttpsRequestWithBasicAuth(final String username, final String password) {
+ return addBasicAuth(createHttpsRestTemplate(), username, password)
+ .getForEntity(createHttpsURL("/"), String.class);
+
+ }
+
+ public ResponseEntity<String> makeHttpsRequestWithClientCert() {
+ return createHttpsRestTemplateWithKeyStore().getForEntity(createHttpsURL("/"), String.class);
+ }
+
+ public ResponseEntity<String> makeHttpsRequestWithClientCertAndBasicAuth(
+ final String username,
+ final String password) {
+ return addBasicAuth(createHttpsRestTemplateWithKeyStore(), username, password)
+ .getForEntity(createHttpsURL("/"), String.class);
+ }
+ }
+}
diff --git a/src/test/java/org/onap/dcae/TestingUtilities.java b/src/test/java/org/onap/dcae/TestingUtilities.java
index bd05c4ea..4c0d5382 100644
--- a/src/test/java/org/onap/dcae/TestingUtilities.java
+++ b/src/test/java/org/onap/dcae/TestingUtilities.java
@@ -24,13 +24,30 @@ import static java.nio.file.Files.readAllBytes;
import static org.assertj.core.api.Assertions.assertThat;
import io.vavr.control.Try;
+
import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContextBuilder;
import org.assertj.core.api.AbstractThrowableAssert;
import org.assertj.core.api.Java6Assertions;
import org.json.JSONObject;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.web.client.RestTemplate;
+
+import javax.net.ssl.SSLContext;
/**
* @author Pawel Szalapski (pawel.szalapski@nokia.com)
@@ -67,11 +84,11 @@ public final class TestingUtilities {
* Exception in test case usually means there is something wrong, it should never be catched, but rather thrown to
* be handled by JUnit framework.
*/
- private static <T> T rethrow(CheckedSupplier<T> supplier) {
+ public static <T> T rethrow(CheckedSupplier<T> supplier) {
try {
return supplier.get();
} catch (Exception e) {
- throw new RuntimeException();
+ throw new RuntimeException(e);
}
}
@@ -84,9 +101,43 @@ public final class TestingUtilities {
public static void assertFailureHasInfo(Try any, String... msgPart) {
Java6Assertions.assertThat(any.isFailure()).isTrue();
AbstractThrowableAssert<?, ? extends Throwable> o = Java6Assertions.assertThat(any.getCause())
- .hasCauseInstanceOf(Exception.class);
+ .hasCauseInstanceOf(Exception.class);
for (String s : msgPart) {
o.hasStackTraceContaining(s);
}
}
+
+ public static SSLContextBuilder sslBuilderWithTrustStore(final Path trustStore, final String pass) {
+ return rethrow(() ->
+ new SSLContextBuilder()
+ .loadTrustMaterial(trustStore.toFile(), pass.toCharArray())
+ );
+ }
+
+ public static SSLContextBuilder configureKeyStore(
+ final SSLContextBuilder builder,
+ final Path keyStore,
+ final String pass) {
+ return rethrow(() -> {
+ KeyStore cks = KeyStore.getInstance(KeyStore.getDefaultType());
+ cks.load(new FileInputStream(keyStore.toFile()), pass.toCharArray());
+
+ builder.loadKeyMaterial(cks, pass.toCharArray());
+
+ return builder;
+ });
+ }
+
+ public static RestTemplate createRestTemplateWithSsl(final SSLContext context) {
+ final SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(context);
+ final HttpClient httpClient = HttpClients
+ .custom()
+ .setSSLSocketFactory(socketFactory)
+ .build();
+
+ final HttpComponentsClientHttpRequestFactory factory =
+ new HttpComponentsClientHttpRequestFactory(httpClient);
+
+ return new RestTemplate(factory);
+ }
}