summaryrefslogtreecommitdiffstats
path: root/policy-utils
diff options
context:
space:
mode:
authorjhh <jorge.hernandez-herrero@att.com>2019-10-16 21:30:26 -0500
committerJorge Hernandez <jorge.hernandez-herrero@att.com>2019-10-24 14:12:41 +0000
commit327ac05ea0e29a8d604f187d78f1a48aa35d8b4a (patch)
treedd6c149b33afb32c63a274dd57f2da6b0b7b7143 /policy-utils
parent6e0b450abe7e62fa47ffe14e95a67d035174dbdb (diff)
Allow encrypted property values
Issue-ID: POLICY-1945 Signed-off-by: jhh <jorge.hernandez-herrero@att.com> Change-Id: I0317a6de838d99b579638252859e42fc49cedfa8 Signed-off-by: jhh <jorge.hernandez-herrero@att.com>
Diffstat (limited to 'policy-utils')
-rw-r--r--policy-utils/src/main/java/org/onap/policy/drools/utils/CryptoCoderValueLookup.java51
-rw-r--r--policy-utils/src/main/java/org/onap/policy/drools/utils/EnvironmentVariableWithDefaultLookup.java57
-rw-r--r--policy-utils/src/main/java/org/onap/policy/drools/utils/PropertyUtil.java142
-rw-r--r--policy-utils/src/test/java/org/onap/policy/drools/utils/PropertyUtilTest.java112
-rw-r--r--policy-utils/src/test/resources/interpolation.properties7
5 files changed, 320 insertions, 49 deletions
diff --git a/policy-utils/src/main/java/org/onap/policy/drools/utils/CryptoCoderValueLookup.java b/policy-utils/src/main/java/org/onap/policy/drools/utils/CryptoCoderValueLookup.java
new file mode 100644
index 00000000..9d4a8824
--- /dev/null
+++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/CryptoCoderValueLookup.java
@@ -0,0 +1,51 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2017-2019 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.policy.drools.utils;
+
+import org.apache.commons.configuration2.interpol.Lookup;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.policy.common.utils.security.CryptoCoder;
+
+/**
+ * Crypto Coder value look up. Syntax: ${enc:encoded-value}.
+ */
+public class CryptoCoderValueLookup implements Lookup {
+
+ protected final CryptoCoder cryptoCoder;
+
+ /**
+ * Crypto Coder Lookup.
+ *
+ * @param crypto crypto coder
+ */
+ public CryptoCoderValueLookup(CryptoCoder crypto) {
+ this.cryptoCoder = crypto;
+ }
+
+ @Override
+ public String lookup(String key) {
+ if (StringUtils.isBlank(key)) {
+ return null;
+ }
+
+ return cryptoCoder.decrypt(PropertyUtil.CRYPTO_CODER_PROPERTY_PREFIX + ":" + key);
+ }
+}
diff --git a/policy-utils/src/main/java/org/onap/policy/drools/utils/EnvironmentVariableWithDefaultLookup.java b/policy-utils/src/main/java/org/onap/policy/drools/utils/EnvironmentVariableWithDefaultLookup.java
new file mode 100644
index 00000000..e0d3e388
--- /dev/null
+++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/EnvironmentVariableWithDefaultLookup.java
@@ -0,0 +1,57 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2017-2019 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.policy.drools.utils;
+
+import com.google.common.base.Splitter;
+import java.util.List;
+import org.apache.commons.configuration2.interpol.Lookup;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Environment Variable with a default value. The syntax is
+ * ${envd:variable-name:default-value}.
+ */
+public class EnvironmentVariableWithDefaultLookup implements Lookup {
+
+ @Override
+ public String lookup(String key) {
+ if (StringUtils.isBlank(key)) {
+ return null;
+ }
+
+ List<String> envWithDefault =
+ Splitter.on(":").trimResults().omitEmptyStrings().splitToList(key);
+ if (envWithDefault.isEmpty()) {
+ return StringUtils.EMPTY;
+ }
+
+ String envVar = System.getenv(envWithDefault.get(0));
+ if (StringUtils.isNotEmpty(envVar)) {
+ return envVar;
+ }
+
+ if (envWithDefault.size() > 1) {
+ return String.join(":", envWithDefault.subList(1, envWithDefault.size()));
+ }
+
+ return StringUtils.EMPTY;
+ }
+}
diff --git a/policy-utils/src/main/java/org/onap/policy/drools/utils/PropertyUtil.java b/policy-utils/src/main/java/org/onap/policy/drools/utils/PropertyUtil.java
index 8594995d..0b49993d 100644
--- a/policy-utils/src/main/java/org/onap/policy/drools/utils/PropertyUtil.java
+++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/PropertyUtil.java
@@ -1,6 +1,6 @@
/*-
* ============LICENSE_START=======================================================
- * policy-utils
+ * ONAP
* ================================================================================
* Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
* ================================================================================
@@ -30,9 +30,10 @@ import java.util.Properties;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
-
+import org.apache.commons.configuration2.Configuration;
import org.apache.commons.configuration2.ConfigurationConverter;
import org.apache.commons.configuration2.SystemConfiguration;
+import org.onap.policy.common.utils.security.CryptoCoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,6 +42,8 @@ import org.slf4j.LoggerFactory;
* file, and optionally get notifications of future changes.
*/
public class PropertyUtil {
+ public static final String ENV_WITH_DEFAULT_PROPERTY_PREFIX = "envd";
+ public static final String CRYPTO_CODER_PROPERTY_PREFIX = "enc";
// timer thread used for polling for property file changes
private static Timer timer = null;
@@ -51,10 +54,17 @@ public class PropertyUtil {
private static final Logger logger = LoggerFactory.getLogger(PropertyUtil.class.getName());
+ private static volatile CryptoCoder cryptoCoder;
+
/**
- * Read in a properties file. Variable interpolation is performed by using
- * apache commons configuration2 library. This allows for embedding system properties,
- * constants, and environment variables in property files.
+ * Sets a default Crypto Coder.
+ */
+ public static void setDefaultCryptoCoder(CryptoCoder cryptoCoder) {
+ PropertyUtil.cryptoCoder = cryptoCoder;
+ }
+
+ /**
+ * Read in a properties file and performs variable interpolation.
*
* @param file the properties file
* @return a Properties object, containing the associated properties
@@ -63,22 +73,22 @@ public class PropertyUtil {
* a problem loading the properties file.
*/
public static Properties getProperties(File file) throws IOException {
- // create an InputStream (may throw a FileNotFoundException)
- Properties rval = new Properties();
- try (FileInputStream fis = new FileInputStream(file)) {
- // create the properties instance
-
- // load properties (may throw an IOException)
- rval.load(fis);
- }
+ return getInterpolatedProperties(getPropertiesFile(file));
+ }
- /*
- * Return properties file with environment variables interpolated.
- * It is necessary to construct the object in this fashion and avoid
- * builders since they use the commons-beanutils (optional) library that has been
- * flagged as insecured.
- */
- return getInterpolatedProperties(rval);
+ /**
+ * Reads a property files and performs variable interpolation. It uses a
+ * crypto coder to interpolate encrypted sensitive data.
+ *
+ * @param file the properties file
+ * @param cryptoCoder a custom CryptoCoder implementation
+ * @return a Properties object, containing the associated properties
+ * @throws IOException - subclass 'FileNotFoundException' if the file
+ * does not exist or can't be opened, and 'IOException' if there is
+ * a problem loading the properties file.
+ */
+ public static Properties getProperties(File file, CryptoCoder cryptoCoder) throws IOException {
+ return getInterpolatedProperties(getPropertiesFile(file), cryptoCoder);
}
/**
@@ -88,13 +98,28 @@ public class PropertyUtil {
* @return a Properties object, containing the associated properties
* @throws IOException - subclass 'FileNotFoundException' if the file
* does not exist or can't be opened, and 'IOException' if there is
- * a problem loading the properties file.
+ * a problem loading the properties file
*/
public static Properties getProperties(String fileName) throws IOException {
return getProperties(new File(fileName));
}
/**
+ * Reads a property files and performs variable interpolation. It uses a
+ * crypto coder to interpolate encrypted sensitive data.
+ *
+ * @param fileName the properties file name
+ * @param cryptoCoder a custom CryptoCoder implementation
+ * @return a Properties object, containing the associated properties
+ * @throws IOException - subclass 'FileNotFoundException' if the file
+ * does not exist or can't be opened, and 'IOException' if there is
+ * a problem loading the properties file
+ */
+ public static Properties getProperties(String fileName, CryptoCoder cryptoCoder) throws IOException {
+ return getProperties(new File(fileName), cryptoCoder);
+ }
+
+ /**
* Read in a properties file, and register for update notifications.
* NOTE: it is possible that the first callback will occur while this
* method is still in progress. To avoid this problem, use 'synchronized'
@@ -110,8 +135,7 @@ public class PropertyUtil {
* does not exist or can't be opened, and 'IOException' if there is
* a problem loading the properties file.
*/
- public static Properties getProperties(File file, Listener listener)
- throws IOException {
+ public static Properties getProperties(File file, Listener listener) throws IOException {
File propFile = file;
if (listener == null) {
// no listener specified -- just fetch the properties
@@ -151,19 +175,63 @@ public class PropertyUtil {
* does not exist or can't be opened, and 'IOException' if there is
* a problem loading the properties file.
*/
- public static Properties getProperties(String fileName, Listener listener)
- throws IOException {
+ public static Properties getProperties(String fileName, Listener listener) throws IOException {
return getProperties(new File(fileName), listener);
}
/**
- * gets interpolated properties from a properties object.
+ * Get an interpolated properties object from a properties one.
*
- * @param properties object
- * @return properties
+ * @param properties non-interpolated properties object
+ * @return Properties - interpolated properties object
*/
public static Properties getInterpolatedProperties(Properties properties) {
- return ConfigurationConverter.getProperties(ConfigurationConverter.getConfiguration(properties));
+ return getInterpolatedProperties(properties, cryptoCoder);
+ }
+
+ /**
+ * Get an interpolated properties object from a properties one.
+ *
+ * @param properties non-interpolated properties object
+ * @param cryptoCoder crypto coder
+ * @return Properties - interpolated properties object
+ */
+ public static Properties getInterpolatedProperties(Properties properties, CryptoCoder cryptoCoder) {
+ Configuration config = ConfigurationConverter.getConfiguration(properties);
+ config.getInterpolator()
+ .registerLookup(ENV_WITH_DEFAULT_PROPERTY_PREFIX, new EnvironmentVariableWithDefaultLookup());
+
+ if (cryptoCoder == null) {
+ return ConfigurationConverter.getProperties(config);
+ }
+
+ config.getInterpolator().registerLookup(CRYPTO_CODER_PROPERTY_PREFIX, new CryptoCoderValueLookup(cryptoCoder));
+ Properties props = ConfigurationConverter.getProperties(config);
+ props.stringPropertyNames().forEach(key -> {
+ props.setProperty(key, cryptoCoder.decrypt(props.getProperty(key)));
+ });
+ return props;
+ }
+
+ /**
+ * Read in a properties file from disk.
+ *
+ * @param file the properties file
+ * @return a Properties object, containing the associated properties
+ * @throws IOException - subclass 'FileNotFoundException' if the file
+ * does not exist or can't be opened, and 'IOException' if there is
+ * a problem loading the properties file.
+ */
+ protected static Properties getPropertiesFile(File file) throws IOException {
+ // create an InputStream (may throw a FileNotFoundException)
+ Properties rval = new Properties();
+ try (FileInputStream fis = new FileInputStream(file)) {
+ // create the properties instance
+
+ // load properties (may throw an IOException)
+ rval.load(fis);
+ }
+ return rval;
}
/**
@@ -172,8 +240,20 @@ public class PropertyUtil {
* @param properties properties file
*/
public static void setSystemProperties(Properties properties) {
- Properties interpolatedProps = getInterpolatedProperties(properties);
- SystemConfiguration.setSystemProperties(ConfigurationConverter.getConfiguration(interpolatedProps));
+ SystemConfiguration
+ .setSystemProperties(ConfigurationConverter
+ .getConfiguration(getInterpolatedProperties(properties)));
+ }
+
+ /**
+ * sets system properties from a properties file.
+ *
+ * @param properties properties file
+ */
+ public static void setSystemProperties(Properties properties, CryptoCoder cryptoCoder) {
+ SystemConfiguration
+ .setSystemProperties(ConfigurationConverter
+ .getConfiguration(getInterpolatedProperties(properties, cryptoCoder)));
}
/* ============================================================ */
diff --git a/policy-utils/src/test/java/org/onap/policy/drools/utils/PropertyUtilTest.java b/policy-utils/src/test/java/org/onap/policy/drools/utils/PropertyUtilTest.java
index f05974c6..006d709c 100644
--- a/policy-utils/src/test/java/org/onap/policy/drools/utils/PropertyUtilTest.java
+++ b/policy-utils/src/test/java/org/onap/policy/drools/utils/PropertyUtilTest.java
@@ -1,6 +1,6 @@
/*-
* ============LICENSE_START=======================================================
- * policy-utils
+ * ONAP
* ================================================================================
* Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
* ================================================================================
@@ -30,22 +30,38 @@ import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
-
+import org.apache.commons.lang3.StringUtils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.onap.policy.common.utils.security.CryptoUtils;
import org.onap.policy.drools.utils.logging.LoggerUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PropertyUtilTest {
- private static final Logger logger = LoggerFactory.getLogger(PropertyUtilTest.class);
private static final String INTERPOLATION_PROPERTIES = "src/test/resources/interpolation.properties";
+ private static final String INTERPOLATION_CRYPTO_KEY = "MTIzNDU2Nzg5MDEyMzQ1Ng==";
+ private static final String INTERPOLATION_PLAINTEXT = "HelloWorld";
+ private static final String INTERPOLATION_ENVD_DEFAULT_VALUE = "default";
+ private static final String INTERPOLATION_ENC_HELLOWORLD = "enc:hcI2XVX+cxPz/6rlbebkWpCFF6WPbBtT7iJRr2VHUkA=";
+ private static final String INTERPOLATION_ENC_HELLOWORLD_VAR = "${" + INTERPOLATION_ENC_HELLOWORLD + "}";
+
private static final String INTERPOLATION_NO = "interpolation.no";
private static final String INTERPOLATION_ENV = "interpolation.env";
+ private static final String INTERPOLATION_ENVD = "interpolation.envd";
private static final String INTERPOLATION_CONST = "interpolation.const";
private static final String INTERPOLATION_SYS = "interpolation.sys";
+ private static final String INTERPOLATION_ENVD_NONE = "interpolation.envd.none";
+ private static final String INTERPOLATION_ENVD_DEFAULT = "interpolation.envd.default";
+ private static final String INTERPOLATION_ENVD_NO_DEFAULT = "interpolation.envd.nodefault";
+ private static final String INTERPOLATION_ENC = "interpolation.enc";
+ private static final String INTERPOLATION_ENC2 = "interpolation.enc2";
+ private static final String INTERPOLATION_ENVENC = "interpolation.envenc";
+
+
+ private static final Logger logger = LoggerFactory.getLogger(PropertyUtilTest.class);
private static File directory = null;
@@ -136,25 +152,85 @@ public class PropertyUtilTest {
// they should match
assertEquals(prop1, prop2);
- Properties prop3 = PropertyUtil.getProperties(INTERPOLATION_PROPERTIES);
+ // tests performed in sequence
+ testGetCryptoCoderArg();
+ testGetNoCryptoProps();
+ testGetDefaultCryptoProps();
+ testGetNoCryptoSystemProps();
+ testGetCryptoArgSystemProps();
+ testGetDefaultCryptoSystemProps();
- assertEquals("no", prop3.getProperty(INTERPOLATION_NO));
- assertEquals(System.getenv("HOME"), prop3.getProperty(INTERPOLATION_ENV));
- assertEquals(LoggerUtil.ROOT_LOGGER, prop3.getProperty(INTERPOLATION_CONST));
- assertEquals(System.getProperty("user.home"), prop3.getProperty(INTERPOLATION_SYS));
+ }
- Properties prop4 = new Properties();
- prop4.put(INTERPOLATION_NO, "no");
- prop4.put(INTERPOLATION_ENV, "${env:HOME}");
- prop4.put(INTERPOLATION_CONST, "${const:org.onap.policy.drools.utils.logging.LoggerUtil.ROOT_LOGGER}");
- prop4.put(INTERPOLATION_SYS, "${sys:user.home}");
+ private void testGetDefaultCryptoSystemProps() throws IOException {
+ // system properties + default crypto coder
+ PropertyUtil.setDefaultCryptoCoder(new CryptoUtils(INTERPOLATION_CRYPTO_KEY));
+ PropertyUtil.setSystemProperties(PropertyUtil.getPropertiesFile(new File(INTERPOLATION_PROPERTIES)));
+ assertPropInterpolation(System.getProperties());
+ assertPropEncInterpolation(System.getProperties());
+ }
- PropertyUtil.setSystemProperties(prop4);
+ private void testGetCryptoArgSystemProps() throws IOException {
+ // system properties + crypto coder passed in
+ PropertyUtil
+ .setSystemProperties(PropertyUtil
+ .getPropertiesFile(new File(INTERPOLATION_PROPERTIES)), new CryptoUtils(INTERPOLATION_CRYPTO_KEY));
+ assertPropInterpolation(System.getProperties());
+ assertPropEncInterpolation(System.getProperties());
+ }
+
+ private void testGetNoCryptoSystemProps() throws IOException {
+ /* system properties + no crypto coder */
+ PropertyUtil.setDefaultCryptoCoder(null);
+ PropertyUtil.setSystemProperties(PropertyUtil.getPropertiesFile(new File(INTERPOLATION_PROPERTIES)));
+ assertPropInterpolation(System.getProperties());
+ assertPropNoEncInterpolation(System.getProperties());
+ }
+
+ private void testGetDefaultCryptoProps() throws IOException {
+ /* properties + default crypto coder */
+ PropertyUtil.setDefaultCryptoCoder(new CryptoUtils(INTERPOLATION_CRYPTO_KEY));
+ Properties props = PropertyUtil.getProperties(INTERPOLATION_PROPERTIES);
+ assertPropInterpolation(props);
+ assertPropEncInterpolation(props);
+ }
+
+ private void testGetNoCryptoProps() throws IOException {
+ /* properties + no crypto coder */
+ Properties props = PropertyUtil.getProperties(INTERPOLATION_PROPERTIES);
+ assertPropInterpolation(props);
+ assertPropNoEncInterpolation(props);
+ }
+
+ private void testGetCryptoCoderArg() throws IOException {
+ /* properties + crypto coder passed in */
+ Properties props =
+ PropertyUtil.getProperties(INTERPOLATION_PROPERTIES, new CryptoUtils(INTERPOLATION_CRYPTO_KEY));
+ assertPropInterpolation(props);
+ assertPropEncInterpolation(props);
+ }
+
+ private void assertPropNoEncInterpolation(Properties props) {
+ assertEquals(INTERPOLATION_ENC_HELLOWORLD_VAR, props.getProperty(INTERPOLATION_ENC));
+ assertEquals(INTERPOLATION_ENC_HELLOWORLD, props.getProperty(INTERPOLATION_ENC2));
+ assertEquals(INTERPOLATION_ENC_HELLOWORLD, props.getProperty(INTERPOLATION_ENVENC));
+ }
+
+ private void assertPropEncInterpolation(Properties props) {
+ assertEquals(INTERPOLATION_PLAINTEXT, props.getProperty(INTERPOLATION_ENC));
+ assertEquals(INTERPOLATION_PLAINTEXT, props.getProperty(INTERPOLATION_ENC2));
+ assertEquals(INTERPOLATION_PLAINTEXT, props.getProperty(INTERPOLATION_ENVENC));
+ }
- assertEquals("no", System.getProperty(INTERPOLATION_NO));
- assertEquals(System.getenv("HOME"), System.getProperty(INTERPOLATION_ENV));
- assertEquals(LoggerUtil.ROOT_LOGGER, System.getProperty(INTERPOLATION_CONST));
- assertEquals(System.getProperty("user.home"), System.getProperty(INTERPOLATION_SYS));
+ private void assertPropInterpolation(Properties props) {
+ assertEquals("no", props.getProperty(INTERPOLATION_NO));
+ assertEquals(System.getenv("HOME"), props.getProperty(INTERPOLATION_ENV));
+ assertEquals(System.getenv("HOME"), props.getProperty(INTERPOLATION_ENVD));
+ assertEquals(StringUtils.EMPTY, props.getProperty(INTERPOLATION_ENVD_NONE));
+ assertEquals(StringUtils.EMPTY, props.getProperty(INTERPOLATION_ENVD_NO_DEFAULT));
+ assertEquals(LoggerUtil.ROOT_LOGGER, props.getProperty(INTERPOLATION_CONST));
+ assertEquals(System.getProperty("user.home"), props.getProperty(INTERPOLATION_SYS));
+ assertEquals(INTERPOLATION_ENVD_DEFAULT_VALUE, props.getProperty(INTERPOLATION_ENVD_DEFAULT));
}
/**
diff --git a/policy-utils/src/test/resources/interpolation.properties b/policy-utils/src/test/resources/interpolation.properties
index 66554337..2145fb61 100644
--- a/policy-utils/src/test/resources/interpolation.properties
+++ b/policy-utils/src/test/resources/interpolation.properties
@@ -2,3 +2,10 @@ interpolation.no=no
interpolation.env=${env:HOME}
interpolation.const=${const:org.onap.policy.drools.utils.logging.LoggerUtil.ROOT_LOGGER}
interpolation.sys=${sys:user.home}
+interpolation.envd=${envd:HOME}
+interpolation.envd.default=${envd:BLAH:default}
+interpolation.envd.none=${envd:BLAH}
+interpolation.envd.nodefault=${envd:BLAH:}
+interpolation.enc=${enc:hcI2XVX+cxPz/6rlbebkWpCFF6WPbBtT7iJRr2VHUkA=}
+interpolation.enc2=enc:hcI2XVX+cxPz/6rlbebkWpCFF6WPbBtT7iJRr2VHUkA=
+interpolation.envenc=${envd:HELLOWORLD:enc:hcI2XVX+cxPz/6rlbebkWpCFF6WPbBtT7iJRr2VHUkA=} \ No newline at end of file