Refactor ClientFactoryManagerConfigurator 64/110064/7
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 28 Jan 2024 20:48:32 +0000 (21:48 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 19 Feb 2024 09:20:59 +0000 (10:20 +0100)
Turn the interface into an abstract class, so that we can evolve -- most
of the use cases boil down to authentication, it would seem.

JIRA: NETCONF-1238
Change-Id: Ieef402a8879a86780bff65614397aae158903495
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
apps/callhome-provider/src/main/java/org/opendaylight/netconf/topology/callhome/CallHomeSshServer.java
apps/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/NetconfClientConfigurationBuilderFactoryImpl.java
protocol/netconf-client/src/test/java/org/opendaylight/netconf/client/NetconfClientFactoryImplTest.java
transport/transport-ssh/src/main/java/org/opendaylight/netconf/transport/ssh/ClientFactoryManagerConfigurator.java
transport/transport-ssh/src/test/java/org/opendaylight/netconf/transport/ssh/SshClientServerTest.java

index 27286b818236ff3870c3048712ea40e6577a00b1..49eb4c0174324b9bac01c41ed2425758dccb6be3 100644 (file)
@@ -20,6 +20,7 @@ import java.util.concurrent.TimeoutException;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.netconf.api.TransportConstants;
 import org.opendaylight.netconf.client.NetconfClientSessionNegotiatorFactory;
+import org.opendaylight.netconf.shaded.sshd.client.ClientFactoryManager;
 import org.opendaylight.netconf.shaded.sshd.client.auth.password.UserAuthPasswordFactory;
 import org.opendaylight.netconf.shaded.sshd.client.auth.pubkey.UserAuthPublicKeyFactory;
 import org.opendaylight.netconf.shaded.sshd.client.session.ClientSession;
@@ -68,11 +69,17 @@ public final class CallHomeSshServer implements AutoCloseable {
         // NB actual username will be assigned dynamically but predefined one is required for transport initialization
         final var sshClientParams = new SshClientParametersBuilder().setClientIdentity(
             new ClientIdentityBuilder().setUsername("ignored").build()).build();
-        final ClientFactoryManagerConfigurator configurator = factoryMgr -> {
-            factoryMgr.setServerKeyVerifier(this::verifyServerKey);
-            factoryMgr.addSessionListener(createSessionListener());
-            // supported auth factories
-            factoryMgr.setUserAuthFactories(List.of(new UserAuthPasswordFactory(), new UserAuthPublicKeyFactory()));
+        final var configurator = new ClientFactoryManagerConfigurator() {
+            @Override
+            protected void configureClientFactoryManager(final ClientFactoryManager factoryManager) {
+                factoryManager.setServerKeyVerifier((clientSession, remoteAddress, serverKey)
+                    -> verifyServerKey(clientSession, remoteAddress, serverKey));
+                factoryManager.addSessionListener(createSessionListener());
+                // supported auth factories
+                factoryManager.setUserAuthFactories(List.of(
+                    new UserAuthPasswordFactory(),
+                    new UserAuthPublicKeyFactory()));
+            }
         };
         try {
             client = transportStackFactory.listenClient(TransportConstants.SSH_SUBSYSTEM, transportChannelListener,
index 24dcad0f53098e690582f54f24c6791d8f7425fe..82fd1f9400f1f22c9a4608bb7d18ddac973df8a2 100644 (file)
@@ -19,8 +19,11 @@ import org.opendaylight.netconf.client.conf.NetconfClientConfiguration.NetconfCl
 import org.opendaylight.netconf.client.conf.NetconfClientConfigurationBuilder;
 import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
 import org.opendaylight.netconf.client.mdsal.api.SslContextFactoryProvider;
+import org.opendaylight.netconf.shaded.sshd.client.ClientFactoryManager;
 import org.opendaylight.netconf.shaded.sshd.client.auth.pubkey.UserAuthPublicKeyFactory;
 import org.opendaylight.netconf.shaded.sshd.common.keyprovider.KeyIdentityProvider;
+import org.opendaylight.netconf.transport.api.UnsupportedConfigurationException;
+import org.opendaylight.netconf.transport.ssh.ClientFactoryManagerConfigurator;
 import org.opendaylight.netconf.transport.tls.FixedSslHandlerFactory;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.crypto.types.rev240208.password.grouping.password.type.CleartextPasswordBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.client.rev240208.netconf.client.initiate.stack.grouping.transport.ssh.ssh.SshClientParametersBuilder;
@@ -115,16 +118,20 @@ public final class NetconfClientConfigurationBuilderFactoryImpl implements Netco
         } else if (credentials instanceof KeyAuth keyAuth) {
             final var keyBased = keyAuth.getKeyBased();
             sshParamsBuilder.setClientIdentity(new ClientIdentityBuilder().setUsername(keyBased.getUsername()).build());
-            confBuilder.withSshConfigurator(factoryMgr -> {
-                final var keyId = keyBased.getKeyId();
-                final var keyPair = credentialProvider.credentialForId(keyId);
-                if (keyPair == null) {
-                    throw new IllegalArgumentException("No keypair found with keyId=" + keyId);
+            confBuilder.withSshConfigurator(new ClientFactoryManagerConfigurator() {
+                @Override
+                protected void configureClientFactoryManager(final ClientFactoryManager factoryManager)
+                        throws UnsupportedConfigurationException {
+                    final var keyId = keyBased.getKeyId();
+                    final var keyPair = credentialProvider.credentialForId(keyId);
+                    if (keyPair == null) {
+                        throw new IllegalArgumentException("No keypair found with keyId=" + keyId);
+                    }
+                    factoryManager.setKeyIdentityProvider(KeyIdentityProvider.wrapKeyPairs(keyPair));
+                    final var factory = new UserAuthPublicKeyFactory();
+                    factory.setSignatureFactories(factoryManager.getSignatureFactories());
+                    factoryManager.setUserAuthFactories(List.of(factory));
                 }
-                factoryMgr.setKeyIdentityProvider(KeyIdentityProvider.wrapKeyPairs(keyPair));
-                final var factory = new UserAuthPublicKeyFactory();
-                factory.setSignatureFactories(factoryMgr.getSignatureFactories());
-                factoryMgr.setUserAuthFactories(List.of(factory));
             });
         } else {
             throw new IllegalArgumentException("Unsupported credential type: " + credentials.getClass());
index 6fb783be5ae8533e12a7f481e585aac85e052323..e349d774fe68a9a02a394c4c32e2f5cafdc1d2b2 100644 (file)
@@ -47,6 +47,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
 import org.opendaylight.netconf.client.conf.NetconfClientConfigurationBuilder;
 import org.opendaylight.netconf.common.impl.DefaultNetconfTimer;
+import org.opendaylight.netconf.shaded.sshd.client.ClientFactoryManager;
 import org.opendaylight.netconf.shaded.sshd.client.auth.password.PasswordIdentityProvider;
 import org.opendaylight.netconf.shaded.sshd.server.auth.password.UserAuthPasswordFactory;
 import org.opendaylight.netconf.shaded.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
@@ -281,10 +282,13 @@ class NetconfClientFactoryImplTest {
                 (usr, psw, session) -> USERNAME.equals(usr) && PASSWORD.equals(psw));
             factoryManager.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());
         };
-        final ClientFactoryManagerConfigurator clientConfigurator = factoryManager -> {
-            factoryManager.setPasswordIdentityProvider(PasswordIdentityProvider.wrapPasswords(PASSWORD));
-            factoryManager.setUserAuthFactories(List.of(
-                new org.opendaylight.netconf.shaded.sshd.client.auth.password.UserAuthPasswordFactory()));
+        final var clientConfigurator = new ClientFactoryManagerConfigurator() {
+            @Override
+            protected void configureClientFactoryManager(final ClientFactoryManager factoryManager) {
+                factoryManager.setPasswordIdentityProvider(PasswordIdentityProvider.wrapPasswords(PASSWORD));
+                factoryManager.setUserAuthFactories(List.of(
+                    new org.opendaylight.netconf.shaded.sshd.client.auth.password.UserAuthPasswordFactory()));
+            }
         };
 
         final var server = SERVER_FACTORY.listenServer("netconf", serverTransportListener, tcpServerParams,
index bdc2e98750493ddd89435e8d18329c36ecbd631a..935106af910e925f926e854f6f8d918b5843c851 100644 (file)
@@ -15,14 +15,13 @@ import org.opendaylight.netconf.transport.api.UnsupportedConfigurationException;
  * Extension interface allowing one to customize {@link ClientFactoryManager} before it is used to create the
  * {@link SSHClient} instance.
  */
-@FunctionalInterface
-public interface ClientFactoryManagerConfigurator {
+public abstract class ClientFactoryManagerConfigurator {
     /**
      * Apply custom configuration.
      *
      * @param factoryManager client factory manager instance
      * @throws UnsupportedConfigurationException if the configuration is not acceptable
      */
-    void configureClientFactoryManager(@NonNull ClientFactoryManager factoryManager)
+    protected abstract void configureClientFactoryManager(@NonNull ClientFactoryManager factoryManager)
         throws UnsupportedConfigurationException;
 }
index 5c2feda4dd3ed641b972e4bff6b751bf1be4922d..2341a881d4369ffbcf9cf7705287ebb9d9b273ab 100644 (file)
@@ -55,6 +55,7 @@ import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
+import org.opendaylight.netconf.shaded.sshd.client.ClientFactoryManager;
 import org.opendaylight.netconf.shaded.sshd.client.auth.password.PasswordIdentityProvider;
 import org.opendaylight.netconf.shaded.sshd.client.session.ClientSession;
 import org.opendaylight.netconf.shaded.sshd.common.session.Session;
@@ -338,10 +339,14 @@ public class SshClientServerTest {
     }
 
     private static ClientFactoryManagerConfigurator clientConfigurator(final String username) {
-        return factoryManager -> {
-            factoryManager.setPasswordIdentityProvider(PasswordIdentityProvider.wrapPasswords(PASSWORD));
-            factoryManager.setUserAuthFactories(List.of(
-                new org.opendaylight.netconf.shaded.sshd.client.auth.password.UserAuthPasswordFactory()));
+        return new ClientFactoryManagerConfigurator() {
+            @Override
+            protected void configureClientFactoryManager(final ClientFactoryManager factoryManager)
+                    throws UnsupportedConfigurationException {
+                factoryManager.setPasswordIdentityProvider(PasswordIdentityProvider.wrapPasswords(PASSWORD));
+                factoryManager.setUserAuthFactories(List.of(
+                    new org.opendaylight.netconf.shaded.sshd.client.auth.password.UserAuthPasswordFactory()));
+            }
         };
     }