From b3cce282f35ff30042a860b788a003f38393c9d3 Mon Sep 17 00:00:00 2001 From: "mark.j.leonard" Date: Wed, 23 Jan 2019 17:26:32 +0000 Subject: Make password obfuscation with Jetty optional Only deobfuscate a password value that begins with the text OBF: Issue-ID: AAI-2115 Change-Id: Ia9d733e7044b63bdba0add6b8df5d40b66decc63 Signed-off-by: mark.j.leonard --- .../validation/ValidationServiceApplication.java | 114 ++++++++++++++++----- .../org/onap/aai/validation/config/RestConfig.java | 12 +-- .../onap/aai/validation/config/TopicConfig.java | 10 +- .../org/onap/aai/validation/util/StringUtils.java | 42 ++++++-- 4 files changed, 135 insertions(+), 43 deletions(-) diff --git a/src/main/java/org/onap/aai/validation/ValidationServiceApplication.java b/src/main/java/org/onap/aai/validation/ValidationServiceApplication.java index 103c6cb..464bbf9 100644 --- a/src/main/java/org/onap/aai/validation/ValidationServiceApplication.java +++ b/src/main/java/org/onap/aai/validation/ValidationServiceApplication.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START=================================================== - * Copyright (c) 2018 Amdocs + * Copyright (c) 2018-2019 European Software Marketing Ltd. * ============================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,12 +17,12 @@ */ package org.onap.aai.validation; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import javax.annotation.PostConstruct; -import org.apache.commons.lang.StringUtils; -import org.eclipse.jetty.util.security.Password; import org.onap.aai.validation.config.TopicPropertiesConfig; +import org.onap.aai.validation.util.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; @@ -35,7 +35,6 @@ import org.springframework.core.env.Environment; /** * Validation Service Spring Boot Application. */ - @Configuration @EnableAutoConfiguration @Import(TopicPropertiesConfig.class) @@ -45,18 +44,71 @@ public class ValidationServiceApplication extends SpringBootServletInitializer { @Autowired private Environment env; - public static void main(String[] args) { - Map props = new HashMap<>(); - String keyStorePassword = System.getProperty("KEY_STORE_PASSWORD"); - if (StringUtils.isEmpty(keyStorePassword)) { - throw new IllegalArgumentException("System Property KEY_STORE_PASSWORD not set"); + private enum SystemProperty { + KEY_STORE_PASSWORD, // Mandatory password for the Application's keystore (containing the server cert) + JAVA_TRUST_STORE("javax.net.ssl.trustStore"), // JVM + JAVA_TRUST_STORE_PASSWORD("javax.net.ssl.trustStorePassword") // JVM + ; + + final private String propertyName; + + SystemProperty() { + propertyName = this.toString(); + } + + SystemProperty(String property) { + propertyName = property; + } + + public String readValue() { + String propertyValue = System.getProperty(propertyName); + if (propertyValue == null) { + throw new IllegalArgumentException("System Property " + this + " not set"); + } + return StringUtils.decrypt(propertyValue); + } + + public void set(String propertyValue) { + System.setProperty(propertyName, propertyValue); } - String deobfuscated = Password.deobfuscate(keyStorePassword); - props.put("server.ssl.key-store-password", deobfuscated); - props.put("schema.service.ssl.key-store-password", deobfuscated); - props.put("schema.service.ssl.trust-store-password", deobfuscated); - new ValidationServiceApplication() - .configure(new SpringApplicationBuilder(ValidationServiceApplication.class).properties(props)) + } + + private enum ApplicationProperty { + SERVER_SSL_KEY_STORE("server.ssl.key-store"), // Spring + SERVER_SSL_KEY_STORE_PASSWORD("server.ssl.key-store-password"), // Spring + SCHEMA_SERVICE_KEY_STORE_PASSWORD("schema.service.ssl.key-store-password"), // aai-schema-ingest + SCHEMA_SERVICE_TRUST_STORE_PASSWORD("schema.service.ssl.trust-store-password") // aai-schema-ingest + ; + + final private String propertyName; + + ApplicationProperty(String property) { + propertyName = property; + } + + public String from(Environment env) { + return env.getProperty(this.propertyName); + } + + public String mandatoryFrom(Environment env) { + String value = from(env); + if (value == null) { + throw new IllegalArgumentException("Env property " + this.propertyName + " not set"); + } + return value; + } + } + + /** + * Create and run the Application. + * + * @param args + * the command line arguments + */ + public static void main(String[] args) { + new ValidationServiceApplication() // + .configure(new SpringApplicationBuilder(ValidationServiceApplication.class) + .properties(buildEnvironmentProperties())) .run(args); } @@ -65,15 +117,31 @@ public class ValidationServiceApplication extends SpringBootServletInitializer { */ @PostConstruct public void setSystemProperties() { - String trustStorePath = env.getProperty("server.ssl.key-store"); + String trustStorePath = ApplicationProperty.SERVER_SSL_KEY_STORE.from(env); if (trustStorePath != null) { - String trustStorePassword = env.getProperty("server.ssl.key-store-password"); - if (trustStorePassword != null) { - System.setProperty("javax.net.ssl.trustStore", trustStorePath); - System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword); - } else { - throw new IllegalArgumentException("Env property server.ssl.key-store-password not set"); - } + String trustStorePassword = ApplicationProperty.SERVER_SSL_KEY_STORE_PASSWORD.mandatoryFrom(env); + SystemProperty.JAVA_TRUST_STORE.set(trustStorePath); + SystemProperty.JAVA_TRUST_STORE_PASSWORD.set(trustStorePassword); + } + } + + /** + * Create the default properties for the Spring Application's environment. + * + * @param keyStorePassword + * SSL key store password + * @return the default environment properties + */ + private static Map buildEnvironmentProperties() { + String keyStorePassword = SystemProperty.KEY_STORE_PASSWORD.readValue(); + Map props = new HashMap<>(); + for (ApplicationProperty property : Arrays.asList( // + ApplicationProperty.SERVER_SSL_KEY_STORE_PASSWORD, + ApplicationProperty.SCHEMA_SERVICE_KEY_STORE_PASSWORD, + ApplicationProperty.SCHEMA_SERVICE_TRUST_STORE_PASSWORD)) { + props.put(property.propertyName, keyStorePassword); } + return props; } + } diff --git a/src/main/java/org/onap/aai/validation/config/RestConfig.java b/src/main/java/org/onap/aai/validation/config/RestConfig.java index b192e73..511d197 100644 --- a/src/main/java/org/onap/aai/validation/config/RestConfig.java +++ b/src/main/java/org/onap/aai/validation/config/RestConfig.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START=================================================== - * Copyright (c) 2018 Amdocs + * Copyright (c) 2018-2019 European Software Marketing Ltd. * ============================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,7 @@ package org.onap.aai.validation.config; import java.util.Objects; import org.apache.commons.lang3.builder.EqualsBuilder; -import org.eclipse.jetty.util.security.Password; +import org.onap.aai.validation.util.StringUtils; import org.springframework.beans.factory.annotation.Value; /** @@ -107,12 +107,12 @@ public class RestConfig { } /** - * Assumes the password is encrypted. + * Return the plain text password, decrypting if necessary. * * @return the decrypted password */ public String getTrustStorePassword() { - return Password.deobfuscate(trustStorePassword); + return StringUtils.decrypt(trustStorePassword); } public void setTrustStorePassword(String trustStorePassword) { @@ -128,12 +128,12 @@ public class RestConfig { } /** - * Assumes the password is encrypted. + * Return the plain text password, decrypting if necessary. * * @return the decrypted password */ public String getKeyStorePassword() { - return Password.deobfuscate(keyStorePassword); + return StringUtils.decrypt(keyStorePassword); } public void setKeyStorePassword(String keyStorePassword) { diff --git a/src/main/java/org/onap/aai/validation/config/TopicConfig.java b/src/main/java/org/onap/aai/validation/config/TopicConfig.java index d769935..38d527e 100644 --- a/src/main/java/org/onap/aai/validation/config/TopicConfig.java +++ b/src/main/java/org/onap/aai/validation/config/TopicConfig.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START=================================================== - * Copyright (c) 2018 Amdocs + * Copyright (c) 2018-2019 European Software Marketing Ltd. * ============================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ import java.util.Objects; import java.util.Properties; import javax.annotation.Resource; import org.apache.commons.lang3.builder.EqualsBuilder; -import org.eclipse.jetty.util.security.Password; +import org.onap.aai.validation.util.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -74,9 +74,9 @@ public class TopicConfig { * Populates the topics list with topic objects created from each item in the topicNames list. * * @param topics - * The topic list to populate. + * The topic list to populate. * @param topicNames - * The list of topic names to populate the topic list with. + * The list of topic names to populate the topic list with. * @return The populated topic list. */ private List populateTopics(List topics, List topicNames) { @@ -160,7 +160,7 @@ public class TopicConfig { } public String getPassword() { - return Password.deobfuscate(password); + return StringUtils.decrypt(password); } public void setPassword(String password) { diff --git a/src/main/java/org/onap/aai/validation/util/StringUtils.java b/src/main/java/org/onap/aai/validation/util/StringUtils.java index d50b5bf..7a57d36 100644 --- a/src/main/java/org/onap/aai/validation/util/StringUtils.java +++ b/src/main/java/org/onap/aai/validation/util/StringUtils.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START=================================================== - * Copyright (c) 2018 Amdocs + * Copyright (c) 2018-2019 European Software Marketing Ltd. * ============================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; +import org.eclipse.jetty.util.security.Password; import org.onap.aai.cl.api.Logger; import org.onap.aai.validation.exception.ValidationServiceError; import org.onap.aai.validation.exception.ValidationServiceException; @@ -41,28 +42,49 @@ public class StringUtils { // Do not instantiate } + /** + * Deobfuscate the supplied String value if it begins with "OBF:", otherwise return the value unchanged. + * + * @param value + * a password or passphrase + * @return the deobfuscated (or original) value + */ + public static String decrypt(String value) { + if (value != null && value.startsWith(Password.__OBFUSCATE)) { + return Password.deobfuscate(value); + } else { + return value; + } + } + /** * Utility method to strip a prefix or set of prefixes (identified by a delimiter sequence) from the string. This is * achieved by finding the index of the last prefix delimiter in the string and removing all characters before and * including this index. * - * @param string the String to strip prefixes from - * @param prefixDelimiter the String that acts as the delimiter for the prefix(es) + * @param string + * the String to strip prefixes from + * @param prefixDelimiter + * the String that acts as the delimiter for the prefix(es) * @return the String minus the prefixes */ public static String stripPrefix(String string, String prefixDelimiter) { return string.contains(prefixDelimiter) - ? string.substring(string.lastIndexOf(prefixDelimiter) + prefixDelimiter.length()) : string; + ? string.substring(string.lastIndexOf(prefixDelimiter) + prefixDelimiter.length()) + : string; } /** * Strips a prefix identified by a delimiter. This is achieved by splitting the string in two around matches of the * first occurrence of the given regular expression. * - * @param string a String from which to strip a prefix - * @param regex the delimiting regular expression + * @param string + * a String from which to strip a prefix + * @param regex + * the delimiting regular expression * @return - * @throws ValidationServiceException If there is a problem with the provided regular expression. + * @throws ValidationServiceException + * If there is a problem with the provided regular expression. */ public static String stripPrefixRegex(String string, String regex) throws ValidationServiceException { String[] strings = validParameters(string, regex) ? string.split(regex, 2) : new String[0]; @@ -72,8 +94,10 @@ public class StringUtils { /** * Process a list of strings and strip the given suffix from each string in the list. * - * @param stringList a list of strings - * @param suffix a suffix to be removed from the strings + * @param stringList + * a list of strings + * @param suffix + * a suffix to be removed from the strings * @return stripped list of strings. */ public static List stripSuffix(List stringList, String suffix) { -- cgit 1.2.3-korg