Provide support for properties encryption
authorRich Tabedzki <richard.tabedzki@att.com>
Tue, 8 May 2018 15:27:50 +0000 (11:27 -0400)
committerRich Tabedzki <richard.tabedzki@att.com>
Fri, 11 May 2018 18:37:35 +0000 (14:37 -0400)
Changes made:
* Implemented code to decrypt password field in property file

Change-Id: I97e5f93fd1f8383c1e2a1e6170489dc1db9d6337
Issue-ID: CCSDK-182
Signed-off-by: Rich Tabedzki <richard.tabedzki@att.com>
dblib/provider/pom.xml
dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLIBResourceProvider.java [changed mode: 0644->0755]
dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/EncShellCommand.java [new file with mode: 0755]
dblib/provider/src/main/resources/org/opendaylight/blueprint/dblib-blueprint.xml

index 3eaefd0..9bf898f 100755 (executable)
                        <artifactId>mockito-core</artifactId>
                        <scope>test</scope>
                </dependency>
+        <dependency>
+               <groupId>org.apache.karaf.shell</groupId>
+               <artifactId>org.apache.karaf.shell.console</artifactId>
+               <version>3.0.8</version>
+        </dependency>
        </dependencies>
 </project>
old mode 100644 (file)
new mode 100755 (executable)
index ddfb733..6d36d63
@@ -23,6 +23,7 @@ package org.onap.ccsdk.sli.core.dblib;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.lang.reflect.Method;
 import java.util.Optional;
 import java.util.Properties;
 import java.util.Vector;
@@ -32,6 +33,9 @@ import org.onap.ccsdk.sli.core.utils.KarafRootFileResolver;
 import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
 import org.onap.ccsdk.sli.core.utils.common.CoreDefaultFileResolver;
 import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -45,6 +49,12 @@ import org.slf4j.LoggerFactory;
  *     <li>A directory identified by the JRE argument <code>dblib.properties</code></li>
  *     <li>A <code>dblib.properties</code> file located in the karaf root directory</li>
  * </ol>
+ * 
+ * Encryption Support
+ * <ol>
+ *    <li>Uses ecryption provided by <code>AAAEncryptionService</code></li>
+ *    <li>AAA Configuration file is <code>aaa-cert-config.xml</code></li>
+ * </ol>
  */
 public class DBLIBResourceProvider {
 
@@ -55,6 +65,8 @@ public class DBLIBResourceProvider {
      */
     private static final String DBLIB_PROP_FILE_NAME = "dblib.properties";
 
+    private static final String DBLIB_PROPERTY_NAME = "org.onap.ccsdk.sli.jdbc.password";
+
     /**
      * A prioritized list of strategies for resolving dblib properties files.
      */
@@ -87,6 +99,20 @@ public class DBLIBResourceProvider {
             try(FileInputStream fileInputStream = new FileInputStream(propertiesFile)) {
                 properties = new Properties();
                 properties.load(fileInputStream);
+
+                if(properties.containsKey(DBLIB_PROPERTY_NAME)) {
+                    String sensitive = properties.getProperty(DBLIB_PROPERTY_NAME);
+                    if(sensitive != null && sensitive.startsWith("ENC:")) {
+                        try {
+                            sensitive = sensitive.substring(4);
+                            String postsense = decrypt(sensitive);
+                            properties.setProperty(DBLIB_PROPERTY_NAME, postsense);
+                        } catch(Exception exc) {
+                            LOG.error("Failed to translate property", exc);
+                        }
+                    }
+                }
+
             } catch (final IOException e) {
                 LOG.error("Failed to load properties for file: {}", propertiesFile.toString(),
                         new DblibConfigurationException("Failed to load properties for file: "
@@ -95,6 +121,36 @@ public class DBLIBResourceProvider {
         }
     }
 
+    /**
+     *
+     * @param value
+     * @return decrypted string if successful or the original value if unsuccessful
+     */
+    private String decrypt(String value) {
+        try {
+            BundleContext bctx = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+
+            ServiceReference sref = bctx.getServiceReference("org.opendaylight.aaa.encrypt.AAAEncryptionService");
+            if(sref == null) {
+                LOG.warn("Could not acquire service reference for 'org.opendaylight.aaa.encrypt.AAAEncryptionService'");
+                return value;
+            }
+            Object encrSvc = bctx.getService(sref);
+            if(encrSvc == null) {
+                LOG.warn("Could not access service for 'org.opendaylight.aaa.encrypt.AAAEncryptionService'");
+                return value;
+            }
+
+            Method gs2Method = encrSvc.getClass().getMethod("decrypt", new Class[] { "".getClass() });
+            Object unmasked = gs2Method.invoke(encrSvc, new Object[] { value });
+            return unmasked.toString();
+
+        } catch (Exception exc) {
+            LOG.error("Failure", exc);
+            return value;
+        }
+    }
+
     /**
      * Extract db config properties.
      *
diff --git a/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/EncShellCommand.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/EncShellCommand.java
new file mode 100755 (executable)
index 0000000..eaa5700
--- /dev/null
@@ -0,0 +1,48 @@
+package org.onap.ccsdk.sli.core.dblib;
+
+import java.lang.reflect.Method;
+
+/**
+ * https://karaf.apache.org/manual/latest-2.x/developers-guide/extending-console.html
+ * https://github.com/apache/karaf/tree/master/shell/console/src/main/java/org/apache/felix/gogo/commands
+ */
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Command(scope = "dblib", name = "encode", description="Says hello")
+public class EncShellCommand extends OsgiCommandSupport {
+    private static Logger LOGGER = LoggerFactory.getLogger(EncShellCommand.class);
+
+    @Argument(index = 0, name = "arg", description = "The command argument", required = true, multiValued = false)
+    String arg = null;
+
+    @Override
+    protected Object doExecute() throws Exception {
+        System.out.println(String.format("Original value: %s", arg));
+        System.out.println(String.format("Encrypted value: %s", encrypt(arg)));
+        return null;
+    }
+
+    private String encrypt(String value) {
+        try {
+            BundleContext bctx = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+
+            ServiceReference sref = bctx.getServiceReference("org.opendaylight.aaa.encrypt.AAAEncryptionService");
+            Object encrSvc = bctx.getService(sref);
+
+            Method gs2Method = encrSvc.getClass().getMethod("encrypt", new Class[] { "".getClass() });
+            Object unmasked = gs2Method.invoke(encrSvc, new Object[] { value });
+            return String.format("ENC:%s", unmasked.toString());
+
+        } catch (Exception exc) {
+            LOGGER.error("Failure", exc);
+            return value;
+        }
+    }
+}
\ No newline at end of file
index f1d5166..d9bb99c 100755 (executable)
         </interfaces>
     </service>
 
+    <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.0.0">
+        <command name="dblib/encode">
+            <action class="org.onap.ccsdk.sli.core.dblib.EncShellCommand"/>
+        </command>
+    </command-bundle>
+
 </blueprint>
\ No newline at end of file