Make netconf utilize encrypted passwords only 28/52528/28
authorColin Dixon <colin@colindixon.com>
Tue, 27 Jun 2017 14:09:28 +0000 (10:09 -0400)
committerColin Dixon <colin@colindixon.com>
Tue, 27 Jun 2017 14:37:42 +0000 (10:37 -0400)
Change-Id: I5c178c4e3865e374f39e326ceb9c4e24be269590
Signed-off-by: Ryan Goulding <ryandgoulding@gmail.com>
Signed-off-by: Atul Gosain <agosain@brocade.com>
Signed-off-by: Colin Dixon <colin@colindixon.com>
21 files changed:
features/netconf-connector/odl-netconf-connector/pom.xml
features/netconf/features-netconf/pom.xml
features/netconf/odl-netconf-netty-util/pom.xml
netconf/callhome-provider/src/main/java/org/opendaylight/netconf/callhome/mount/BaseCallHomeTopology.java
netconf/callhome-provider/src/main/java/org/opendaylight/netconf/callhome/mount/CallHomeMountDispatcher.java
netconf/callhome-provider/src/main/java/org/opendaylight/netconf/callhome/mount/CallHomeTopology.java
netconf/callhome-provider/src/main/resources/org/opendaylight/blueprint/callhome-topology.xml
netconf/callhome-provider/src/test/java/org/opendaylight/netconf/callhome/mount/CallHomeMountDispatcherTest.java
netconf/netconf-netty-util/pom.xml
netconf/netconf-netty-util/src/main/java/org/opendaylight/netconf/nettyutil/handler/ssh/authentication/LoginPassword.java
netconf/netconf-topology-config/src/main/resources/org/opendaylight/blueprint/netconf-topology.xml
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/NetconfTopologyManager.java
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/RemoteDeviceConnectorImpl.java
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/utils/NetconfTopologySetup.java
netconf/netconf-topology-singleton/src/main/resources/org/opendaylight/blueprint/netconf-topology-singleton.xml
netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/NetconfTopologyManagerTest.java
netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/RemoteDeviceConnectorImplTest.java
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImpl.java
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImplTest.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/util/AuthEncryptor.java [new file with mode: 0644]

index 7d82fb9c7d6fed8c21657fbfebadffaedb71e58f..dfaa6a7eeeb14112d190f127b2defa8323afebd4 100644 (file)
             <groupId>org.opendaylight.netconf</groupId>
             <artifactId>netconf-config</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.aaa</groupId>
+            <artifactId>odl-aaa-encryption-service</artifactId>
+            <version>0.6.0-SNAPSHOT</version>
+            <type>xml</type>
+            <classifier>features</classifier>
+        </dependency>
+
     </dependencies>
-</project>
\ No newline at end of file
+</project>
index 44d39ec27b3d7fd4dd0574bd6e391ba8adf01162..9b885532611b28c28ab645e6696836ce52027507 100644 (file)
       <type>xml</type>
       <classifier>features</classifier>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.aaa</groupId>
+      <artifactId>aaa-encrypt-service</artifactId>
+      <version>0.6.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.aaa</groupId>
+      <artifactId>aaa-encrypt-service</artifactId>
+      <version>0.6.0-SNAPSHOT</version>
+      <classifier>config</classifier>
+      <type>xml</type>
+    </dependency>
   </dependencies>
-</project>
\ No newline at end of file
+</project>
index a615f2f0ddf8025dff9172d82944b69b4e365056..9d537c73b722ac3c76263e57cd361231f3a87ede 100644 (file)
             <groupId>org.bouncycastle</groupId>
             <artifactId>bcprov-jdk15on</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.aaa</groupId>
+            <artifactId>aaa-encrypt-service</artifactId>
+            <version>0.6.0-SNAPSHOT</version>
+            <classifier>config</classifier>
+            <type>xml</type>
+        </dependency>
     </dependencies>
