import static java.util.Objects.requireNonNull;
-import com.google.common.base.Strings;
-import java.io.IOException;
-import java.io.StringReader;
-import java.security.KeyPair;
-import java.util.Base64;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.opendaylight.aaa.encrypt.AAAEncryptionService;
-import org.opendaylight.aaa.encrypt.PKIUtil;
import org.opendaylight.netconf.client.conf.NetconfClientConfiguration.NetconfClientProtocol;
import org.opendaylight.netconf.client.conf.NetconfClientConfigurationBuilder;
import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
import org.opendaylight.netconf.client.mdsal.api.SslHandlerFactoryProvider;
import org.opendaylight.netconf.shaded.sshd.client.auth.pubkey.UserAuthPublicKeyFactory;
import org.opendaylight.netconf.shaded.sshd.common.keyprovider.KeyIdentityProvider;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.crypto.types.rev230417.password.grouping.password.type.CleartextPasswordBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.client.rev230417.netconf.client.initiate.stack.grouping.transport.ssh.ssh.SshClientParametersBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.client.rev230417.netconf.client.initiate.stack.grouping.transport.ssh.ssh.TcpClientParametersBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ssh.client.rev230417.ssh.client.grouping.ClientIdentity;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ssh.client.rev230417.ssh.client.grouping.ClientIdentityBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ssh.client.rev230417.ssh.client.grouping.client.identity.PasswordBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240110.connection.parameters.Protocol.Name;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240110.credentials.Credentials;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240110.credentials.credentials.KeyAuth;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240110.credentials.credentials.LoginPw;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240110.credentials.credentials.LoginPwUnencrypted;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.crypto.types.rev231228.password.grouping.password.type.CleartextPasswordBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.client.rev231228.netconf.client.initiate.stack.grouping.transport.ssh.ssh.SshClientParametersBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.client.rev231228.netconf.client.initiate.stack.grouping.transport.ssh.ssh.TcpClientParametersBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ssh.client.rev231228.ssh.client.grouping.ClientIdentity;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ssh.client.rev231228.ssh.client.grouping.ClientIdentityBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ssh.client.rev231228.ssh.client.grouping.client.identity.PasswordBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.connection.parameters.Protocol.Name;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.credentials.Credentials;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.credentials.credentials.KeyAuth;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.credentials.credentials.LoginPw;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.credentials.credentials.LoginPwUnencrypted;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.NetconfNode;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.osgi.service.component.annotations.Activate;
@Override
public NetconfClientConfigurationBuilder createClientConfigurationBuilder(final NodeId nodeId,
- final NetconfNode node) {
+ final NetconfNode node) {
final var builder = NetconfClientConfigurationBuilder.create();
final var protocol = node.getProtocol();
if (node.requireTcpOnly()) {
builder.withProtocol(NetconfClientProtocol.SSH);
setSshParametersFromCredentials(builder, node.getCredentials());
} else if (protocol.getName() == Name.TLS) {
- builder.withProtocol(NetconfClientProtocol.TLS).withSslHandlerFactory(
- channel -> sslHandlerFactoryProvider.getSslHandlerFactory(protocol.getSpecification())
- .createSslHandler());
+ final var handlerFactory = sslHandlerFactoryProvider.getSslHandlerFactory(protocol.getSpecification());
+ builder.withProtocol(NetconfClientProtocol.TLS)
+ .withSslHandlerFactory(channel -> handlerFactory.createSslHandler());
} else {
throw new IllegalArgumentException("Unsupported protocol type: " + protocol.getName());
}
} else if (credentials instanceof LoginPw loginPw) {
final var loginPassword = loginPw.getLoginPassword();
final var username = loginPassword.getUsername();
- final var password = Base64.getEncoder().encodeToString(loginPassword.getPassword());
- sshParamsBuilder.setClientIdentity(loginPasswordIdentity(username, encryptionService.decrypt(password)));
+
+ final byte[] plainBytes;
+ try {
+ plainBytes = encryptionService.decrypt(loginPassword.getPassword());
+ } catch (GeneralSecurityException e) {
+ throw new IllegalStateException("Failed to decrypt password", e);
+ }
+
+ sshParamsBuilder.setClientIdentity(loginPasswordIdentity(username,
+ new String(plainBytes, StandardCharsets.UTF_8)));
} else if (credentials instanceof KeyAuth keyAuth) {
final var keyBased = keyAuth.getKeyBased();
sshParamsBuilder.setClientIdentity(new ClientIdentityBuilder().setUsername(keyBased.getUsername()).build());
confBuilder.withSshConfigurator(factoryMgr -> {
- final var keyPair = getKeyPair(keyBased.getKeyId());
+ final var keyId = keyBased.getKeyId();
+ final var keyPair = credentialProvider.credentialForId(keyId);
+ if (keyPair == null) {
+ throw new IllegalArgumentException("No keypair found with keyId=" + keyId);
+ }
factoryMgr.setKeyIdentityProvider(KeyIdentityProvider.wrapKeyPairs(keyPair));
final var factory = new UserAuthPublicKeyFactory();
factory.setSignatureFactories(factoryMgr.getSignatureFactories());
.build())
.build();
}
-
- private KeyPair getKeyPair(final String keyId) {
- // public key retrieval logic taken from DatastoreBackedPublicKeyAuth
- final var dsKeypair = credentialProvider.credentialForId(keyId);
- if (dsKeypair == null) {
- throw new IllegalArgumentException("No keypair found with keyId=" + keyId);
- }
- final var passPhrase = Strings.isNullOrEmpty(dsKeypair.getPassphrase()) ? "" : dsKeypair.getPassphrase();
- try {
- return new PKIUtil().decodePrivateKey(
- new StringReader(encryptionService.decrypt(dsKeypair.getPrivateKey()).replace("\\n", "\n")),
- encryptionService.decrypt(passPhrase));
- } catch (IOException e) {
- throw new IllegalStateException("Could not decode private key with keyId=" + keyId, e);
- }
- }
}