private key configurable in config.ini 72/4072/5
authorMartin Bobak <mbobak@cisco.com>
Wed, 8 Jan 2014 12:18:11 +0000 (13:18 +0100)
committerMartin Bobak <mbobak@cisco.com>
Wed, 8 Jan 2014 16:07:22 +0000 (17:07 +0100)
Netconf SSH bridge has private key stored in distribution.
Path to this file is configured in config.ini.

Change-Id: I517586009c883a537c80fde8205d9040b5fe6052
Signed-off-by: Martin Bobak <mbobak@cisco.com>
opendaylight/distribution/opendaylight/src/main/resources/configuration/RSA.pk [moved from opendaylight/netconf/netconf-ssh/src/main/resources/RSA.pk with 100% similarity]
opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java
opendaylight/netconf/netconf-it/src/test/resources/RSA.pk [new file with mode: 0644]
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/osgi/NetconfSSHActivator.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProvider.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProviderInterface.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/SocketThread.java
opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/SSHServerTest.java
opendaylight/netconf/netconf-ssh/src/test/resources/RSA.pk [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java

index 8ffaff45c7487bb7a78e59c1818ca640c8d0fc58..995e4076c275b3eb76f65913e4ce4ffd6b1de080 100644 (file)
@@ -21,6 +21,8 @@ netconf.tcp.client.port=8383
 
 netconf.ssh.address=0.0.0.0
 netconf.ssh.port=1830
+netconf.ssh.pk.path = ./configuration/RSA.pk
+
 
 netconf.config.persister.active=1,2
 # read startup configuration
index 4818b5f0a3c7868be0a02dafd19e8c1657e0d777..bc2961c3171ef4ffbac432ca9a0529b262901428 100644 (file)
@@ -432,7 +432,8 @@ public class NetconfITTest extends AbstractConfigTest {
     private void startSSHServer() throws Exception{
         logger.info("Creating SSH server");
         StubUserManager um = new StubUserManager(USERNAME,PASSWORD);
-        AuthProvider ap = new AuthProvider(um);
+        InputStream is = getClass().getResourceAsStream("/RSA.pk");
+        AuthProvider ap = new AuthProvider(um, is);
         Thread sshServerThread = new Thread(NetconfSSHServer.start(10830,tcpAddress,ap));
         sshServerThread.setDaemon(true);
         sshServerThread.start();
diff --git a/opendaylight/netconf/netconf-it/src/test/resources/RSA.pk b/opendaylight/netconf/netconf-it/src/test/resources/RSA.pk
new file mode 100644 (file)
index 0000000..c0266c7
--- /dev/null
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAuC9hbEacpewvylI0mwFwjy3Wou2hpr/ncN9BBiFDSaG5yW2k
+3Oy+SCAcFCL+ZKWb6cc6Ch4gUeCwyEHRojZguuhliKtak9YQf6qbvpPLe00842Lx
+iqNAGurMpzizCDsGFq8ChaAkBZQI3TvcHuPoSUWSMJ+K8xHpRyUdVr6g2yEjezKJ
+sTXBtWaeCCh6YUafFujuDJk7fvYcPW7Je5KRBBStIKvxcMW0zB+7eq04deTHwGbJ
+gGjKWilQ72hsDDP3Hbp5CJMAYg1r4GlCmFx3KyHRGztgWgNgaD7nNpKCkTLjtmA6
+b4x7TA+jrzZ6Af2z5TMrI4dv5w1SrxHaZ+ziLQIDAQABAoIBAHTndeGgq/rQf8De
+Do+4CTaHtK0zQSAyu/azbXUzlZ7drKuCEVs8VMY4wzmwwGEnkF+A2YDkgEUX5X0l
+8aYQ97KKoS9u+43MGCrAIhyDeGrpqlT1TzRcy+qJz53v6gq2U/X/3QztiQ+VV078
+mIluxNgE9XYxPaNsYfGLSCTv1+9c8y/hjGVX2kwFK+u4ut0ZZETggNa8UxfaHVDS
+fIJQX9Gm3J3GSUV30fDGMBIUW6ESLc2L8b7u8Mp9TRP39ZeQSuEUjBe8MYKv0Rel
+oEpjZvcnniMTpFbLpndBYn7/AoIiEBvtCN8faVTuRRcvvLcsRm09IctzKQYnMh6M
+6PLKV+ECgYEA8HFRYaKHUzxpzE/fyon82GQbzqFFY0/bbWrfWICMfNbIgshJUie6
+FmH5iUFMfeqaT7v557HFM0GB9FeIeSbvd88YmiBAcRopZ3DfMkDH+DT73yJ+/TKG
+2nrQtdhyuTIs4bwHqeS2BBJYs7PK9R2rratF3l34Tf7mjlvyOgygHdUCgYEAxBo2
+8hEBlAVNcNb1hTYUxe1w1B6675/mFlmw98Xmj9dRYfICXNhahs8tX3/lsBEd+vBu
+fI0oyHaff8m5bPgGzD1ZMybfeROujNrgxaKVk7Ef0FDRRCop4bm18OroFlFAt9l8
+wMp++ToACbdvQvL/mjWMPYlIxhB/YxHswICZZvkCgYAexxKYwdo6sGAGlC7cWT9x
+X5cjowcjyEQZRHXkeUgCbufpvcOM7aLnXJE5nY8yCwbHsBM0MlBA2GDPKylAANjk
+aDEJAZneIHAuWodngl1Wi0m2bU7+ECqs6s2uiU9eH2sZVh1RBQK7kLGkBx6ys6KX
+L3ZZGYRAT6GplWFzRsx0JQKBgCeVlxPD5QqpC1nEumi6YvUVGdpnnZpzL3HBhxxs
+wT612wKnZFyze4qM1X7ahVXGDsQxtkvD/sCAWW/lG13orw6ZL6FIroF1PJ3ILOkY
+CZN3hJF7TtKwpCWhZB2OfWzL2AGEkE8mUP0j/Q/5DCd6f6f0OSvOw3bfq6cm3iB5
+lP2ZAoGAXsRN5TZTX4AQ2xTlrDQ8A5XgcvyWQpJOmEXMTyHV7VaJVzmNWFVAvndK
+5UIq8ALDwB2t7vjmMUW6euvIwqtXiop7G79UOb3e3NhzeyWFGQyBLqCRznGaXQTT
+dlFy73xhukZMhFnj006bjKCYvOPnwuGl3+0fuWil5Rq3jOuY5c8=
+-----END RSA PRIVATE KEY-----
index 3b513790bd128806a7ef1bec2561bd90fee6420a..446c5008960e92a001bf78f332435276dc1aef95 100644 (file)
@@ -8,6 +8,8 @@
 package org.opendaylight.controller.netconf.osgi;
 
 import com.google.common.base.Optional;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.net.InetSocketAddress;
 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
 import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
@@ -85,7 +87,28 @@ public class NetconfSSHActivator implements BundleActivator{
                 EXCEPTION_MESSAGE, true);
 
         if (sshSocketAddressOptional.isPresent()){
-            AuthProvider authProvider = new AuthProvider(iUserManager);
+            String path = NetconfConfigUtil.getPrivateKeyPath(context);
+            path = path.replace("\\", "/");
+            if (path.equals("")){
+                throw new Exception("Missing netconf.ssh.pk.path key in configuration file.");
+            }
+            FileInputStream fis = null;
+            try {
+                fis = new FileInputStream(path);
+            } catch (FileNotFoundException e){
+                throw new Exception("Missing file described by netconf.ssh.pk.path key in configuration file.");
+            } catch (SecurityException e){
+                throw new Exception("Read access denied to file described by netconf.ssh.pk.path key in configuration file.");
+            }
+            AuthProvider authProvider = null;
+            try {
+                authProvider = new AuthProvider(iUserManager,fis);
+            } catch (Exception e){
+                if (fis!=null){
+                    fis.close();
+                }
+                throw (e);
+            }
             this.server = NetconfSSHServer.start(sshSocketAddressOptional.get().getPort(),tcpSocketAddress,authProvider);
             Thread serverThread = new  Thread(server,"netconf SSH server thread");
             serverThread.setDaemon(true);
index a73dfdfd49eca56129a5ba0e98efb13fba001556..22dda95064c092c286a1046edc90595943485a0d 100644 (file)
@@ -7,8 +7,6 @@
  */
 package org.opendaylight.controller.netconf.ssh.authentication;
 
-import ch.ethz.ssh2.signature.RSAPrivateKey;
-import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
@@ -17,26 +15,30 @@ import org.opendaylight.controller.sal.authorization.AuthResultEnum;
 import org.opendaylight.controller.sal.authorization.UserLevel;
 import org.opendaylight.controller.usermanager.IUserManager;
 import org.opendaylight.controller.usermanager.UserConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class AuthProvider implements AuthProviderInterface {
 
-    private static RSAPrivateKey hostkey = null;
     private static IUserManager um;
-    private static final String DEAFULT_USER = "netconf";
-    private static final String DEAFULT_PASSWORD = "netconf";
+    private static final String DEFAULT_USER = "netconf";
+    private static final String DEFAULT_PASSWORD = "netconf";
+    private static InputStream privateKeyFileInputStream;
 
+    private static final Logger logger =  LoggerFactory.getLogger(AuthProvider.class);
 
-    public AuthProvider(IUserManager ium) throws Exception {
+    public AuthProvider(IUserManager ium,InputStream privateKeyFileInputStream) throws Exception {
 
         this.um = ium;
-
         if (this.um  == null){
             throw new Exception("No usermanager service available.");
         }
 
+        this.privateKeyFileInputStream = privateKeyFileInputStream;
+
         List<String> roles = new ArrayList<String>(1);
         roles.add(UserLevel.SYSTEMADMIN.toString());
-        this.um.addLocalUser(new UserConfig(DEAFULT_USER, DEAFULT_PASSWORD, roles));
+        this.um.addLocalUser(new UserConfig(DEFAULT_USER, DEFAULT_PASSWORD, roles));
     }
     @Override
     public boolean authenticated(String username, String password)  throws Exception {
@@ -51,15 +53,10 @@ public class AuthProvider implements AuthProviderInterface {
     }
 
     @Override
-    public char[] getPEMAsCharArray() {
-
-        InputStream is = getClass().getResourceAsStream("/RSA.pk");
-        try {
-            return IOUtils.toCharArray(is);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        return null;
+    public char[] getPEMAsCharArray() throws Exception {
+        char [] PEM  = IOUtils.toCharArray(privateKeyFileInputStream);
+        privateKeyFileInputStream.close();
+        return PEM;
     }
 
     @Override
index 71f1cc350fda1d5d829cb101798d208eaf1bc906..8e40578a0e47c001676b8fb28809a9cf306364e2 100644 (file)
@@ -13,7 +13,7 @@ import org.opendaylight.controller.usermanager.IUserManager;
 public interface AuthProviderInterface {
 
     public boolean authenticated(String username, String password) throws Exception;
-    public char[] getPEMAsCharArray();
+    public char[] getPEMAsCharArray() throws Exception;
     public void removeUserManagerService();
     public void addUserManagerService(IUserManager userManagerService);
 }
index e5da03b4cf4c9d97765ce098a8c2761b0eda8e39..32de75ca3969a039bbeb0046fc4c2a7b55d3462d 100644 (file)
@@ -59,8 +59,8 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser
         conn = new ServerConnection(socket);
         try {
             conn.setPEMHostKey(authProvider.getPEMAsCharArray(),"netconf");
-        } catch (IOException e) {
-            e.printStackTrace();
+        } catch (Exception e) {
+            logger.debug("Server authentication setup failed.");
         }
         conn.setAuthenticationCallback(this);
         conn.setServerConnectionCallback(this);
index 62396ed87ac1f4db3dcaa7942f676012ab35ade8..91783ff755b5e934af8359c47f25b51d9ed5cd23 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.controller.netconf;
 
 import ch.ethz.ssh2.Connection;
+import java.io.InputStream;
 import java.net.InetSocketAddress;
 import junit.framework.Assert;
 import org.junit.Test;
@@ -33,7 +34,8 @@ public class SSHServerTest {
     public void startSSHServer() throws Exception{
         logger.info("Creating SSH server");
         StubUserManager um = new StubUserManager(USER,PASSWORD);
-        AuthProvider ap = new AuthProvider(um);
+        InputStream is = getClass().getResourceAsStream("/RSA.pk");
+        AuthProvider ap = new AuthProvider(um, is);
         NetconfSSHServer server = NetconfSSHServer.start(PORT,tcpAddress,ap);
         sshServerThread = new Thread(server);
         sshServerThread.setDaemon(true);
diff --git a/opendaylight/netconf/netconf-ssh/src/test/resources/RSA.pk b/opendaylight/netconf/netconf-ssh/src/test/resources/RSA.pk
new file mode 100644 (file)
index 0000000..c0266c7
--- /dev/null
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAuC9hbEacpewvylI0mwFwjy3Wou2hpr/ncN9BBiFDSaG5yW2k
+3Oy+SCAcFCL+ZKWb6cc6Ch4gUeCwyEHRojZguuhliKtak9YQf6qbvpPLe00842Lx
+iqNAGurMpzizCDsGFq8ChaAkBZQI3TvcHuPoSUWSMJ+K8xHpRyUdVr6g2yEjezKJ
+sTXBtWaeCCh6YUafFujuDJk7fvYcPW7Je5KRBBStIKvxcMW0zB+7eq04deTHwGbJ
+gGjKWilQ72hsDDP3Hbp5CJMAYg1r4GlCmFx3KyHRGztgWgNgaD7nNpKCkTLjtmA6
+b4x7TA+jrzZ6Af2z5TMrI4dv5w1SrxHaZ+ziLQIDAQABAoIBAHTndeGgq/rQf8De
+Do+4CTaHtK0zQSAyu/azbXUzlZ7drKuCEVs8VMY4wzmwwGEnkF+A2YDkgEUX5X0l
+8aYQ97KKoS9u+43MGCrAIhyDeGrpqlT1TzRcy+qJz53v6gq2U/X/3QztiQ+VV078
+mIluxNgE9XYxPaNsYfGLSCTv1+9c8y/hjGVX2kwFK+u4ut0ZZETggNa8UxfaHVDS
+fIJQX9Gm3J3GSUV30fDGMBIUW6ESLc2L8b7u8Mp9TRP39ZeQSuEUjBe8MYKv0Rel
+oEpjZvcnniMTpFbLpndBYn7/AoIiEBvtCN8faVTuRRcvvLcsRm09IctzKQYnMh6M
+6PLKV+ECgYEA8HFRYaKHUzxpzE/fyon82GQbzqFFY0/bbWrfWICMfNbIgshJUie6
+FmH5iUFMfeqaT7v557HFM0GB9FeIeSbvd88YmiBAcRopZ3DfMkDH+DT73yJ+/TKG
+2nrQtdhyuTIs4bwHqeS2BBJYs7PK9R2rratF3l34Tf7mjlvyOgygHdUCgYEAxBo2
+8hEBlAVNcNb1hTYUxe1w1B6675/mFlmw98Xmj9dRYfICXNhahs8tX3/lsBEd+vBu
+fI0oyHaff8m5bPgGzD1ZMybfeROujNrgxaKVk7Ef0FDRRCop4bm18OroFlFAt9l8
+wMp++ToACbdvQvL/mjWMPYlIxhB/YxHswICZZvkCgYAexxKYwdo6sGAGlC7cWT9x
+X5cjowcjyEQZRHXkeUgCbufpvcOM7aLnXJE5nY8yCwbHsBM0MlBA2GDPKylAANjk
+aDEJAZneIHAuWodngl1Wi0m2bU7+ECqs6s2uiU9eH2sZVh1RBQK7kLGkBx6ys6KX
+L3ZZGYRAT6GplWFzRsx0JQKBgCeVlxPD5QqpC1nEumi6YvUVGdpnnZpzL3HBhxxs
+wT612wKnZFyze4qM1X7ahVXGDsQxtkvD/sCAWW/lG13orw6ZL6FIroF1PJ3ILOkY
+CZN3hJF7TtKwpCWhZB2OfWzL2AGEkE8mUP0j/Q/5DCd6f6f0OSvOw3bfq6cm3iB5
+lP2ZAoGAXsRN5TZTX4AQ2xTlrDQ8A5XgcvyWQpJOmEXMTyHV7VaJVzmNWFVAvndK
+5UIq8ALDwB2t7vjmMUW6euvIwqtXiop7G79UOb3e3NhzeyWFGQyBLqCRznGaXQTT
+dlFy73xhukZMhFnj006bjKCYvOPnwuGl3+0fuWil5Rq3jOuY5c8=
+-----END RSA PRIVATE KEY-----
index 987708d67ed03db1276a6459ad47c75f7eabf0bf..55ed7e074423968dd7e7626e45a181893cdfd4a1 100644 (file)
@@ -23,6 +23,7 @@ public class NetconfConfigUtil {
     private static final String PORT_SUFFIX_PROP = ".port";
     private static final String ADDRESS_SUFFIX_PROP = ".address";
     private static final String CLIENT_PROP = ".client";
+    private static final String PRIVATE_KEY_PATH_PROP = ".pk.path";
 
     public static InetSocketAddress extractTCPNetconfAddress(BundleContext context, String exceptionMessageIfNotFound, boolean forClient) {
 
@@ -38,6 +39,16 @@ public class NetconfConfigUtil {
         return extractSomeNetconfAddress(context, InfixProp.ssh, exceptionMessage, false);
     }
 
+    public static String getPrivateKeyPath(BundleContext context){
+        return getPropertyValue(context,PREFIX_PROP + InfixProp.ssh +PRIVATE_KEY_PATH_PROP);
+    }
+    private static String getPropertyValue(BundleContext context, String propertyName){
+        String propertyValue = context.getProperty(propertyName);
+        if (propertyValue == null){
+            throw new IllegalStateException("Cannot find initial property with name '"+propertyName+"'");
+        }
+        return propertyValue;
+    }
     /**
      * @param context
      *            from which properties are being read.