-</project>
\ No newline at end of file
+</project>
index f2d01b753ef4f3e3aa08f3f39b2d87ee051edbaf..f663445cc8bd13f940b48d24375fcdaa6f64b180 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.netconf.callhome.mount;
 
 import io.netty.util.concurrent.EventExecutor;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -27,9 +28,10 @@ abstract class BaseCallHomeTopology extends AbstractNetconfTopology {
                          final ThreadPool processingExecutor,
                          final SchemaRepositoryProvider schemaRepositoryProvider,
                          final DataBroker dataBroker,
-                         final DOMMountPointService mountPointService) {
+                         final DOMMountPointService mountPointService,
+                         final AAAEncryptionService encryptionService) {
         super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor,
-                processingExecutor, schemaRepositoryProvider, dataBroker, mountPointService);
+                processingExecutor, schemaRepositoryProvider, dataBroker, mountPointService, encryptionService);
         this.mountPointService = mountPointService;
     }
 }
index dab26d92c2253c7f343f0e30aba85fe7a297f31b..b8c2ba80905b31af884ecffede57efe211604e4d 100644 (file)
@@ -12,6 +12,7 @@ import io.netty.util.concurrent.EventExecutor;
 import io.netty.util.concurrent.FailedFuture;
 import io.netty.util.concurrent.Future;
 import java.net.InetSocketAddress;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -42,6 +43,7 @@ public class CallHomeMountDispatcher implements NetconfClientDispatcher, CallHom
     private final CallHomeMountSessionManager sessionManager;
     private final DataBroker dataBroker;
     private final DOMMountPointService mountService;
+    private final AAAEncryptionService encryptionService;
 
     protected CallHomeTopology topology;
 
@@ -53,13 +55,10 @@ public class CallHomeMountDispatcher implements NetconfClientDispatcher, CallHom
         }
     };
 
-    public CallHomeMountDispatcher(final String topologyId,
-                                   final EventExecutor eventExecutor,
-                                   final ScheduledThreadPool keepaliveExecutor,
-                                   final ThreadPool processingExecutor,
-                                   final SchemaRepositoryProvider schemaRepositoryProvider,
-                                   final DataBroker dataBroker,
-                                   final DOMMountPointService mountService) {
+    public CallHomeMountDispatcher(final String topologyId, final EventExecutor eventExecutor,
+            final ScheduledThreadPool keepaliveExecutor, final ThreadPool processingExecutor,
+            final SchemaRepositoryProvider schemaRepositoryProvider, final DataBroker dataBroker,
+            final DOMMountPointService mountService, final AAAEncryptionService encryptionService) {
         this.topologyId = topologyId;
         this.eventExecutor = eventExecutor;
         this.keepaliveExecutor = keepaliveExecutor;
@@ -68,6 +67,7 @@ public class CallHomeMountDispatcher implements NetconfClientDispatcher, CallHom
         this.sessionManager = new CallHomeMountSessionManager();
         this.dataBroker = dataBroker;
         this.mountService = mountService;
+        this.encryptionService = encryptionService;
     }
 
     @Override
@@ -91,15 +91,15 @@ public class CallHomeMountDispatcher implements NetconfClientDispatcher, CallHom
     }
 
     void createTopology() {
-        this.topology = new CallHomeTopology(topologyId, this, eventExecutor,
-                keepaliveExecutor, processingExecutor, schemaRepositoryProvider, dataBroker, mountService);
+        this.topology = new CallHomeTopology(topologyId, this, eventExecutor, keepaliveExecutor, processingExecutor,
+                schemaRepositoryProvider, dataBroker, mountService, encryptionService);
     }
 
     @Override
     public void onNetconfSubsystemOpened(final CallHomeProtocolSessionContext session,
-                                         final CallHomeChannelActivator activator) {
-        final CallHomeMountSessionContext deviceContext = getSessionManager()
-            .createSession(session, activator, onCloseHandler);
+            final CallHomeChannelActivator activator) {
+        final CallHomeMountSessionContext deviceContext =
+                getSessionManager().createSession(session, activator, onCloseHandler);
         final NodeId nodeId = deviceContext.getId();
         final Node configNode = deviceContext.getConfigNode();
         LOG.info("Provisioning fake config {}", configNode);
index c722f615ceaf91db612e557583de6f1f11cdc5cd..60ac1ff6a03eed74442a291068d27658c6112aac 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.netconf.callhome.mount;
 
 import io.netty.util.concurrent.EventExecutor;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -23,13 +24,12 @@ import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
 public class CallHomeTopology extends BaseCallHomeTopology {
 
     public CallHomeTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
-                            final EventExecutor eventExecutor,
-                            final ScheduledThreadPool keepaliveExecutor, final ThreadPool processingExecutor,
-                            final SchemaRepositoryProvider schemaRepositoryProvider,
-                            final DataBroker dataBroker, final DOMMountPointService mountPointService) {
-        super(topologyId, clientDispatcher, eventExecutor,
-                keepaliveExecutor, processingExecutor, schemaRepositoryProvider,
-                dataBroker, mountPointService);
+            final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
+            final ThreadPool processingExecutor, final SchemaRepositoryProvider schemaRepositoryProvider,
+            final DataBroker dataBroker, final DOMMountPointService mountPointService,
+            final AAAEncryptionService encryptionService) {
+        super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
+                schemaRepositoryProvider, dataBroker, mountPointService, encryptionService);
     }
 
     @Override
