Netconf SSH user authentication using UserManager
[controller.git] / opendaylight / netconf / netconf-ssh / src / main / java / org / opendaylight / controller / netconf / osgi / NetconfSSHActivator.java
index d2f6c8c81ce749a234d7ae2d433dad953e2e20c6..3b513790bd128806a7ef1bec2561bd90fee6420a 100644 (file)
@@ -10,9 +10,14 @@ package org.opendaylight.controller.netconf.osgi;
 import com.google.common.base.Optional;
 import java.net.InetSocketAddress;
 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
+import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
 import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
+import org.opendaylight.controller.usermanager.IUserManager;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -30,18 +35,58 @@ public class NetconfSSHActivator implements BundleActivator{
 
     private NetconfSSHServer server;
     private static final Logger logger =  LoggerFactory.getLogger(NetconfSSHActivator.class);
+    private static final String EXCEPTION_MESSAGE = "Netconf ssh bridge is not available.";
+    private IUserManager iUserManager;
+    private BundleContext context = null;
+
+    ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>(){
+        @Override
+        public IUserManager addingService(ServiceReference<IUserManager> reference) {
+            logger.info("Service IUserManager added, let there be SSH bridge.");
+            iUserManager =  context.getService(reference);
+            try {
+                onUserManagerFound(iUserManager);
+            } catch (Exception e) {
+                logger.trace("Can't start SSH server due to {}",e);
+            }
+            return iUserManager;
+        }
+        @Override
+        public void modifiedService(ServiceReference<IUserManager> reference, IUserManager service) {
+            logger.info("Replacing modified service IUserManager in netconf SSH.");
+            server.addUserManagerService(service);
+        }
+        @Override
+        public void removedService(ServiceReference<IUserManager> reference, IUserManager service) {
+            logger.info("Removing service IUserManager from netconf SSH. " +
+                    "SSH won't authenticate users until IUserManeger service will be started.");
+            removeUserManagerService();
+        }
+    };
+
 
     @Override
     public void start(BundleContext context) throws Exception {
+        this.context = context;
+        listenForManagerService();
+    }
 
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        if (server != null){
+            server.stop();
+            logger.trace("Netconf SSH bridge is down ...");
+        }
+    }
+    private void startSSHServer() throws Exception {
         logger.trace("Starting netconf SSH  bridge.");
-
-        Optional<InetSocketAddress> sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context);
+        Optional<InetSocketAddress> sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context, EXCEPTION_MESSAGE);
         InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,
-                "TCP is not configured, netconf ssh bridge is not available.");
+                EXCEPTION_MESSAGE, true);
 
         if (sshSocketAddressOptional.isPresent()){
-            server = NetconfSSHServer.start(sshSocketAddressOptional.get().getPort(),tcpSocketAddress);
+            AuthProvider authProvider = new AuthProvider(iUserManager);
+            this.server = NetconfSSHServer.start(sshSocketAddressOptional.get().getPort(),tcpSocketAddress,authProvider);
             Thread serverThread = new  Thread(server,"netconf SSH server thread");
             serverThread.setDaemon(true);
             serverThread.start();
@@ -51,13 +96,18 @@ public class NetconfSSHActivator implements BundleActivator{
             throw new Exception("No valid connection configuration for SSH bridge found.");
         }
     }
-
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        if (server != null){
-            logger.trace("Netconf SSH bridge going down ...");
-            server.stop();
-            logger.trace("Netconf SSH bridge is down ...");
+    private void onUserManagerFound(IUserManager userManager) throws Exception{
+        if (server!=null && server.isUp()){
+           server.addUserManagerService(userManager);
+        } else {
+           startSSHServer();
         }
     }
+    private void removeUserManagerService(){
+        this.server.removeUserManagerService();
+    }
+    private void listenForManagerService(){
+        ServiceTracker<IUserManager, IUserManager> listenerTracker = new ServiceTracker<>(context, IUserManager.class,customizer);
+        listenerTracker.open();
+    }
 }