From: Martin Bobak Date: Thu, 12 Dec 2013 14:47:01 +0000 (+0100) Subject: Netconf SSH user authentication using UserManager X-Git-Tag: jenkins-controller-bulk-release-prepare-only-2-1~179^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=0818295c3e0c6878853cb87285452854b565a6dd Netconf SSH user authentication using UserManager Change-Id: I48112f86cf8f839d5cbfdc62f0b7a6866118ed25 Signed-off-by: Martin Bobak --- diff --git a/opendaylight/netconf/netconf-it/pom.xml b/opendaylight/netconf/netconf-it/pom.xml index f2de91ef46..31248137e8 100644 --- a/opendaylight/netconf/netconf-it/pom.xml +++ b/opendaylight/netconf/netconf-it/pom.xml @@ -91,6 +91,12 @@ netconf-ssh test + + ${project.groupId} + netconf-ssh + test + test-jar + ${project.groupId} netconf-util diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java index c61dab7f64..4818b5f0a3 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java @@ -8,18 +8,14 @@ package org.opendaylight.controller.netconf.it; -import static java.util.Collections.emptyList; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; +import ch.ethz.ssh2.Connection; +import ch.ethz.ssh2.Session; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.HashedWheelTimer; - import java.io.IOException; import java.io.InputStream; import java.lang.management.ManagementFactory; @@ -31,12 +27,9 @@ import java.util.Collections; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; - import javax.management.ObjectName; import javax.xml.parsers.ParserConfigurationException; - import junit.framework.Assert; - import org.junit.After; import org.junit.Before; import org.junit.Ignore; @@ -51,6 +44,7 @@ import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactor import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory; import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleMXBean; import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory; +import org.opendaylight.controller.netconf.StubUserManager; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.client.NetconfClient; import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; @@ -68,6 +62,7 @@ import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFact import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.controller.netconf.ssh.NetconfSSHServer; +import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider; import org.opendaylight.controller.netconf.util.test.XmlFileLoader; import org.opendaylight.controller.netconf.util.xml.ExiParameters; import org.opendaylight.controller.netconf.util.xml.XmlElement; @@ -79,12 +74,13 @@ import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.xml.sax.SAXException; - -import ch.ethz.ssh2.Connection; -import ch.ethz.ssh2.Session; - -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; +import static java.util.Collections.emptyList; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; public class NetconfITTest extends AbstractConfigTest { @@ -435,7 +431,9 @@ public class NetconfITTest extends AbstractConfigTest { private void startSSHServer() throws Exception{ logger.info("Creating SSH server"); - Thread sshServerThread = new Thread(NetconfSSHServer.start(10830,tcpAddress)); + StubUserManager um = new StubUserManager(USERNAME,PASSWORD); + AuthProvider ap = new AuthProvider(um); + Thread sshServerThread = new Thread(NetconfSSHServer.start(10830,tcpAddress,ap)); sshServerThread.setDaemon(true); sshServerThread.start(); logger.info("SSH server on"); diff --git a/opendaylight/netconf/netconf-ssh/pom.xml b/opendaylight/netconf/netconf-ssh/pom.xml index f60b4b02f5..5dde0448bd 100644 --- a/opendaylight/netconf/netconf-ssh/pom.xml +++ b/opendaylight/netconf/netconf-ssh/pom.xml @@ -33,10 +33,28 @@ commons-io commons-io + + org.opendaylight.controller + usermanager + 0.4.1-SNAPSHOT + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + package + + test-jar + + + + org.apache.felix maven-bundle-plugin @@ -55,9 +73,13 @@ org.apache.commons.io, org.opendaylight.controller.netconf.util, org.opendaylight.controller.netconf.util.osgi, + org.opendaylight.controller.usermanager, + org.opendaylight.controller.sal.authorization, + org.opendaylight.controller.sal.utils, org.opendaylight.protocol.framework, org.osgi.framework, - org.slf4j + org.osgi.util.tracker, + org.slf4j, diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/osgi/NetconfSSHActivator.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/osgi/NetconfSSHActivator.java index b91824866a..3b513790bd 100644 --- a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/osgi/NetconfSSHActivator.java +++ b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/osgi/NetconfSSHActivator.java @@ -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; @@ -31,18 +36,57 @@ 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 customizer = new ServiceTrackerCustomizer(){ + @Override + public IUserManager addingService(ServiceReference 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 reference, IUserManager service) { + logger.info("Replacing modified service IUserManager in netconf SSH."); + server.addUserManagerService(service); + } + @Override + public void removedService(ServiceReference 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 sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context,EXCEPTION_MESSAGE); + Optional sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context, EXCEPTION_MESSAGE); InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context, 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(); @@ -52,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 listenerTracker = new ServiceTracker<>(context, IUserManager.class,customizer); + listenerTracker.open(); + } } diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java index 72135cc7dc..45807a8333 100644 --- a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java +++ b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java @@ -12,20 +12,23 @@ import java.net.InetSocketAddress; import java.net.ServerSocket; import java.util.concurrent.atomic.AtomicLong; import javax.annotation.concurrent.ThreadSafe; +import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider; import org.opendaylight.controller.netconf.ssh.threads.SocketThread; +import org.opendaylight.controller.usermanager.IUserManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @ThreadSafe public class NetconfSSHServer implements Runnable { - private static boolean acceptMore = true; private ServerSocket ss = null; private static final Logger logger = LoggerFactory.getLogger(NetconfSSHServer.class); private static final AtomicLong sesssionId = new AtomicLong(); private final InetSocketAddress clientAddress; + private final AuthProvider authProvider; + private boolean up = false; - private NetconfSSHServer(int serverPort,InetSocketAddress clientAddress) throws Exception{ + private NetconfSSHServer(int serverPort,InetSocketAddress clientAddress, AuthProvider authProvider) throws Exception{ logger.trace("Creating SSH server socket on port {}",serverPort); this.ss = new ServerSocket(serverPort); @@ -34,27 +37,37 @@ public class NetconfSSHServer implements Runnable { } logger.trace("Server socket created."); this.clientAddress = clientAddress; - + this.authProvider = authProvider; + this.up = true; } - - public static NetconfSSHServer start(int serverPort, InetSocketAddress clientAddress) throws Exception { - return new NetconfSSHServer(serverPort, clientAddress); + public static NetconfSSHServer start(int serverPort, InetSocketAddress clientAddress,AuthProvider authProvider) throws Exception { + return new NetconfSSHServer(serverPort, clientAddress,authProvider); } public void stop() throws Exception { - acceptMore = false; + up = false; logger.trace("Closing SSH server socket."); ss.close(); logger.trace("SSH server socket closed."); } + public void removeUserManagerService(){ + this.authProvider.removeUserManagerService(); + } + + public void addUserManagerService(IUserManager userManagerService){ + this.authProvider.addUserManagerService(userManagerService); + } + public boolean isUp(){ + return this.up; + } @Override public void run() { - while (acceptMore) { + while (up) { logger.trace("Starting new socket thread."); try { - SocketThread.start(ss.accept(), clientAddress, sesssionId.incrementAndGet()); + SocketThread.start(ss.accept(), clientAddress, sesssionId.incrementAndGet(),authProvider); } catch (IOException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProvider.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProvider.java new file mode 100644 index 0000000000..a73dfdfd49 --- /dev/null +++ b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProvider.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. 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.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; +import org.apache.commons.io.IOUtils; +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; + +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"; + + + public AuthProvider(IUserManager ium) throws Exception { + + this.um = ium; + + if (this.um == null){ + throw new Exception("No usermanager service available."); + } + + List roles = new ArrayList(1); + roles.add(UserLevel.SYSTEMADMIN.toString()); + this.um.addLocalUser(new UserConfig(DEAFULT_USER, DEAFULT_PASSWORD, roles)); + } + @Override + public boolean authenticated(String username, String password) throws Exception { + if (this.um == null){ + throw new Exception("No usermanager service available."); + } + AuthResultEnum authResult = this.um.authenticate(username,password); + if (authResult.equals(AuthResultEnum.AUTH_ACCEPT) || authResult.equals(AuthResultEnum.AUTH_ACCEPT_LOC)){ + return true; + } + return false; + } + + @Override + public char[] getPEMAsCharArray() { + + InputStream is = getClass().getResourceAsStream("/RSA.pk"); + try { + return IOUtils.toCharArray(is); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public void removeUserManagerService() { + this.um = null; + } + + @Override + public void addUserManagerService(IUserManager userManagerService) { + this.um = userManagerService; + } + + +} diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/KeyStoreHandler.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProviderInterface.java similarity index 52% rename from opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/KeyStoreHandler.java rename to opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProviderInterface.java index 59a911b207..71f1cc350f 100644 --- a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/KeyStoreHandler.java +++ b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProviderInterface.java @@ -1,3 +1,4 @@ + /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -7,8 +8,12 @@ */ package org.opendaylight.controller.netconf.ssh.authentication; -import ch.ethz.ssh2.signature.RSAPrivateKey; +import org.opendaylight.controller.usermanager.IUserManager; + +public interface AuthProviderInterface { -public interface KeyStoreHandler { - public RSAPrivateKey getPrivateKey(); + public boolean authenticated(String username, String password) throws Exception; + public char[] getPEMAsCharArray(); + public void removeUserManagerService(); + public void addUserManagerService(IUserManager userManagerService); } diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/RSAKey.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/RSAKey.java deleted file mode 100644 index b420b33a7b..0000000000 --- a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/RSAKey.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. 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.controller.netconf.ssh.authentication; - -import ch.ethz.ssh2.signature.RSAPrivateKey; - -import java.math.BigInteger; - -public class RSAKey implements KeyStoreHandler { - - private static RSAPrivateKey hostkey = null; - private static String user = "netconf"; - private static String password = "netconf"; - static { - - BigInteger p = new BigInteger("2967886344240998436887630478678331145236162666668503940430852241825039192450179076148979094256007292741704260675085192441025058193581327559331546948442042987131728039318861235625879376246169858586459472691398815098207618446039"); //.BigInteger.probablePrime(N / 2, rnd); - BigInteger q = new BigInteger("4311534819291430017572425052029278681302539382618633848168923130451247487970187151403375389974616614405320169278870943605377518341666894603659873284783174749122655429409273983428000534304828056597676444751611433784228298909767"); //BigInteger.probablePrime(N / 2, rnd); - BigInteger phi = (p.subtract(BigInteger.ONE)).multiply(q.subtract(BigInteger.ONE)); - - BigInteger n = p.multiply(q); - BigInteger e = new BigInteger("65537"); - BigInteger d = e.modInverse(phi); - - hostkey = new RSAPrivateKey(d, e, n); - } - - @Override - public RSAPrivateKey getPrivateKey() { - return hostkey; - } -} diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/SocketThread.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/SocketThread.java index 15d99a44ee..e5da03b4cf 100644 --- a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/SocketThread.java +++ b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/SocketThread.java @@ -13,7 +13,7 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import javax.annotation.concurrent.ThreadSafe; -import org.opendaylight.controller.netconf.ssh.authentication.RSAKey; +import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,27 +30,38 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser private long sessionId; private String currentUser; private final String remoteAddressWithPort; + private final AuthProvider authProvider; - public static void start(Socket socket, InetSocketAddress clientAddress, long sessionId) throws IOException{ - Thread netconf_ssh_socket_thread = new Thread(new SocketThread(socket,clientAddress,sessionId)); + public static void start(Socket socket, + InetSocketAddress clientAddress, + long sessionId, + AuthProvider authProvider) throws IOException{ + Thread netconf_ssh_socket_thread = new Thread(new SocketThread(socket,clientAddress,sessionId,authProvider)); netconf_ssh_socket_thread.setDaemon(true); netconf_ssh_socket_thread.start(); } - private SocketThread(Socket socket, InetSocketAddress clientAddress, long sessionId) throws IOException { + private SocketThread(Socket socket, + InetSocketAddress clientAddress, + long sessionId, + AuthProvider authProvider) throws IOException { this.socket = socket; this.clientAddress = clientAddress; this.sessionId = sessionId; this.remoteAddressWithPort = socket.getRemoteSocketAddress().toString().replaceFirst("/",""); + this.authProvider = authProvider; } @Override public void run() { conn = new ServerConnection(socket); - RSAKey keyStore = new RSAKey(); - conn.setRsaHostKey(keyStore.getPrivateKey()); + try { + conn.setPEMHostKey(authProvider.getPEMAsCharArray(),"netconf"); + } catch (IOException e) { + e.printStackTrace(); + } conn.setAuthenticationCallback(this); conn.setServerConnectionCallback(this); try { @@ -90,7 +101,7 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser netconf_ssh_output.start(); } catch (Throwable t){ - logger.error(t.getMessage(),t); + logger.error("SSH bridge couldn't create echo socket",t.getMessage(),t); try { if (netconf_ssh_input!=null){ @@ -166,13 +177,16 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser public AuthenticationResult authenticateWithPassword(ServerConnection sc, String username, String password) { - if (USER.equals(username) && PASSWORD.equals(password)){ - currentUser = username; - logger.trace("user {}@{} authenticated",currentUser,remoteAddressWithPort); - return AuthenticationResult.SUCCESS; - } - + try { + if (authProvider.authenticated(username,password)){ + currentUser = username; + logger.trace("user {}@{} authenticated",currentUser,remoteAddressWithPort); + return AuthenticationResult.SUCCESS; + } + } catch (Exception e){ + logger.info("Authentication failed due to :" + e.getLocalizedMessage()); + } return AuthenticationResult.FAILURE; } diff --git a/opendaylight/netconf/netconf-ssh/src/main/resources/RSA.pk b/opendaylight/netconf/netconf-ssh/src/main/resources/RSA.pk new file mode 100644 index 0000000000..c0266c7bd2 --- /dev/null +++ b/opendaylight/netconf/netconf-ssh/src/main/resources/RSA.pk @@ -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----- diff --git a/opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/ssh/SSHServerTest.java b/opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/SSHServerTest.java similarity index 53% rename from opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/ssh/SSHServerTest.java rename to opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/SSHServerTest.java index 54bc7bc4b6..62396ed87a 100644 --- a/opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/ssh/SSHServerTest.java +++ b/opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/SSHServerTest.java @@ -5,15 +5,14 @@ * 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.controller.netconf.ssh; +package org.opendaylight.controller.netconf; import ch.ethz.ssh2.Connection; -import ch.ethz.ssh2.Session; -import java.io.IOException; import java.net.InetSocketAddress; import junit.framework.Assert; -import org.apache.commons.io.IOUtils; import org.junit.Test; +import org.opendaylight.controller.netconf.ssh.NetconfSSHServer; +import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,36 +25,37 @@ public class SSHServerTest { private static final int PORT = 1830; private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 8383); private static final Logger logger = LoggerFactory.getLogger(SSHServerTest.class); + private Thread sshServerThread; + + + -// @Before public void startSSHServer() throws Exception{ - logger.info("Creating SSH server"); - NetconfSSHServer server = NetconfSSHServer.start(PORT,tcpAddress); - Thread sshServerThread = new Thread(server); - sshServerThread.setDaemon(true); - sshServerThread.start(); - logger.info("SSH server on"); + logger.info("Creating SSH server"); + StubUserManager um = new StubUserManager(USER,PASSWORD); + AuthProvider ap = new AuthProvider(um); + NetconfSSHServer server = NetconfSSHServer.start(PORT,tcpAddress,ap); + sshServerThread = new Thread(server); + sshServerThread.setDaemon(true); + sshServerThread.start(); + logger.info("SSH server on"); } @Test public void connect(){ - Connection conn = new Connection(HOST,PORT); - Assert.assertNotNull(conn); try { + this.startSSHServer(); + Connection conn = new Connection(HOST,PORT); + Assert.assertNotNull(conn); logger.info("connecting to SSH server"); conn.connect(); logger.info("authenticating ..."); boolean isAuthenticated = conn.authenticateWithPassword(USER,PASSWORD); Assert.assertTrue(isAuthenticated); - logger.info("opening session"); - Session sess = conn.openSession(); - logger.info("subsystem netconf"); - sess.startSubSystem("netconf"); - sess.getStdin().write("urn:ietf:params:netconf:base:1.1]]>]]>".getBytes()); - IOUtils.copy(sess.getStdout(), System.out); - } catch (IOException e) { - e.printStackTrace(); + } catch (Exception e) { + logger.error("Error while starting SSH server.", e); } + } } diff --git a/opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/StubUserManager.java b/opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/StubUserManager.java new file mode 100644 index 0000000000..4a3a650ecd --- /dev/null +++ b/opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/StubUserManager.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. 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.controller.netconf; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.opendaylight.controller.sal.authorization.AuthResultEnum; +import org.opendaylight.controller.sal.authorization.UserLevel; +import org.opendaylight.controller.sal.utils.Status; +import org.opendaylight.controller.sal.utils.StatusCode; +import org.opendaylight.controller.usermanager.AuthorizationConfig; +import org.opendaylight.controller.usermanager.ISessionManager; +import org.opendaylight.controller.usermanager.IUserManager; +import org.opendaylight.controller.usermanager.ServerConfig; +import org.opendaylight.controller.usermanager.UserConfig; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.web.context.SecurityContextRepository; + +public class StubUserManager implements IUserManager{ + + + private static String user; + private static String password; + + public StubUserManager(String user, String password){ + this.user = user; + this.password = password; + } + @Override + public List getUserRoles(String userName) { + return null; + } + + @Override + public AuthResultEnum authenticate(String username, String password) { + if (this.user.equals(username) && this.password.equals(password)){ + return AuthResultEnum.AUTH_ACCEPT_LOC; + } + return AuthResultEnum.AUTH_REJECT_LOC; + } + + @Override + public Status addAAAServer(ServerConfig configObject) { + return null; + } + + @Override + public Status removeAAAServer(ServerConfig configObject) { + return null; + } + + @Override + public Status addLocalUser(UserConfig configObject) { + return new Status(StatusCode.SUCCESS); + } + + @Override + public Status modifyLocalUser(UserConfig configObject) { + return null; + } + + @Override + public Status removeLocalUser(UserConfig configObject) { + return null; + } + + @Override + public Status removeLocalUser(String userName) { + return null; + } + + @Override + public Status addAuthInfo(AuthorizationConfig AAAconf) { + return null; + } + + @Override + public Status removeAuthInfo(AuthorizationConfig AAAconf) { + return null; + } + + @Override + public List getAuthorizationList() { + return null; + } + + @Override + public Set getAAAProviderNames() { + return null; + } + + @Override + public Status changeLocalUserPassword(String user, String curPassword, String newPassword) { + return null; + } + + @Override + public List getAAAServerList() { + return null; + } + + @Override + public List getLocalUserList() { + return null; + } + + @Override + public Status saveLocalUserList() { + return null; + } + + @Override + public Status saveAAAServerList() { + return null; + } + + @Override + public Status saveAuthorizationList() { + return null; + } + + @Override + public void userLogout(String username) { + + } + + @Override + public void userTimedOut(String username) { + + } + + @Override + public Map> getUserLoggedIn() { + return null; + } + + @Override + public String getAccessDate(String user) { + return null; + } + + @Override + public UserLevel getUserLevel(String userName) { + return null; + } + + @Override + public List getUserLevels(String userName) { + return null; + } + + @Override + public SecurityContextRepository getSecurityContextRepo() { + return null; + } + + @Override + public ISessionManager getSessionManager() { + return null; + } + + @Override + public boolean isRoleInUse(String role) { + return false; + } + + @Override + public String getPassword(String username) { + return null; + } + + @Override + public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { + return null; + } + +} diff --git a/opendaylight/netconf/pom.xml b/opendaylight/netconf/pom.xml index e70df1b949..c4b1467220 100644 --- a/opendaylight/netconf/pom.xml +++ b/opendaylight/netconf/pom.xml @@ -148,6 +148,12 @@ netconf-ssh ${netconf.version} + + ${project.groupId} + netconf-ssh + ${netconf.version} + test-jar + ${project.groupId} netconf-mapping-api diff --git a/opendaylight/usermanager/implementation/pom.xml b/opendaylight/usermanager/implementation/pom.xml index 4eedf7eda9..dcdc2f6d50 100644 --- a/opendaylight/usermanager/implementation/pom.xml +++ b/opendaylight/usermanager/implementation/pom.xml @@ -51,10 +51,10 @@ org.opendaylight.controller.usermanager - + --> org.opendaylight.controller.usermanager.internal.Activator