X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fnetconf%2Fnetconf-it%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetconf%2Fit%2FNetconfITSecureTest.java;h=bc8efbe91535573cc18bcd00d97e43dcf91abc2f;hp=cc9e8c367a9f3d2871842510daddd29aa95ea441;hb=2473df9920f0820fde7dcaf62eaf14166695a5f6;hpb=f3714846c0eedf09fe83844c0dc30889f790fbc2 diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java index cc9e8c367a..bc8efbe915 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java @@ -8,91 +8,191 @@ package org.opendaylight.controller.netconf.it; -import io.netty.channel.ChannelFuture; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import io.netty.channel.local.LocalAddress; +import io.netty.util.concurrent.GlobalEventExecutor; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; -import org.opendaylight.controller.config.spi.ModuleFactory; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.netconf.api.NetconfMessage; +import org.opendaylight.controller.netconf.auth.AuthProvider; import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; -import org.opendaylight.controller.netconf.client.test.TestingNetconfClient; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException; -import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; -import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import java.io.IOException; -import java.io.InputStream; -import java.lang.management.ManagementFactory; -import java.net.InetSocketAddress; -import java.security.KeyManagementException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; -import java.util.Collection; -import java.util.List; +import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl; +import org.opendaylight.controller.netconf.client.NetconfClientSessionListener; +import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder; +import org.opendaylight.controller.netconf.client.TestingNetconfClient; +import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler; +import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.LoginPassword; +import org.opendaylight.controller.netconf.ssh.NetconfSSHServer; +import org.opendaylight.controller.netconf.ssh.authentication.PEMGenerator; +import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil; +import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.opendaylight.controller.sal.connect.api.RemoteDevice; +import org.opendaylight.controller.sal.connect.api.RemoteDeviceCommunicator; +import org.opendaylight.controller.sal.connect.netconf.listener.NetconfDeviceCommunicator; +import org.opendaylight.controller.sal.connect.netconf.listener.NetconfSessionCapabilities; +import org.opendaylight.controller.sal.connect.util.RemoteDeviceId; +import org.opendaylight.protocol.framework.NeverReconnectStrategy; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.xml.sax.SAXException; public class NetconfITSecureTest extends AbstractNetconfConfigTest { - private static final InetSocketAddress tlsAddress = new InetSocketAddress("127.0.0.1", 12024); + public static final int PORT = 12024; + private static final InetSocketAddress TLS_ADDRESS = new InetSocketAddress("127.0.0.1", PORT); - private DefaultCommitNotificationProducer commitNot; - private NetconfServerDispatcher dispatchS; + public static final String USERNAME = "user"; + public static final String PASSWORD = "pwd"; + private NetconfSSHServer sshServer; @Before public void setUp() throws Exception { - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,getModuleFactories().toArray( - new ModuleFactory[0]))); - - NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl(); - factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore())); - - commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer()); + final char[] pem = PEMGenerator.generate().toCharArray(); + sshServer = NetconfSSHServer.start(TLS_ADDRESS.getPort(), NetconfConfigUtil.getNetconfLocalAddress(), getNettyThreadgroup(), pem); + sshServer.setAuthProvider(getAuthProvider()); + } + @After + public void tearDown() throws Exception { + sshServer.close(); + sshServer.join(); + } - dispatchS = createDispatcher(factoriesListener); - ChannelFuture s = dispatchS.createServer(tlsAddress); - s.await(); + @Test + public void testSecure() throws Exception { + final NetconfClientDispatcher dispatch = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer()); + try (TestingNetconfClient netconfClient = new TestingNetconfClient("testing-ssh-client", dispatch, getClientConfiguration(new SimpleNetconfClientSessionListener()))) { + NetconfMessage response = netconfClient.sendMessage(getGetConfig()); + assertFalse("Unexpected error message " + XmlUtil.toString(response.getDocument()), + NetconfMessageUtil.isErrorMessage(response)); + + final NetconfMessage gs = new NetconfMessage(XmlUtil.readXmlToDocument("\n" + + " \n" + + " config\n" + + " \n" + + "\n")); + + response = netconfClient.sendMessage(gs); + assertFalse("Unexpected error message " + XmlUtil.toString(response.getDocument()), + NetconfMessageUtil.isErrorMessage(response)); + } } - private NetconfServerDispatcher createDispatcher(NetconfOperationServiceFactoryListenerImpl factoriesListener) { - return super.createDispatcher(factoriesListener, NetconfITTest.getNetconfMonitoringListenerService(), commitNot); + /** + * Test all requests are handled properly and no mismatch occurs in listener + */ + @Test(timeout = 5*60*1000) + public void testSecureStress() throws Exception { + final int requests = 10000; + + final NetconfClientDispatcher dispatch = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer()); + final NetconfDeviceCommunicator sessionListener = getSessionListener(); + try (TestingNetconfClient netconfClient = new TestingNetconfClient("testing-ssh-client", dispatch, getClientConfiguration(sessionListener))) { + + final AtomicInteger responseCounter = new AtomicInteger(0); + final List>> futures = Lists.newArrayList(); + + for (int i = 0; i < requests; i++) { + NetconfMessage getConfig = getGetConfig(); + getConfig = changeMessageId(getConfig, i); + final ListenableFuture> netconfMessageFuture = sessionListener.sendRequest(getConfig, QName.create("namespace", "2012-12-12", "get")); + futures.add(netconfMessageFuture); + Futures.addCallback(netconfMessageFuture, new FutureCallback>() { + @Override + public void onSuccess(final RpcResult result) { + responseCounter.incrementAndGet(); + } + + @Override + public void onFailure(final Throwable t) { + throw new RuntimeException(t); + } + }); + } + + // Wait for every future + for (final ListenableFuture> future : futures) { + try { + future.get(3, TimeUnit.MINUTES); + } catch (final TimeoutException e) { + fail("Request " + futures.indexOf(future) + " is not responding"); + } + } + + // Give future listeners some time to finish counter incrementation + Thread.sleep(5000); + + assertEquals(requests, responseCounter.get()); + } } - @After - public void tearDown() throws Exception { - commitNot.close(); + private NetconfMessage changeMessageId(final NetconfMessage getConfig, final int i) throws IOException, SAXException { + String s = XmlUtil.toString(getConfig.getDocument(), false); + s = s.replace("101", Integer.toString(i)); + return new NetconfMessage(XmlUtil.readXmlToDocument(s)); } - private SSLContext getSslContext() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, - IOException, UnrecoverableKeyException, KeyManagementException { - final InputStream keyStore = getClass().getResourceAsStream("/keystore.jks"); - final InputStream trustStore = getClass().getResourceAsStream("/keystore.jks"); - SSLContext sslContext = SSLUtil.initializeSecureContext("password", keyStore, trustStore, KeyManagerFactory.getDefaultAlgorithm()); - keyStore.close(); - trustStore.close(); - return sslContext; + public NetconfClientConfiguration getClientConfiguration(final NetconfClientSessionListener sessionListener) throws IOException { + final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create(); + b.withAddress(TLS_ADDRESS); + // Using session listener from sal-netconf-connector since stress test cannot be performed with simple listener + b.withSessionListener(sessionListener); + b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, 5000)); + b.withProtocol(NetconfClientConfiguration.NetconfClientProtocol.SSH); + b.withConnectionTimeoutMillis(5000); + b.withAuthHandler(getAuthHandler()); + return b.build(); } - private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException { - final Collection yangDependencies = NetconfITTest.getBasicYangs(); - return new HardcodedYangStoreService(yangDependencies); + @Mock + private RemoteDevice mockedRemoteDevice; + + private NetconfDeviceCommunicator getSessionListener() { + MockitoAnnotations.initMocks(this); + doNothing().when(mockedRemoteDevice).onRemoteSessionUp(any(NetconfSessionCapabilities.class), any(RemoteDeviceCommunicator.class)); + doNothing().when(mockedRemoteDevice).onRemoteSessionDown(); + return new NetconfDeviceCommunicator(new RemoteDeviceId("secure-test"), mockedRemoteDevice); } - protected List getModuleFactories() { - return NetconfITTest.getModuleFactoriesS(); + public AuthProvider getAuthProvider() throws Exception { + final AuthProvider mockAuth = mock(AuthProvider.class); + doReturn("mockedAuth").when(mockAuth).toString(); + doReturn(true).when(mockAuth).authenticated(anyString(), anyString()); + return mockAuth; } - @Test - public void testSecure() throws Exception { - NetconfClientDispatcher dispatch = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup, 5000); - try (TestingNetconfClient netconfClient = new TestingNetconfClient("tls-client", tlsAddress, 4000, dispatch)) { + public AuthenticationHandler getAuthHandler() throws IOException { + return new LoginPassword(USERNAME, PASSWORD); + } - } + @Override + protected LocalAddress getTcpServerAddress() { + return NetconfConfigUtil.getNetconfLocalAddress(); } }