index 201c206282143538a087595ab9603a336ace62e4..3fdc8c9467d329db8b64e66e6fe1384d5e9ca931 100755 (executable)
@@ -23,6 +23,9 @@
                interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"/>
     <reference id="domMountPointService"
                interface="org.opendaylight.controller.md.sal.dom.api.DOMMountPointService"/>
+    <reference id="encryptionService"
+               interface="org.opendaylight.aaa.encrypt.AAAEncryptionService" />
+
 
     <bean id="schemaRepository" class="org.opendaylight.netconf.callhome.mount.SchemaRepositoryProviderImpl">
         <argument value="shared-schema-repository-impl"/>
@@ -44,6 +47,7 @@
         <argument ref="schemaRepository"/>
         <argument ref="dataBroker"/>
         <argument ref="domMountPointService"/>
+        <argument ref="encryptionService"/>
     </bean>
 
 </blueprint>
\ No newline at end of file
index 1b822413a55c5809679d0b53844f9ae2c18c63c1..b7d074eb506213273fed46da775136d9c6f9de38 100644 (file)
@@ -22,6 +22,7 @@ import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
 import org.junit.Before;
 import org.junit.Test;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -53,6 +54,7 @@ public class CallHomeMountDispatcherTest {
     private CallHomeMountSessionManager mockSessMgr;
     private CallHomeTopology mockTopology;
     private CallHomeProtocolSessionContext mockProtoSess;
+    private AAAEncryptionService mockEncryptionService;
 
     @Before
     public void setup() {
@@ -66,9 +68,10 @@ public class CallHomeMountDispatcherTest {
         mockSessMgr = mock(CallHomeMountSessionManager.class);
         mockTopology = mock(CallHomeTopology.class);
         mockProtoSess = mock(CallHomeProtocolSessionContext.class);
+        mockEncryptionService = mock(AAAEncryptionService.class);
 
         instance = new CallHomeMountDispatcher(topologyId, mockExecutor, mockKeepAlive,
-                mockProcessingExecutor, mockSchemaRepoProvider, mockDataBroker, mockMount) {
+                mockProcessingExecutor, mockSchemaRepoProvider, mockDataBroker, mockMount, mockEncryptionService) {
             @Override
             public CallHomeMountSessionManager getSessionManager() {
                 return mockSessMgr;
index 6cb6e9d668b96f192e14b66fafe31d374376ed2c..82d0ee0a1fa974fb865a2f36c0effc6ac0f25cf1 100644 (file)
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>mockito-configuration</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.aaa</groupId>
+      <artifactId>aaa-encrypt-service</artifactId>
+      <version>0.6.0-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 
   <build>
index 46cb2c717b314cb64548c553354087bf5df2f082..500791fc8280f234c11954d5a77a8d44f8645440 100644 (file)
@@ -11,28 +11,45 @@ package org.opendaylight.netconf.nettyutil.handler.ssh.authentication;
 import java.io.IOException;
 import org.apache.sshd.ClientSession;
 import org.apache.sshd.client.future.AuthFuture;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 
 /**
  * Class Providing username/password authentication option to
  * {@link org.opendaylight.netconf.nettyutil.handler.ssh.client.AsyncSshHandler}.
  */
 public class LoginPassword extends AuthenticationHandler {
+
     private final String username;
     private final String password;
+    private final AAAEncryptionService encryptionService;
 
     public LoginPassword(String username, String password) {
+        this(username, password, null);
+    }
+
+    public LoginPassword(final String username, final String password, final AAAEncryptionService encryptionService) {
         this.username = username;
         this.password = password;
+        this.encryptionService = encryptionService;
     }
 
     @Override
     public String getUsername() {
+        if (encryptionService != null) {
+            return encryptionService.decrypt(username);
+
+        }
         return username;
     }
 
     @Override
     public AuthFuture authenticate(final ClientSession session) throws IOException {
-        session.addPasswordIdentity(password);
+        if (encryptionService != null) {
+            final String decryptedPassword = encryptionService.decrypt(password);
+            session.addPasswordIdentity(decryptedPassword);
+        } else {
+            session.addPasswordIdentity(password);
+        }
         return session.auth();
     }
 }
index 11e922f34d9220a3f153a3bfce9671f7fbd2f52e..94dd257e45b81c28fb37751f1c13fbcaa8e91047 100755 (executable)
@@ -28,6 +28,9 @@
                interface="org.opendaylight.controller.md.sal.dom.api.DOMMountPointService"
                odl:type="default"/>
 
+    <reference id="encryptionService"
+               interface="org.opendaylight.aaa.encrypt.AAAEncryptionService" />
+
     <bean id="schemaRepository" class="org.opendaylight.netconf.topology.impl.SchemaRepositoryProviderImpl">
         <argument value="shared-schema-repository-impl"/>
     </bean>
         <argument ref="schemaRepository"/>
         <argument ref="dataBroker"/>
         <argument ref="mountPointService"/>
+        <argument ref="encryptionService" />
     </bean>
 
     <bean id="netconfConnectorFactory" class="org.opendaylight.netconf.topology.impl.NetconfConnectorFactoryImpl"/>
     <service ref="netconfConnectorFactory" interface="org.opendaylight.netconf.topology.api.NetconfConnectorFactory"
              odl:type="default"/>
 
-</blueprint>
\ No newline at end of file
+</blueprint>
index 5019b11bf162e90c4bfd821176e9c7fb73cec708..decd31e55455d4a2e0765108494a460609159304 100644 (file)
@@ -19,6 +19,7 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import javax.annotation.Nonnull;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.cluster.ActorSystemProvider;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
@@ -75,7 +76,7 @@ public class NetconfTopologyManager
     private final String topologyId;
     private final Duration writeTxIdleTimeout;
     private final DOMMountPointService mountPointService;
-
+    private final AAAEncryptionService encryptionService;
     private ListenerRegistration<NetconfTopologyManager> dataChangeListenerRegistration;
 
     public NetconfTopologyManager(final DataBroker dataBroker, final RpcProviderRegistry rpcProviderRegistry,
@@ -84,7 +85,9 @@ public class NetconfTopologyManager
                                   final ActorSystemProvider actorSystemProvider,
                                   final EventExecutor eventExecutor, final NetconfClientDispatcher clientDispatcher,
                                   final String topologyId, final Config config,
-                                  final DOMMountPointService mountPointService) {
+                                  final DOMMountPointService mountPointService,
+                                  final AAAEncryptionService encryptionService) {
+
         this.dataBroker = Preconditions.checkNotNull(dataBroker);
         this.rpcProviderRegistry = Preconditions.checkNotNull(rpcProviderRegistry);
         this.clusterSingletonServiceProvider = Preconditions.checkNotNull(clusterSingletonServiceProvider);
@@ -96,6 +99,7 @@ public class NetconfTopologyManager
         this.topologyId = Preconditions.checkNotNull(topologyId);
         this.writeTxIdleTimeout = Duration.apply(config.getWriteTransactionIdleTimeout(), TimeUnit.SECONDS);
         this.mountPointService = mountPointService;
+        this.encryptionService = Preconditions.checkNotNull(encryptionService);
     }
 
     // Blueprint init method
@@ -267,7 +271,8 @@ public class NetconfTopologyManager
                 .setTopologyId(topologyId)
                 .setNetconfClientDispatcher(clientDispatcher)
                 .setSchemaResourceDTO(NetconfTopologyUtils.setupSchemaCacheDTO(node))
-                .setIdleTimeout(writeTxIdleTimeout);
+                .setIdleTimeout(writeTxIdleTimeout)
+                .setEncryptionService(encryptionService);
 
         return builder.build();
     }
index f242558f051736bf43a05c37b610a90103c717d7..962e6b85f2cf779b6719402c588f5c875c1aaf0e 100644 (file)
@@ -26,6 +26,7 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import javax.annotation.Nullable;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.netconf.api.NetconfMessage;
 import org.opendaylight.netconf.client.NetconfClientSessionListener;
@@ -46,6 +47,7 @@ import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPrefe
 import org.opendaylight.netconf.sal.connect.netconf.listener.UserPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade;
 import org.opendaylight.netconf.sal.connect.netconf.schema.YangLibrarySchemaYangSourceProvider;
+import org.opendaylight.netconf.sal.connect.util.AuthEncryptor;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.netconf.topology.singleton.api.RemoteDeviceConnector;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfConnectorDTO;
@@ -78,6 +80,7 @@ public class RemoteDeviceConnectorImpl implements RemoteDeviceConnector {
     private final RemoteDeviceId remoteDeviceId;
     private final DOMMountPointService mountService;
     private final Timeout actorResponseWaitTime;
+    private final AAAEncryptionService encryptionService;
 
     private NetconfConnectorDTO deviceCommunicatorDTO;
 
@@ -89,6 +92,8 @@ public class RemoteDeviceConnectorImpl implements RemoteDeviceConnector {
         this.remoteDeviceId = remoteDeviceId;
         this.actorResponseWaitTime = actorResponseWaitTime;
         this.mountService = mountService;
+        this.encryptionService = netconfTopologyDeviceSetup.getEncryptionService();
+
     }
 
     @Override
@@ -96,6 +101,11 @@ public class RemoteDeviceConnectorImpl implements RemoteDeviceConnector {
 
         final NetconfNode netconfNode = netconfTopologyDeviceSetup.getNode().getAugmentation(NetconfNode.class);
         final NodeId nodeId = netconfTopologyDeviceSetup.getNode().getNodeId();
+
+        AuthEncryptor.encryptIfNeeded(nodeId, netconfNode, encryptionService,
+                netconfTopologyDeviceSetup.getTopologyId(),
+                netconfTopologyDeviceSetup.getDataBroker());
+
         Preconditions.checkNotNull(netconfNode.getHost());
         Preconditions.checkNotNull(netconfNode.getPort());
         Preconditions.checkNotNull(netconfNode.isTcpOnly());
@@ -280,7 +290,8 @@ public class RemoteDeviceConnectorImpl implements RemoteDeviceConnector {
                     ((org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf
                             .node.credentials.credentials.LoginPassword) credentials).getUsername(),
                     ((org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf
-                            .node.credentials.credentials.LoginPassword) credentials).getPassword());
+                            .node.credentials.credentials.LoginPassword) credentials).getPassword(),
+                            encryptionService);
         } else {
             throw new IllegalStateException(remoteDeviceId + ": Only login/password authentication is supported");
         }
index cee8c0d80774b077665c771a27a36142439872b1..23376b64501a1fadee9632c1d53f7d51f2ac4b88 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.netconf.topology.singleton.impl.utils;
 
 import akka.actor.ActorSystem;
 import io.netty.util.concurrent.EventExecutor;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -36,6 +37,7 @@ public class NetconfTopologySetup {
     private final String topologyId;
     private final NetconfDevice.SchemaResourcesDTO schemaResourceDTO;
     private final Duration idleTimeout;
+    private final AAAEncryptionService encryptionService;
 
     private NetconfTopologySetup(final NetconfTopologySetupBuilder builder) {
         this.clusterSingletonServiceProvider = builder.getClusterSingletonServiceProvider();
@@ -51,6 +53,7 @@ public class NetconfTopologySetup {
         this.topologyId = builder.getTopologyId();
         this.schemaResourceDTO = builder.getSchemaResourceDTO();
         this.idleTimeout = builder.getIdleTimeout();
+        this.encryptionService = builder.getEncryptionService();
     }
 
     public ClusterSingletonServiceProvider getClusterSingletonServiceProvider() {
@@ -105,6 +108,10 @@ public class NetconfTopologySetup {
         return idleTimeout;
     }
 
+    public AAAEncryptionService getEncryptionService() {
+        return encryptionService;
+    }
+
     public static class NetconfTopologySetupBuilder {
 
         private ClusterSingletonServiceProvider clusterSingletonServiceProvider;
@@ -120,6 +127,7 @@ public class NetconfTopologySetup {
         private NetconfClientDispatcher netconfClientDispatcher;
         private NetconfDevice.SchemaResourcesDTO schemaResourceDTO;
         private Duration idleTimeout;
+        private AAAEncryptionService encryptionService;
 
         public NetconfTopologySetupBuilder(){
         }
@@ -247,6 +255,15 @@ public class NetconfTopologySetup {
             return idleTimeout;
         }
 
+        private AAAEncryptionService getEncryptionService() {
+            return this.encryptionService;
+        }
+
+        public NetconfTopologySetupBuilder setEncryptionService(final AAAEncryptionService encryptionService) {
+            this.encryptionService = encryptionService;
+            return this;
+        }
+
         public static NetconfTopologySetupBuilder create() {
             return new NetconfTopologySetupBuilder();
         }
index 8c60682605e6f2534db9cc9bbdcb69cd67369368..f173a95a2a757fb0f476fb3475d25ef9b257e2c9 100644 (file)
@@ -39,6 +39,9 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
             binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.topology.singleton.config.rev170419.Config"
     />
 
+    <reference id="encryptionService"
+               interface="org.opendaylight.aaa.encrypt.AAAEncryptionService" />
+
     <bean id="netconfTopologyManager"
           class="org.opendaylight.netconf.topology.singleton.impl.NetconfTopologyManager"
           init-method="init" destroy-method="close">
@@ -53,6 +56,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
         <argument value="topology-netconf"/>
         <argument ref="singletonConfig"/>
         <argument ref="mountPointService"/>
+        <argument ref="encryptionService" />
     </bean>
     <service ref="netconfTopologyManager"
              interface="org.opendaylight.netconf.topology.singleton.api.NetconfTopologySingletonService"/>
index 817a58a5eca7eabd5800507c92c0aa00d33e5b83..0353f889ab5ed16b222c3f483d62efc3a7f2a71a 100644 (file)
@@ -32,6 +32,7 @@ import javax.annotation.Nonnull;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.cluster.ActorSystemProvider;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
@@ -84,11 +85,13 @@ public class NetconfTopologyManagerTest {
         final EventExecutor eventExecutor = mock(EventExecutor.class);
         final NetconfClientDispatcher clientDispatcher = mock(NetconfClientDispatcher.class);
         final DOMMountPointService mountPointService = mock(DOMMountPointService.class);
+        final AAAEncryptionService encryptionService = mock(AAAEncryptionService.class);
 
         final Config config = new ConfigBuilder().setWriteTransactionIdleTimeout(0).build();
         netconfTopologyManager = new NetconfTopologyManager(dataBroker, rpcProviderRegistry,
                 clusterSingletonServiceProvider, keepaliveExecutor, processingExecutor,
-                actorSystemProvider, eventExecutor, clientDispatcher, topologyId, config, mountPointService);
+                actorSystemProvider, eventExecutor, clientDispatcher, topologyId, config,
+                mountPointService, encryptionService);
     }
 
     @Test
index 9745e87c2db5e9e4ed746b0d26f724a6d781844b..4aeb5de1a14cafa552196638581165b28e77c7c8 100644 (file)
@@ -32,6 +32,7 @@ import java.util.concurrent.ExecutorService;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
@@ -105,6 +106,9 @@ public class RemoteDeviceConnectorImplTest {
     @Mock
     private WriteTransaction writeTx;
 
+    @Mock
+    private AAAEncryptionService encryptionService;
+
     private NetconfTopologySetup.NetconfTopologySetupBuilder builder;
     private RemoteDeviceId remoteDeviceId;
 
@@ -130,6 +134,7 @@ public class RemoteDeviceConnectorImplTest {
         builder.setEventExecutor(eventExecutor);
         builder.setNetconfClientDispatcher(clientDispatcher);
         builder.setTopologyId(TOPOLOGY_ID);
+        builder.setEncryptionService(encryptionService);
     }
 
     @Test
@@ -258,7 +263,7 @@ public class RemoteDeviceConnectorImplTest {
         assertEquals(defaultClientConfig.getAddress(), new InetSocketAddress(InetAddresses.forString("127.0.0.1"),
             9999));
         assertSame(defaultClientConfig.getSessionListener(), listener);
-        assertEquals(defaultClientConfig.getAuthHandler().getUsername(), "testuser");
+        assertEquals(defaultClientConfig.getAuthHandler().getUsername(), encryptionService.encrypt("testuser"));
         assertEquals(defaultClientConfig.getProtocol(), NetconfClientConfiguration.NetconfClientProtocol.TCP);
     }
 }
index ad4bfa9029425205ccab65efdf3bc4600395a493..c7f5cf450988efd12356880aff73404aa1edc550 100644 (file)
@@ -24,6 +24,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -49,6 +50,7 @@ import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPrefe
 import org.opendaylight.netconf.sal.connect.netconf.listener.UserPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade;
 import org.opendaylight.netconf.sal.connect.netconf.schema.YangLibrarySchemaYangSourceProvider;
+import org.opendaylight.netconf.sal.connect.util.AuthEncryptor;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.netconf.topology.api.NetconfTopology;
 import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
@@ -167,11 +169,14 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
 
     protected final HashMap<NodeId, NetconfConnectorDTO> activeConnectors = new HashMap<>();
 
+    protected final AAAEncryptionService encryptionService;
+
     protected AbstractNetconfTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
                                       final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
                                       final ThreadPool processingExecutor,
                                       final SchemaRepositoryProvider schemaRepositoryProvider,
-                                      final DataBroker dataBroker, final DOMMountPointService mountPointService) {
+                                      final DataBroker dataBroker, final DOMMountPointService mountPointService,
+                                      final AAAEncryptionService encryptionService) {
         this.topologyId = topologyId;
         this.clientDispatcher = clientDispatcher;
         this.eventExecutor = eventExecutor;
@@ -180,6 +185,7 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
         this.sharedSchemaRepository = schemaRepositoryProvider.getSharedSchemaRepository();
         this.dataBroker = dataBroker;
         this.mountPointService = mountPointService;
+        this.encryptionService = encryptionService;
     }
 
     public void setSchemaRegistry(final SchemaSourceRegistry schemaRegistry) {
@@ -215,6 +221,8 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
                                                                         final Node configNode) {
         final NetconfNode netconfNode = configNode.getAugmentation(NetconfNode.class);
 
+        AuthEncryptor.encryptIfNeeded(nodeId, netconfNode, encryptionService, topologyId, dataBroker);
+
         Preconditions.checkNotNull(netconfNode.getHost());
         Preconditions.checkNotNull(netconfNode.getPort());
         Preconditions.checkNotNull(netconfNode.isTcpOnly());
@@ -423,7 +431,8 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
                     ((org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114
                             .netconf.node.credentials.credentials.LoginPassword) credentials).getUsername(),
                     ((org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114
-                            .netconf.node.credentials.credentials.LoginPassword) credentials).getPassword());
+                            .netconf.node.credentials.credentials.LoginPassword) credentials).getPassword(),
+                    encryptionService);
         } else {
             throw new IllegalStateException("Only login/password authentification is supported");
         }
index 97bf00a5fdbce8e4385447f046c23c79da3c5cb6..41e4ef62fd98a51e34934fb707e2e0cf9e8714ed 100644 (file)
@@ -13,6 +13,7 @@ import com.google.common.util.concurrent.Futures;
 import io.netty.util.concurrent.EventExecutor;
 import java.util.Collection;
 import javax.annotation.Nonnull;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -53,9 +54,10 @@ public class NetconfTopologyImpl extends AbstractNetconfTopology
                                final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
                                final ThreadPool processingExecutor,
                                final SchemaRepositoryProvider schemaRepositoryProvider,
-                               final DataBroker dataBroker, final DOMMountPointService mountPointService) {
+                               final DataBroker dataBroker, final DOMMountPointService mountPointService,
+                               final AAAEncryptionService encryptionService) {
         super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
-                schemaRepositoryProvider, dataBroker, mountPointService);
+                schemaRepositoryProvider, dataBroker, mountPointService, encryptionService);
     }
 
     @Override
