summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorPiotr Jaszczyk <piotr.jaszczyk@nokia.com>2019-02-04 14:53:57 +0100
committerPiotr Jaszczyk <piotr.jaszczyk@nokia.com>2019-02-06 09:58:53 +0100
commit6b50f21a75f76ebad011188c42b6406d7c097537 (patch)
tree804e94ade1126210092c9979ff6e3b680ecae1dc /security
parent09b68daf6b644df4dd66ab792c430898bb9d2f6d (diff)
Add support for server-side SSL context factory
Change-Id: I2fa64c71f55f1abfdeb4a2323c5456475d87fdd1 Issue-ID: DCAEGEN2-1069 Signed-off-by: Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
Diffstat (limited to 'security')
-rw-r--r--security/crypt-password/pom.xml6
-rw-r--r--security/pom.xml1
-rw-r--r--security/ssl/pom.xml8
-rw-r--r--security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/KeyStoreTypes.java61
-rw-r--r--security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/SecurityKeys.java6
-rw-r--r--security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/SecurityKeysStore.java53
-rw-r--r--security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/SslFactory.java70
-rw-r--r--security/ssl/src/test/java/org/onap/dcaegen2/services/sdk/security/ssl/KeyStoreTypesTest.java76
8 files changed, 244 insertions, 37 deletions
diff --git a/security/crypt-password/pom.xml b/security/crypt-password/pom.xml
index e7fc357d..7135e213 100644
--- a/security/crypt-password/pom.xml
+++ b/security/crypt-password/pom.xml
@@ -6,15 +6,15 @@
<parent>
<groupId>org.onap.dcaegen2.services.sdk.security</groupId>
<artifactId>dcaegen2-services-sdk-security</artifactId>
- <version>1.1.0-SNAPSHOT</version>
+ <version>1.1.2-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.onap.dcaegen2.services.sdk.security.crypt</groupId>
<artifactId>crypt-password</artifactId>
- <version>1.1.0-SNAPSHOT</version>
- <name>dcaegen2-services-sdk-security-crypt-password</name>
+ <name>Security :: Crypt Password</name>
<description>DMaaP Security Module</description>
<packaging>jar</packaging>
diff --git a/security/pom.xml b/security/pom.xml
index bf3ba379..fc298258 100644
--- a/security/pom.xml
+++ b/security/pom.xml
@@ -13,7 +13,6 @@
<groupId>org.onap.dcaegen2.services.sdk.security</groupId>
<artifactId>dcaegen2-services-sdk-security</artifactId>
- <version>1.1.0-SNAPSHOT</version>
<name>dcaegen2-services-sdk-security</name>
<description>Common SDK repo for all DCAE Security</description>
diff --git a/security/ssl/pom.xml b/security/ssl/pom.xml
index ecccd767..0100d65b 100644
--- a/security/ssl/pom.xml
+++ b/security/ssl/pom.xml
@@ -6,14 +6,14 @@
<parent>
<groupId>org.onap.dcaegen2.services.sdk.security</groupId>
<artifactId>dcaegen2-services-sdk-security</artifactId>
- <version>1.1.0-SNAPSHOT</version>
+ <version>1.1.2-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
</parent>
<artifactId>ssl</artifactId>
- <version>1.1.1-SNAPSHOT</version>
- <name>SSL</name>
- <description>Common SSL-related Classes Library</description>
+ <name>Security :: SSL</name>
+ <description>Common functionality to handle SSL/TLS in Netty-based applications</description>
<packaging>jar</packaging>
<dependencies>
diff --git a/security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/KeyStoreTypes.java b/security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/KeyStoreTypes.java
new file mode 100644
index 00000000..61e551e6
--- /dev/null
+++ b/security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/KeyStoreTypes.java
@@ -0,0 +1,61 @@
+/*
+ * ============LICENSE_START====================================
+ * DCAEGEN2-SERVICES-SDK
+ * =========================================================
+ * Copyright (C) 2019 Nokia. 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.dcaegen2.services.sdk.security.ssl;
+
+import io.vavr.collection.HashSet;
+import io.vavr.collection.Set;
+import io.vavr.control.Option;
+import java.nio.file.Path;
+
+/**
+ * @author <a href="mailto:piotr.jaszczyk@nokia.com">Piotr Jaszczyk</a>
+ * @since 1.1.1
+ */
+final class KeyStoreTypes {
+ static final String TYPE_JKS = "jks";
+ static final String TYPE_PKCS12 = "pkcs12";
+ private static final Set<String> JKS_EXTENSIONS = HashSet.of(TYPE_JKS);
+ private static final Set<String> PKCS12_EXTENSIONS = HashSet.of(TYPE_PKCS12, "p12");
+
+ private KeyStoreTypes() {}
+
+ static Option<String> inferTypeFromExtension(Path filePath) {
+ return extension(filePath.toString())
+ .flatMap(KeyStoreTypes::typeForExtension);
+ }
+
+ private static Option<String> extension(String filePath) {
+ final int dotIndex = filePath.lastIndexOf('.');
+ return dotIndex < 0 || dotIndex + 1 >= filePath.length()
+ ? Option.none()
+ : Option.of(filePath.substring(dotIndex + 1).toLowerCase());
+ }
+
+ private static Option<String> typeForExtension(String extension) {
+ if (JKS_EXTENSIONS.contains(extension)) {
+ return Option.of(TYPE_JKS);
+ } else if (PKCS12_EXTENSIONS.contains(extension)) {
+ return Option.of(TYPE_PKCS12);
+ } else {
+ return Option.none();
+ }
+ }
+}
diff --git a/security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/SecurityKeys.java b/security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/SecurityKeys.java
index 05c3c470..244e33c8 100644
--- a/security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/SecurityKeys.java
+++ b/security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/SecurityKeys.java
@@ -20,7 +20,6 @@
package org.onap.dcaegen2.services.sdk.security.ssl;
-import java.nio.file.Path;
import org.immutables.value.Value;
/**
@@ -29,9 +28,10 @@ import org.immutables.value.Value;
*/
@Value.Immutable
public interface SecurityKeys {
- Path keyStore();
+
+ SecurityKeysStore keyStore();
Password keyStorePassword();
- Path trustStore();
+ SecurityKeysStore trustStore();
Password trustStorePassword();
}
diff --git a/security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/SecurityKeysStore.java b/security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/SecurityKeysStore.java
new file mode 100644
index 00000000..0ebfc451
--- /dev/null
+++ b/security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/SecurityKeysStore.java
@@ -0,0 +1,53 @@
+/*
+ * ============LICENSE_START====================================
+ * DCAEGEN2-SERVICES-SDK
+ * =========================================================
+ * Copyright (C) 2019 Nokia. 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.dcaegen2.services.sdk.security.ssl;
+
+import java.nio.file.Path;
+import org.immutables.value.Value;
+
+/**
+ * @author <a href="mailto:piotr.jaszczyk@nokia.com">Piotr Jaszczyk</a>
+ * @since 1.1.1
+ */
+@Value.Immutable
+public interface SecurityKeysStore {
+ /**
+ * Stores the file path of the key store. It should contain data in format specified by {@link #type()}.
+ *
+ * @return key store path
+ */
+ @Value.Parameter
+ Path path();
+
+ /**
+ * Type of the key store. Can be anything supported by the JVM, eg. {@code jks} or {@code pkcs12}.
+ *
+ * If not set it will be guessed from the {@link #path()}. {@link IllegalStateException} will be thrown if it will
+ * not be possible.
+ *
+ * @return key store type
+ */
+ @Value.Default
+ default String type() {
+ return KeyStoreTypes.inferTypeFromExtension(path())
+ .getOrElseThrow(() -> new IllegalStateException("Could not determine key store type by file name"));
+ }
+}
diff --git a/security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/SslFactory.java b/security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/SslFactory.java
index 15739eb6..1f3f4cfd 100644
--- a/security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/SslFactory.java
+++ b/security/ssl/src/main/java/org/onap/dcaegen2/services/sdk/security/ssl/SslFactory.java
@@ -36,54 +36,72 @@ import javax.net.ssl.TrustManagerFactory;
public class SslFactory {
/**
- * Function for creating secure ssl context.
+ * Creates Netty SSL <em>client</em> context using provided security keys.
*
* @param keys - Security keys to be used
* @return configured SSL context
*/
- public Try<SslContext> createSecureContext(final SecurityKeys keys) {
- final Try<KeyManagerFactory> keyManagerFactory =
- keyManagerFactory(keys.keyStore(), keys.keyStorePassword());
- final Try<TrustManagerFactory> trustManagerFactory =
- trustManagerFactory(keys.trustStore(), keys.trustStorePassword());
+ public Try<SslContext> createSecureClientContext(final SecurityKeys keys) {
+ return Try.success(SslContextBuilder.forClient())
+ .flatMap(ctx -> keyManagerFactory(keys).map(ctx::keyManager))
+ .flatMap(ctx -> trustManagerFactory(keys).map(ctx::trustManager))
+ .mapTry(SslContextBuilder::build);
+ }
+ /**
+ * Creates Netty SSL <em>server</em> context using provided security keys.
+ *
+ * @param keys - Security keys to be used
+ * @return configured SSL context
+ */
+ public Try<SslContext> createSecureServerContext(final SecurityKeys keys) {
+ return keyManagerFactory(keys)
+ .map(SslContextBuilder::forServer)
+ .flatMap(ctx -> trustManagerFactory(keys).map(ctx::trustManager))
+ .mapTry(SslContextBuilder::build);
+ }
+
+ /**
+ * Function for creating insecure SSL context.
+ *
+ * @return configured insecure ssl context
+ * @deprecated Do not use in production. Will trust anyone.
+ */
+ @Deprecated
+ public Try<SslContext> createInsecureClientContext() {
return Try.success(SslContextBuilder.forClient())
- .flatMap(ctx -> keyManagerFactory.map(ctx::keyManager))
- .flatMap(ctx -> trustManagerFactory.map(ctx::trustManager))
+ .map(ctx -> ctx.trustManager(InsecureTrustManagerFactory.INSTANCE))
.mapTry(SslContextBuilder::build);
}
- private Try<KeyManagerFactory> keyManagerFactory(Path path, Password password) {
+ private Try<TrustManagerFactory> trustManagerFactory(SecurityKeys keys) {
+ return trustManagerFactory(keys.trustStore(), keys.trustStorePassword());
+ }
+
+ private Try<KeyManagerFactory> keyManagerFactory(SecurityKeys keys) {
+ return keyManagerFactory(keys.keyStore(), keys.keyStorePassword());
+ }
+
+ private Try<KeyManagerFactory> keyManagerFactory(SecurityKeysStore store, Password password) {
return password.useChecked(passwordChars -> {
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
- kmf.init(loadKeyStoreFromFile(path, passwordChars), passwordChars);
+ kmf.init(loadKeyStoreFromFile(store, passwordChars), passwordChars);
return kmf;
});
}
- private Try<TrustManagerFactory> trustManagerFactory(Path path, Password password) {
+ private Try<TrustManagerFactory> trustManagerFactory(SecurityKeysStore store, Password password) {
return password.useChecked(passwordChars -> {
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
- tmf.init(loadKeyStoreFromFile(path, passwordChars));
+ tmf.init(loadKeyStoreFromFile(store, passwordChars));
return tmf;
});
}
- private KeyStore loadKeyStoreFromFile(Path path, char[] keyStorePassword)
+ private KeyStore loadKeyStoreFromFile(SecurityKeysStore store, char[] keyStorePassword)
throws GeneralSecurityException, IOException {
- KeyStore ks = KeyStore.getInstance("pkcs12");
- ks.load(Files.newInputStream(path, StandardOpenOption.READ), keyStorePassword);
+ KeyStore ks = KeyStore.getInstance(store.type());
+ ks.load(Files.newInputStream(store.path(), StandardOpenOption.READ), keyStorePassword);
return ks;
}
-
- /**
- * Function for creating insecure ssl context.
- *
- * @return configured insecure ssl context
- */
- public Try<SslContext> createInsecureContext() {
- return Try.success(SslContextBuilder.forClient())
- .map(ctx -> ctx.trustManager(InsecureTrustManagerFactory.INSTANCE))
- .mapTry(SslContextBuilder::build);
- }
}
diff --git a/security/ssl/src/test/java/org/onap/dcaegen2/services/sdk/security/ssl/KeyStoreTypesTest.java b/security/ssl/src/test/java/org/onap/dcaegen2/services/sdk/security/ssl/KeyStoreTypesTest.java
new file mode 100644
index 00000000..ab2aa773
--- /dev/null
+++ b/security/ssl/src/test/java/org/onap/dcaegen2/services/sdk/security/ssl/KeyStoreTypesTest.java
@@ -0,0 +1,76 @@
+/*
+ * ============LICENSE_START====================================
+ * DCAEGEN2-SERVICES-SDK
+ * =========================================================
+ * Copyright (C) 2019 Nokia. 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.dcaegen2.services.sdk.security.ssl;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.vavr.control.Option;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author <a href="mailto:piotr.jaszczyk@nokia.com">Piotr Jaszczyk</a>
+ * @since February 2019
+ */
+class KeyStoreTypesTest {
+
+ @Test
+ void guessType_shouldReturnExtension_forP12() {
+ final Option<String> result = callGuessTypeWithFileName("file.p12");
+ assertThat(result.get()).isEqualTo(KeyStoreTypes.TYPE_PKCS12);
+ }
+
+ @Test
+ void guessType_shouldReturnExtension_forPkcs12() {
+ final Option<String> result = callGuessTypeWithFileName("file.pkcs12");
+ assertThat(result.get()).isEqualTo(KeyStoreTypes.TYPE_PKCS12);
+ }
+
+ @Test
+ void guessType_shouldReturnExtension_forJks() {
+ final Option<String> result = callGuessTypeWithFileName("file.jks");
+ assertThat(result.get()).isEqualTo(KeyStoreTypes.TYPE_JKS);
+ }
+
+ @Test
+ void guessType_shouldReturnExtension_ignoringCase() {
+ final Option<String> result = callGuessTypeWithFileName("file.PKCS12");
+ assertThat(result.get()).isEqualTo(KeyStoreTypes.TYPE_PKCS12);
+ }
+
+ @Test
+ void guessType_shouldReturnNone_whenFileDoesNotHaveExtension() {
+ final Option<String> result = callGuessTypeWithFileName("file");
+ assertThat(result.isEmpty()).isTrue();
+ }
+
+ @Test
+ void guessType_shouldReturnNone_whenFileEndsWithDot() {
+ final Option<String> result = callGuessTypeWithFileName("file.");
+ assertThat(result.isEmpty()).isTrue();
+ }
+
+ private Option<String> callGuessTypeWithFileName(String fileName) {
+ final Path path = Paths.get("/", "tmp", fileName);
+ return KeyStoreTypes.inferTypeFromExtension(path);
+ }
+} \ No newline at end of file