index 52272916356f669dbdff8d814e05a262c4608c84..48df0a6c03685391b467d65b6ba7b9cc61bce99d 100644 (file)
@@ -29,6 +29,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -89,6 +90,9 @@ public class NetconfTopologyImplTest {
     @Mock
     private DOMMountPointService mountPointService;
 
+    @Mock
+    private AAAEncryptionService encryptionService;
+
     private TestingNetconfTopologyImpl topology;
     private TestingNetconfTopologyImpl spyTopology;
 
@@ -105,7 +109,7 @@ public class NetconfTopologyImplTest {
 
         topology = new TestingNetconfTopologyImpl(TOPOLOGY_ID, mockedClientDispatcher,
                 mockedEventExecutor, mockedKeepaliveExecutor, mockedProcessingExecutor, mockedSchemaRepositoryProvider,
-                dataBroker, mountPointService);
+                dataBroker, mountPointService, encryptionService);
 
         spyTopology = spy(topology);
     }
@@ -192,9 +196,10 @@ public class NetconfTopologyImplTest {
                 final String topologyId, final NetconfClientDispatcher clientDispatcher,
                 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
                 final ThreadPool processingExecutor, final SchemaRepositoryProvider schemaRepositoryProvider,
-                final DataBroker dataBroker, final DOMMountPointService mountPointService) {
+                final DataBroker dataBroker, final DOMMountPointService mountPointService,
+                final AAAEncryptionService encryptionService) {
             super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor,
-                    processingExecutor, schemaRepositoryProvider, dataBroker, mountPointService);
+                    processingExecutor, schemaRepositoryProvider, dataBroker, mountPointService, encryptionService);
         }
 
         @Override
diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/util/AuthEncryptor.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/util/AuthEncryptor.java
new file mode 100644 (file)
index 0000000..28a9171
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2016 Brocade Communication Systems and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netconf.sal.connect.util;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *  Utility to encrypt netconf username and password.
+ */
+public class AuthEncryptor {
+    private static final Logger LOG = LoggerFactory.getLogger(AuthEncryptor.class);
+
+    public static void encryptIfNeeded(final NodeId nodeId, final NetconfNode netconfNode,
+                                 AAAEncryptionService encryptionService,
+                                 final String topologyId, final DataBroker dataBroker) {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node
+                .credentials.credentials.LoginPassword creds =
+                (org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node
+                        .credentials.credentials.LoginPassword) netconfNode.getCredentials();
+        final String decryptedPassword = encryptionService.decrypt(creds.getPassword());
+        if (decryptedPassword != null && decryptedPassword.equals(creds.getPassword())) {
+            LOG.info("Encrypting the provided credentials");
+            final String username = encryptionService.encrypt(creds.getUsername());
+            final String password = encryptionService.encrypt(creds.getPassword());
+            final org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node
+                    .credentials.credentials.LoginPasswordBuilder passwordBuilder =
+                    new org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114
+                            .netconf.node.credentials.credentials.LoginPasswordBuilder();
+            passwordBuilder.setUsername(username);
+            passwordBuilder.setPassword(password);
+            final NetconfNodeBuilder nnb = new NetconfNodeBuilder();
+            nnb.setCredentials(passwordBuilder.build());
+
+            final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+            final InstanceIdentifier<NetworkTopology> networkTopologyId =
+                    InstanceIdentifier.builder(NetworkTopology.class).build();
+            final InstanceIdentifier<NetconfNode> niid = networkTopologyId.child(Topology.class,
+                    new TopologyKey(new TopologyId(topologyId))).child(Node.class,
+                    new NodeKey(nodeId)).augmentation(NetconfNode.class);
+            writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, niid, nnb.build());
+            final CheckedFuture<Void, TransactionCommitFailedException> future = writeTransaction.submit();
+            Futures.addCallback(future, new FutureCallback<Void>() {
+
+                @Override
+                public void onSuccess(Void result) {
+                    LOG.info("Encrypted netconf username/password successfully");
+                }
+
+                @Override
+                public void onFailure(Throwable exception) {
+                    LOG.error("Unable to encrypt netconf username/password." + exception.getMessage());
+                }
+            });
+        }
+    }
+}