import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
import org.opendaylight.netconf.nettyutil.ReconnectFuture;
import org.opendaylight.netconf.topology.spi.NetconfNodeUtils;
private final DataBroker dataBroker;
private final DOMMountPointService mountService;
private final AAAEncryptionService encryptionService;
- private final NetconfKeystoreAdapter keystoreAdapter;
+ private final CredentialProvider credentialProvider;
+ private final KeyStoreProvider keyStoreProvider;
protected CallHomeTopology topology;
final ScheduledThreadPool keepaliveExecutor, final ThreadPool processingExecutor,
final SchemaResourceManager schemaRepositoryProvider, final BaseNetconfSchemas baseSchemas,
final DataBroker dataBroker, final DOMMountPointService mountService,
- final AAAEncryptionService encryptionService, final NetconfKeystoreAdapter keystoreAdapter) {
+ final AAAEncryptionService encryptionService, final CredentialProvider credentialProvider,
+ final KeyStoreProvider keyStoreProvider) {
this(topologyId, eventExecutor, keepaliveExecutor, processingExecutor, schemaRepositoryProvider, baseSchemas,
- dataBroker, mountService, encryptionService, keystoreAdapter, null);
+ dataBroker, mountService, encryptionService, credentialProvider, keyStoreProvider, null);
}
@Activate
@Reference final SchemaResourceManager schemaRepositoryProvider,
@Reference final BaseNetconfSchemas baseSchemas, @Reference final DataBroker dataBroker,
@Reference final DOMMountPointService mountService, @Reference final AAAEncryptionService encryptionService,
- @Reference final NetconfKeystoreAdapter keystoreAdapter,
+ @Reference final CredentialProvider credentialProvider,
+ @Reference final KeyStoreProvider keyStoreProvider,
@Reference final DeviceActionFactory deviceActionFactory) {
this(NetconfNodeUtils.DEFAULT_TOPOLOGY_NAME, eventExecutor, keepaliveExecutor, processingExecutor,
- schemaRepositoryProvider, baseSchemas, dataBroker, mountService, encryptionService, keystoreAdapter,
- deviceActionFactory);
+ schemaRepositoryProvider, baseSchemas, dataBroker, mountService, encryptionService, credentialProvider,
+ keyStoreProvider, deviceActionFactory);
}
public CallHomeMountDispatcher(final String topologyId, final EventExecutor eventExecutor,
final ScheduledThreadPool keepaliveExecutor, final ThreadPool processingExecutor,
final SchemaResourceManager schemaRepositoryProvider, final BaseNetconfSchemas baseSchemas,
final DataBroker dataBroker, final DOMMountPointService mountService,
- final AAAEncryptionService encryptionService,
- final NetconfKeystoreAdapter keystoreAdapter, final DeviceActionFactory deviceActionFactory) {
+ final AAAEncryptionService encryptionService, final CredentialProvider credentialProvider,
+ final KeyStoreProvider keyStoreProvider, final DeviceActionFactory deviceActionFactory) {
this.topologyId = topologyId;
this.eventExecutor = eventExecutor;
this.keepaliveExecutor = keepaliveExecutor;
this.dataBroker = dataBroker;
this.mountService = mountService;
this.encryptionService = encryptionService;
- this.keystoreAdapter = requireNonNull(keystoreAdapter);
+ this.credentialProvider = requireNonNull(credentialProvider);
+ this.keyStoreProvider = requireNonNull(keyStoreProvider);
}
@Override
void createTopology() {
topology = new CallHomeTopology(topologyId, this, eventExecutor, keepaliveExecutor, processingExecutor,
schemaRepositoryProvider, dataBroker, mountService, encryptionService, baseSchemas,
- deviceActionFactory, keystoreAdapter);
+ deviceActionFactory, credentialProvider, keyStoreProvider);
}
@VisibleForTesting
import org.opendaylight.mdsal.dom.api.DOMMountPointService;
import org.opendaylight.netconf.client.NetconfClientDispatcher;
import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
// Non-final for mocking
public class CallHomeTopology extends AbstractNetconfTopology {
-
public CallHomeTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
final DataBroker dataBroker, final DOMMountPointService mountPointService,
final AAAEncryptionService encryptionService, final BaseNetconfSchemas baseSchemas,
- final DeviceActionFactory deviceActionFactory, final NetconfKeystoreAdapter keystoreAdapter) {
+ final DeviceActionFactory deviceActionFactory, final CredentialProvider credentialProvider,
+ final KeyStoreProvider keyStoreProvider) {
super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, deviceActionFactory,
- baseSchemas, keystoreAdapter);
+ baseSchemas, credentialProvider, keyStoreProvider);
}
}
import org.opendaylight.netconf.callhome.protocol.tls.NetconfCallHomeTlsServer;
import org.opendaylight.netconf.callhome.protocol.tls.NetconfCallHomeTlsServerBuilder;
import org.opendaylight.netconf.callhome.protocol.tls.TlsAllowedDevicesMonitor;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
private final NetconfCallHomeTlsServer server;
@Activate
- public NetconfCallHomeTlsService(@Reference final NetconfKeystoreAdapter keystoreAdapter,
+ public NetconfCallHomeTlsService(@Reference final KeyStoreProvider keyStoreProvider,
@Reference final TlsAllowedDevicesMonitor allowedDevicesMonitor,
@Reference final CallHomeNetconfSubsystemListener subsystemListener,
@Reference(target = "(type=global-boss-group)") final EventLoopGroup bossGroup,
@Reference(target = "(type=global-worker-group)") final EventLoopGroup workerGroup) {
- this(keystoreAdapter, allowedDevicesMonitor, subsystemListener, bossGroup, workerGroup,
+ this(keyStoreProvider, allowedDevicesMonitor, subsystemListener, bossGroup, workerGroup,
// FIXME: tie together with OSGi Config Admin
defaultTlsConfiguration());
}
- public NetconfCallHomeTlsService(final NetconfKeystoreAdapter keystoreAdapter,
+ public NetconfCallHomeTlsService(final KeyStoreProvider keyStoreProvider,
final TlsAllowedDevicesMonitor allowedDevicesMonitor,
final CallHomeNetconfSubsystemListener subsystemListener,
final EventLoopGroup bossGroup,
.setTimeout(config.getTimeout())
.setMaxConnections(config.getMaxConnections())
.setAllowedDevicesMonitor(requireNonNull(allowedDevicesMonitor))
- .setSslHandlerFactory(new SslHandlerFactoryAdapter(keystoreAdapter, allowedDevicesMonitor))
+ .setSslHandlerFactory(new SslHandlerFactoryAdapter(keyStoreProvider, allowedDevicesMonitor))
.setSubsystemListener(requireNonNull(subsystemListener))
.setBossGroup(requireNonNull(bossGroup))
.setWorkerGroup(requireNonNull(workerGroup))
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.netconf.callhome.protocol.tls.TlsAllowedDevicesMonitor;
import org.opendaylight.netconf.client.SslHandlerFactory;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.netconf.sal.connect.util.SslHandlerFactoryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final TlsAllowedDevicesMonitor allowedDevicesMonitor;
private final SslHandlerFactory sslHandlerFactory;
- public SslHandlerFactoryAdapter(final NetconfKeystoreAdapter keystoreAdapter,
+ public SslHandlerFactoryAdapter(final KeyStoreProvider keyStoreProvider,
final @NonNull TlsAllowedDevicesMonitor allowedDevicesMonitor) {
this.allowedDevicesMonitor = requireNonNull(allowedDevicesMonitor);
- sslHandlerFactory = new SslHandlerFactoryImpl(keystoreAdapter);
+ sslHandlerFactory = new SslHandlerFactoryImpl(keyStoreProvider);
}
@Override
import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
import org.opendaylight.netconf.client.conf.NetconfClientConfigurationBuilder;
import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
import org.opendaylight.netconf.nettyutil.ReconnectStrategy;
import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
private CallHomeProtocolSessionContext mockProtoSess;
private AAAEncryptionService mockEncryptionService;
private BaseNetconfSchemas mockBaseSchemas;
- private NetconfKeystoreAdapter mockKeystoreAdapter;
+ private CredentialProvider mockCredentialProvider;
+ private KeyStoreProvider mockKeyStoreProvider;
@Before
public void setup() {
mockProtoSess = mock(CallHomeProtocolSessionContext.class);
mockEncryptionService = mock(AAAEncryptionService.class);
mockBaseSchemas = mock(BaseNetconfSchemas.class);
- mockKeystoreAdapter = mock(NetconfKeystoreAdapter.class);
+ mockCredentialProvider = mock(CredentialProvider.class);
+ mockKeyStoreProvider = mock(KeyStoreProvider.class);
instance = new CallHomeMountDispatcher(topologyId, mockExecutor, mockKeepAlive,
mockProcessingExecutor, mockSchemaRepoProvider, mockBaseSchemas, mockDataBroker, mockMount,
- mockEncryptionService, mockKeystoreAdapter) {
+ mockEncryptionService, mockCredentialProvider, mockKeyStoreProvider) {
@Override
CallHomeMountSessionManager sessionManager() {
return mockSessMgr;
import org.opendaylight.mdsal.dom.api.DOMMountPointService;
import org.opendaylight.netconf.client.NetconfClientDispatcher;
import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
import org.opendaylight.netconf.topology.spi.NetconfConnectorDTO;
@Reference final DOMMountPointService mountPointService,
@Reference final AAAEncryptionService encryptionService,
@Reference final RpcProviderService rpcProviderService, @Reference final BaseNetconfSchemas baseSchemas,
- @Reference final NetconfKeystoreAdapter keystoreAdapter,
+ @Reference final CredentialProvider credentialProvider,
+ @Reference final KeyStoreProvider keyStoreProvider,
@Reference final DeviceActionFactory deviceActionFactory) {
this(NetconfNodeUtils.DEFAULT_TOPOLOGY_NAME, clientDispatcher, eventExecutor, keepaliveExecutor,
processingExecutor, schemaRepositoryProvider, dataBroker, mountPointService, encryptionService,
- rpcProviderService, baseSchemas, keystoreAdapter, deviceActionFactory);
+ rpcProviderService, baseSchemas, credentialProvider, keyStoreProvider, deviceActionFactory);
}
public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
final DataBroker dataBroker, final DOMMountPointService mountPointService,
final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
- final BaseNetconfSchemas baseSchemas, final NetconfKeystoreAdapter keystoreAdapter) {
+ final BaseNetconfSchemas baseSchemas, final CredentialProvider credentialProvider,
+ final KeyStoreProvider keyStoreProvider) {
this(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, rpcProviderService,
- baseSchemas, keystoreAdapter, null);
+ baseSchemas, credentialProvider, keyStoreProvider, null);
}
@SuppressFBWarnings(value = "MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR",
final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
final DataBroker dataBroker, final DOMMountPointService mountPointService,
final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
- final BaseNetconfSchemas baseSchemas, final NetconfKeystoreAdapter keystoreAdapter,
- final DeviceActionFactory deviceActionFactory) {
+ final BaseNetconfSchemas baseSchemas, final CredentialProvider credentialProvider,
+ final KeyStoreProvider keyStoreProvider, final DeviceActionFactory deviceActionFactory) {
super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, deviceActionFactory,
- baseSchemas, keystoreAdapter);
+ baseSchemas, credentialProvider, keyStoreProvider);
LOG.debug("Registering datastore listener");
dtclReg = dataBroker.registerDataTreeChangeListener(DataTreeIdentifier.create(
import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
import org.opendaylight.netconf.client.mdsal.impl.DefaultBaseNetconfSchemas;
import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
@Mock
private RpcProviderService rpcProviderService;
@Mock
- private NetconfKeystoreAdapter keystoreAdapter;
+ private CredentialProvider credentialProvider;
+ @Mock
+ private KeyStoreProvider keyStoreProvider;
@Mock
private WriteTransaction wtx;
topology = new TestingNetconfTopologyImpl(TOPOLOGY_ID, mockedClientDispatcher, mockedEventExecutor,
mockedKeepaliveExecutor, mockedProcessingExecutor, mockedResourceManager, dataBroker, mountPointService,
- encryptionService, rpcProviderService, keystoreAdapter);
+ encryptionService, rpcProviderService, credentialProvider, keyStoreProvider);
//verify initialization of topology
verify(wtx).merge(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(NetworkTopology.class)
.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))).build(),
final DataBroker dataBroker, final DOMMountPointService mountPointService,
final AAAEncryptionService encryptionService,
final RpcProviderService rpcProviderService,
- final NetconfKeystoreAdapter keystoreAdapter) {
+ final CredentialProvider credentialProvider,
+ final KeyStoreProvider keyStoreProvider) {
super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, rpcProviderService,
- BASE_SCHEMAS, keystoreAdapter, null);
+ BASE_SCHEMAS, credentialProvider, keyStoreProvider, null);
}
@Override
import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
import org.opendaylight.netconf.client.NetconfClientDispatcher;
import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
import org.opendaylight.netconf.topology.singleton.api.NetconfTopologySingletonService;
private final AAAEncryptionService encryptionService;
private final RpcProviderService rpcProviderService;
private final DeviceActionFactory deviceActionFactory;
- private final NetconfKeystoreAdapter keystoreAdapter;
+ private final CredentialProvider credentialProvider;
+ private final KeyStoreProvider keyStoreProvider;
private final SchemaResourceManager resourceManager;
private ListenerRegistration<NetconfTopologyManager> dataChangeListenerRegistration;
final RpcProviderService rpcProviderService,
final DeviceActionFactory deviceActionFactory,
final SchemaResourceManager resourceManager,
- final NetconfKeystoreAdapter keystoreAdapter) {
+ final CredentialProvider credentialProvider,
+ final KeyStoreProvider keyStoreProvider) {
this.baseSchemas = requireNonNull(baseSchemas);
this.dataBroker = requireNonNull(dataBroker);
this.rpcProviderRegistry = requireNonNull(rpcProviderRegistry);
this.rpcProviderService = requireNonNull(rpcProviderService);
this.deviceActionFactory = requireNonNull(deviceActionFactory);
this.resourceManager = requireNonNull(resourceManager);
- this.keystoreAdapter = requireNonNull(keystoreAdapter);
+ this.credentialProvider = requireNonNull(credentialProvider);
+ this.keyStoreProvider = requireNonNull(keyStoreProvider);
}
// Blueprint init method
deviceId))
.setIdleTimeout(writeTxIdleTimeout)
.setEncryptionService(encryptionService)
- .setKeystoreAdapter(keystoreAdapter)
+ .setCredentialProvider(credentialProvider)
+ .setKeyStoreProvider(keyStoreProvider)
.build();
}
}
import com.google.common.util.concurrent.MoreExecutors;
import java.math.BigDecimal;
import java.net.InetSocketAddress;
-import java.net.URL;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import org.opendaylight.aaa.encrypt.AAAEncryptionService;
import org.opendaylight.netconf.client.NetconfClientSessionListener;
import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
import org.opendaylight.netconf.client.mdsal.NetconfDevice;
import org.opendaylight.netconf.client.mdsal.NetconfDeviceBuilder;
import org.opendaylight.netconf.client.mdsal.SchemalessNetconfDevice;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.netconf.client.mdsal.api.RemoteDevice;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceHandler;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yangtools.yang.common.Decimal64;
import org.opendaylight.yangtools.yang.common.Empty;
-import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
private final NetconfTopologySetup netconfTopologyDeviceSetup;
private final RemoteDeviceId remoteDeviceId;
private final AAAEncryptionService encryptionService;
- private final NetconfKeystoreAdapter keystoreAdapter;
+ private final CredentialProvider credentialProvider;
+ private final KeyStoreProvider keyStoreProvider;
private final DeviceActionFactory deviceActionFactory;
// FIXME: this seems to be a builder-like transition between {start,stop}RemoteDeviceConnection. More documentation
this.remoteDeviceId = remoteDeviceId;
this.deviceActionFactory = requireNonNull(deviceActionFactory);
encryptionService = netconfTopologyDeviceSetup.getEncryptionService();
- keystoreAdapter = netconfTopologyDeviceSetup.getKeystoreAdapter();
+ credentialProvider = netconfTopologyDeviceSetup.getCredentialProvider();
+ keyStoreProvider = netconfTopologyDeviceSetup.getKeyStoreProvider();
}
@Override
libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL);
}
- for (final Map.Entry<SourceIdentifier, URL> sourceIdentifierURLEntry :
- libraryModulesSchemas.getAvailableModels().entrySet()) {
- registeredYangLibSources
- .add(schemaResourcesDTO.getSchemaRegistry().registerSchemaSource(
- new LibrarySchemaSourceProvider(remoteDeviceId,
- libraryModulesSchemas.getAvailableModels()),
- PotentialSchemaSource
- .create(sourceIdentifierURLEntry.getKey(), YangTextSchemaSource.class,
- PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
+ for (var sourceIdentifierURLEntry : libraryModulesSchemas.getAvailableModels().entrySet()) {
+ registeredYangLibSources.add(schemaResourcesDTO.getSchemaRegistry().registerSchemaSource(
+ new LibrarySchemaSourceProvider(remoteDeviceId, libraryModulesSchemas.getAvailableModels()),
+ PotentialSchemaSource.create(sourceIdentifierURLEntry.getKey(), YangTextSchemaSource.class,
+ PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
}
}
}
.withAuthHandler(getHandlerFromCredentials(node.getCredentials()));
} else if (protocol.getName() == Name.TLS) {
reconnectingClientConfigurationBuilder = NetconfReconnectingClientConfigurationBuilder.create()
- .withSslHandlerFactory(new SslHandlerFactoryImpl(keystoreAdapter, protocol.getSpecification()))
+ .withSslHandlerFactory(new SslHandlerFactoryImpl(keyStoreProvider, protocol.getSpecification()))
.withProtocol(NetconfClientConfiguration.NetconfClientProtocol.TLS);
} else {
throw new IllegalStateException("Unsupported protocol type: " + protocol.getName());
if (credentials instanceof KeyAuth keyAuth) {
final var keyPair = keyAuth.getKeyBased();
return new DatastoreBackedPublicKeyAuth(keyPair.getUsername(), keyPair.getKeyId(),
- keystoreAdapter, encryptionService);
+ credentialProvider, encryptionService);
}
throw new IllegalStateException("Unsupported credential type: " + credentials.getClass());
}
import org.opendaylight.netconf.client.NetconfClientDispatcher;
import org.opendaylight.netconf.client.mdsal.NetconfDevice;
import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
private final Duration idleTimeout;
private final AAAEncryptionService encryptionService;
private final BaseNetconfSchemas baseSchemas;
- private final NetconfKeystoreAdapter keystoreAdapter;
+ private final CredentialProvider credentialProvider;
+ private final KeyStoreProvider keyStoreProvider;
NetconfTopologySetup(final NetconfTopologySetupBuilder builder) {
clusterSingletonServiceProvider = builder.getClusterSingletonServiceProvider();
idleTimeout = builder.getIdleTimeout();
encryptionService = builder.getEncryptionService();
baseSchemas = builder.getBaseSchemas();
- keystoreAdapter = builder.getKeystoreAdapter();
+ credentialProvider = builder.getCredentialProvider();
+ keyStoreProvider = builder.getKeyStoreProvider();
}
public ClusterSingletonServiceProvider getClusterSingletonServiceProvider() {
return encryptionService;
}
- public NetconfKeystoreAdapter getKeystoreAdapter() {
- return keystoreAdapter;
+ public CredentialProvider getCredentialProvider() {
+ return requireNonNull(credentialProvider);
+ }
+
+ public KeyStoreProvider getKeyStoreProvider() {
+ return requireNonNull(keyStoreProvider);
}
public BaseNetconfSchemas getBaseSchemas() {
private Duration idleTimeout;
private AAAEncryptionService encryptionService;
private BaseNetconfSchemas baseSchemas;
- private NetconfKeystoreAdapter keystoreAdapter;
+ private CredentialProvider credentialProvider;
+ private KeyStoreProvider keyStoreProvider;
public NetconfTopologySetupBuilder() {
return this;
}
- NetconfKeystoreAdapter getKeystoreAdapter() {
- return requireNonNull(keystoreAdapter);
+ CredentialProvider getCredentialProvider() {
+ return requireNonNull(credentialProvider);
+ }
+
+ public NetconfTopologySetupBuilder setCredentialProvider(final CredentialProvider credentialProvider) {
+ this.credentialProvider = credentialProvider;
+ return this;
+ }
+
+ KeyStoreProvider getKeyStoreProvider() {
+ return requireNonNull(keyStoreProvider);
}
- public NetconfTopologySetupBuilder setKeystoreAdapter(final NetconfKeystoreAdapter keystoreAdapter) {
- this.keystoreAdapter = keystoreAdapter;
+ public NetconfTopologySetupBuilder setKeyStoreProvider(final KeyStoreProvider keyStoreProvider) {
+ this.keyStoreProvider = keyStoreProvider;
return this;
}
interface="org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager"/>
<reference id="baseSchemas"
interface="org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas"/>
- <reference id="keystoreAdapter"
- interface="org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter"/>
- <odl:clustered-app-config
- id="singletonConfig"
- binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.topology.singleton.config.rev170419.Config"
- />
-
+ <reference id="credentialProvider"
+ interface="org.opendaylight.netconf.client.mdsal.api.CredentialProvider"/>
+ <reference id="keyStoreProvider"
+ interface="org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider"/>
<reference id="encryptionService"
interface="org.opendaylight.aaa.encrypt.AAAEncryptionService" />
+ <odl:clustered-app-config id="singletonConfig"
+ binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.topology.singleton.config.rev170419.Config"/>
+
<bean id="netconfTopologyManager"
class="org.opendaylight.netconf.topology.singleton.impl.NetconfTopologyManager"
init-method="init" destroy-method="close">
<argument ref="rpcProvider" />
<argument ref="deviceActionFactory"/>
<argument ref="schemaManager"/>
- <argument ref="keystoreAdapter"/>
+ <argument ref="credentialProvider"/>
+ <argument ref="keyStoreProvider"/>
</bean>
<service ref="netconfTopologyManager"
interface="org.opendaylight.netconf.topology.singleton.api.NetconfTopologySingletonService"/>
import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
import org.opendaylight.netconf.client.NetconfClientDispatcher;
import org.opendaylight.netconf.client.mdsal.NetconfDeviceSchema;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceServices;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceServices.Rpcs;
import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
@Mock private ThreadPool mockThreadPool;
@Mock private ScheduledThreadPool mockKeepaliveExecutor;
@Mock private DeviceActionFactory deviceActionFactory;
- @Mock private NetconfKeystoreAdapter keystoreAdapter;
+ @Mock private CredentialProvider credentialProvider;
+ @Mock private KeyStoreProvider keyStoreProvider;
@Mock private ActorSystemProvider mockMasterActorSystemProvider;
@Mock private DOMMountPointListener masterMountPointListener;
mockRpcProviderRegistry, mockActionProviderRegistry, masterClusterSingletonServiceProvider,
mockKeepaliveExecutor, mockThreadPool, mockMasterActorSystemProvider, eventExecutor,
mockClientDispatcher, TOPOLOGY_ID, config, masterMountPointService, mockEncryptionService,
- mockRpcProviderService, deviceActionFactory, resourceManager, keystoreAdapter) {
+ mockRpcProviderService, deviceActionFactory, resourceManager, credentialProvider, keyStoreProvider) {
@Override
protected NetconfTopologyContext newNetconfTopologyContext(final NetconfTopologySetup setup,
final ServiceGroupIdentifier serviceGroupIdent, final Timeout actorResponseWaitTime,
mockActionProviderRegistry, mockSlaveClusterSingletonServiceProvider, mockKeepaliveExecutor, mockThreadPool,
mockSlaveActorSystemProvider, eventExecutor, mockClientDispatcher, TOPOLOGY_ID, config,
slaveMountPointService, mockEncryptionService, mockRpcProviderService, deviceActionFactory,
- resourceManager, keystoreAdapter) {
+ resourceManager, credentialProvider, keyStoreProvider) {
@Override
protected NetconfTopologyContext newNetconfTopologyContext(final NetconfTopologySetup setup,
final ServiceGroupIdentifier serviceGroupIdent, final Timeout actorResponseWaitTime,
import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
import org.opendaylight.netconf.client.mdsal.NetconfDevice.SchemaResourcesDTO;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceServices;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceServices.Actions;
@Mock
private SchemaResourcesDTO schemaResourceDTO;
@Mock
- private NetconfKeystoreAdapter keystoreAdapter;
+ private CredentialProvider credentialProvider;
+ @Mock
+ private KeyStoreProvider keyStoreProvider;
@Before
public void setup() {
.setIdleTimeout(Duration.ofSeconds(1))
.setSchemaResourceDTO(schemaResourceDTO)
.setBaseSchemas(BASE_SCHEMAS)
- .setKeystoreAdapter(keystoreAdapter)
+ .setCredentialProvider(credentialProvider)
+ .setKeyStoreProvider(keyStoreProvider)
.build();
final Props props = NetconfNodeActor.props(setup, remoteDeviceId, TIMEOUT, mockMountPointService);
.setBaseSchemas(BASE_SCHEMAS)
.setSchemaResourceDTO(schemaResourceDTO)
.setActorSystem(system)
- .setKeystoreAdapter(keystoreAdapter)
+ .setCredentialProvider(credentialProvider)
+ .setKeyStoreProvider(keyStoreProvider)
.build();
masterRef.tell(new RefreshSetupMasterActorData(newSetup, newRemoteDeviceId), testKit.getRef());
.setSchemaResourceDTO(schemaResourceDTO2)
.setBaseSchemas(BASE_SCHEMAS)
.setActorSystem(system)
- .setKeystoreAdapter(keystoreAdapter)
+ .setCredentialProvider(credentialProvider)
+ .setKeyStoreProvider(keyStoreProvider)
.build();
final ActorRef slaveRef = system.actorOf(NetconfNodeActor.props(setup, remoteDeviceId, TIMEOUT,
.setSchemaResourceDTO(schemaResourceDTO2)
.setIdleTimeout(Duration.ofSeconds(1))
.setBaseSchemas(BASE_SCHEMAS)
- .setKeystoreAdapter(keystoreAdapter)
+ .setCredentialProvider(credentialProvider)
+ .setKeyStoreProvider(keyStoreProvider)
.build();
final Props props = NetconfNodeActor.props(setup, remoteDeviceId, TIMEOUT, mockMountPointService);
ActorRef actor = TestActorRef.create(system, props, "master_messages_2");
.setSchemaResourceDTO(schemaResourceDTO2)
.setActorSystem(system)
.setBaseSchemas(BASE_SCHEMAS)
- .setKeystoreAdapter(keystoreAdapter)
+ .setCredentialProvider(credentialProvider)
+ .setKeyStoreProvider(keyStoreProvider)
.build(), remoteDeviceId, TIMEOUT, mockMountPointService));
doReturn(Futures.immediateFuture(mockSchemaContext))
import org.opendaylight.mdsal.dom.api.DOMNotificationService;
import org.opendaylight.mdsal.dom.api.DOMRpcService;
import org.opendaylight.netconf.client.mdsal.NetconfDevice;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.netconf.client.mdsal.api.NetconfDeviceSchemasResolver;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceServices;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceServices.Actions;
@Mock
private EffectiveModelContextFactory mockSchemaContextFactory;
@Mock
- private NetconfKeystoreAdapter keystoreAdapter;
+ private CredentialProvider credentialProvider;
+ @Mock
+ private KeyStoreProvider keyStoreProvider;
private ActorSystem slaveSystem;
private ActorSystem masterSystem;
.setSchemaResourceDTO(new NetconfDevice.SchemaResourcesDTO(
masterSchemaRepository, masterSchemaRepository, mockSchemaContextFactory, mockSchemasResolver))
.setBaseSchemas(BASE_SCHEMAS)
- .setKeystoreAdapter(keystoreAdapter)
+ .setCredentialProvider(credentialProvider)
+ .setKeyStoreProvider(keyStoreProvider)
.build();
testMasterActorRef = TestActorRef.create(masterSystem, Props.create(TestMasterActor.class, masterSetup,
.setSchemaResourceDTO(new NetconfDevice.SchemaResourcesDTO(
slaveSchemaRepository, slaveSchemaRepository, mockSchemaContextFactory, mockSchemasResolver))
.setBaseSchemas(BASE_SCHEMAS)
- .setKeystoreAdapter(keystoreAdapter)
+ .setCredentialProvider(credentialProvider)
+ .setKeyStoreProvider(keyStoreProvider)
.build();
netconfNodeManager = new NetconfNodeManager(slaveSetup, DEVICE_ID, responseTimeout,
import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
import org.opendaylight.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.netconf.client.mdsal.impl.DefaultSchemaResourceManager;
import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
final AAAEncryptionService encryptionService = mock(AAAEncryptionService.class);
final DeviceActionFactory deviceActionFactory = mock(DeviceActionFactory.class);
final RpcProviderService rpcProviderService = mock(RpcProviderService.class);
- final NetconfKeystoreAdapter keystoreAdapter = mock(NetconfKeystoreAdapter.class);
+ final CredentialProvider credentialProvider = mock(CredentialProvider.class);
+ final KeyStoreProvider keyStoreProvider = mock(KeyStoreProvider.class);
final Config config = new ConfigBuilder().setWriteTransactionIdleTimeout(Uint16.ZERO).build();
netconfTopologyManager = new NetconfTopologyManager(BASE_SCHEMAS, dataBroker, rpcProviderRegistry,
actionProviderRegistry, clusterSingletonServiceProvider, keepaliveExecutor, processingThreadPool,
actorSystemProvider, eventExecutor, clientDispatcher, TOPOLOGY_ID, config,
mountPointService, encryptionService, rpcProviderService, deviceActionFactory,
- new DefaultSchemaResourceManager(new DefaultYangParserFactory()), keystoreAdapter) {
+ new DefaultSchemaResourceManager(new DefaultYangParserFactory()), credentialProvider,
+ keyStoreProvider) {
@Override
protected NetconfTopologyContext newNetconfTopologyContext(final NetconfTopologySetup setup,
final ServiceGroupIdentifier serviceGroupIdent, final Timeout actorResponseWaitTime,
import org.opendaylight.netconf.client.NetconfClientSessionListener;
import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceHandler;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
import org.opendaylight.netconf.client.mdsal.impl.DefaultSchemaResourceManager;
@Mock
private DeviceActionFactory deviceActionFactory;
@Mock
- private NetconfKeystoreAdapter keystoreAdapter;
+ private CredentialProvider credentialProvider;
+ @Mock
+ private KeyStoreProvider keyStoreProvider;
private NetconfTopologySetup.NetconfTopologySetupBuilder builder;
private RemoteDeviceId remoteDeviceId;
.setEventExecutor(eventExecutor)
.setNetconfClientDispatcher(clientDispatcher)
.setTopologyId(TOPOLOGY_ID)
- .setKeystoreAdapter(keystoreAdapter);
+ .setCredentialProvider(credentialProvider)
+ .setKeyStoreProvider(keyStoreProvider);
}
@Test
import org.opendaylight.netconf.client.mdsal.NetconfDeviceBuilder;
import org.opendaylight.netconf.client.mdsal.SchemalessNetconfDevice;
import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.netconf.client.mdsal.api.RemoteDevice;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceHandler;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
private final NetconfClientDispatcher clientDispatcher;
private final EventExecutor eventExecutor;
private final DeviceActionFactory deviceActionFactory;
- private final NetconfKeystoreAdapter keystoreAdapter;
+ private final CredentialProvider credentialProvider;
+ private final KeyStoreProvider keystoreProvider;
private final SchemaResourceManager schemaManager;
private final BaseNetconfSchemas baseSchemas;
final AAAEncryptionService encryptionService,
final DeviceActionFactory deviceActionFactory,
final BaseNetconfSchemas baseSchemas,
- final NetconfKeystoreAdapter keystoreAdapter) {
+ final CredentialProvider credentialProvider,
+ final KeyStoreProvider keystoreProvider) {
this.topologyId = requireNonNull(topologyId);
this.clientDispatcher = clientDispatcher;
this.eventExecutor = eventExecutor;
this.mountPointService = mountPointService;
this.encryptionService = encryptionService;
this.baseSchemas = requireNonNull(baseSchemas);
- this.keystoreAdapter = requireNonNull(keystoreAdapter);
+ this.credentialProvider = requireNonNull(credentialProvider);
+ this.keystoreProvider = requireNonNull(keystoreProvider);
// FIXME: this should be a put(), as we are initializing and will be re-populating the datastore with all the
// devices. Whatever has been there before should be nuked to properly re-align lifecycle.
.withAuthHandler(getHandlerFromCredentials(node.getCredentials()));
} else if (protocol.getName() == Name.TLS) {
reconnectingClientConfigurationBuilder = NetconfReconnectingClientConfigurationBuilder.create()
- .withSslHandlerFactory(new SslHandlerFactoryImpl(keystoreAdapter, protocol.getSpecification()))
+ .withSslHandlerFactory(new SslHandlerFactoryImpl(keystoreProvider, protocol.getSpecification()))
.withProtocol(NetconfClientConfiguration.NetconfClientProtocol.TLS);
} else {
throw new IllegalStateException("Unsupported protocol type: " + protocol.getName());
}
if (credentials instanceof KeyAuth keyAuth) {
final var keyPair = keyAuth.getKeyBased();
- return new DatastoreBackedPublicKeyAuth(keyPair.getUsername(), keyPair.getKeyId(),
- keystoreAdapter, encryptionService);
+ return new DatastoreBackedPublicKeyAuth(keyPair.getUsername(), keyPair.getKeyId(), credentialProvider,
+ encryptionService);
}
throw new IllegalStateException("Unsupported credential type: " + credentials.getClass());
}
import java.util.Optional;
import org.opendaylight.aaa.encrypt.AAAEncryptionService;
import org.opendaylight.aaa.encrypt.PKIUtil;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
import org.opendaylight.netconf.shaded.sshd.client.future.AuthFuture;
import org.opendaylight.netconf.shaded.sshd.client.session.ClientSession;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.keystore.entry.KeyCredential;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final String username;
private final String pairId;
- private final NetconfKeystoreAdapter keystoreAdapter;
+ private final CredentialProvider credentialProvider;
private final AAAEncryptionService encryptionService;
// FIXME: do not use Optional here and deal with atomic set
private Optional<KeyPair> keyPair = Optional.empty();
public DatastoreBackedPublicKeyAuth(final String username, final String pairId,
- final NetconfKeystoreAdapter keystoreAdapter,
+ final CredentialProvider credentialProvider,
final AAAEncryptionService encryptionService) {
this.username = username;
this.pairId = pairId;
- this.keystoreAdapter = keystoreAdapter;
+ this.credentialProvider = credentialProvider;
this.encryptionService = encryptionService;
// try to immediately retrieve the pair from the adapter
private boolean tryToSetKeyPair() {
LOG.debug("Trying to retrieve keypair for: {}", pairId);
- final Optional<KeyCredential> keypairOptional = keystoreAdapter.getKeypairFromId(pairId);
-
- if (keypairOptional.isPresent()) {
- final KeyCredential dsKeypair = keypairOptional.orElseThrow();
- final String passPhrase = Strings.isNullOrEmpty(dsKeypair.getPassphrase()) ? "" : dsKeypair.getPassphrase();
+ final var dsKeypair = credentialProvider.credentialForId(pairId);
+ if (dsKeypair == null) {
+ LOG.debug("Unable to retrieve keypair for: {}", pairId);
+ return false;
+ }
- try {
- keyPair = Optional.of(new PKIUtil().decodePrivateKey(
- new StringReader(encryptionService.decrypt(dsKeypair.getPrivateKey()).replace("\\n", "\n")),
- encryptionService.decrypt(passPhrase)));
- } catch (IOException exception) {
- LOG.warn("Unable to decode private key, id={}", pairId, exception);
- return false;
- }
- return true;
+ final String passPhrase = Strings.isNullOrEmpty(dsKeypair.getPassphrase()) ? "" : dsKeypair.getPassphrase();
+ try {
+ keyPair = Optional.of(new PKIUtil().decodePrivateKey(
+ new StringReader(encryptionService.decrypt(dsKeypair.getPrivateKey()).replace("\\n", "\n")),
+ encryptionService.decrypt(passPhrase)));
+ } catch (IOException exception) {
+ LOG.warn("Unable to decode private key, id={}", pairId, exception);
+ return false;
}
- LOG.debug("Unable to retrieve keypair for: {}", pairId);
- return false;
+ return true;
}
}
--- /dev/null
+/*
+ * Copyright (c) 2023 PANTHEON.tech, s.r.o. 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.netconf.client.mdsal.api;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.keystore.entry.KeyCredential;
+
+public interface CredentialProvider {
+ /**
+ * Get the a {@link KeyCredential} for a particular id.
+ *
+ * @param id Credential id
+ * @return A {@link KeyCredential} object, {@code null} if not found
+ * @throws NullPointerException if {@code id} is {@code null}
+ */
+ @Nullable KeyCredential credentialForId(String id);
+}
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
-import java.util.Optional;
import java.util.Set;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.keystore.entry.KeyCredential;
-
-public interface NetconfKeystoreAdapter {
-
- Optional<KeyCredential> getKeypairFromId(String keyId);
+public interface KeyStoreProvider {
/**
* Using private keys and trusted certificates to create a new JDK <code>KeyStore</code> which
* will be used by TLS clients to create <code>SSLEngine</code>. The private keys are essential
--- /dev/null
+/*
+ * Copyright (c) 2017 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.netconf.client.mdsal.impl;
+
+import com.google.common.collect.Iterables;
+import java.util.Collection;
+import java.util.Map;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
+import org.opendaylight.mdsal.binding.api.DataTreeModification;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.Keystore;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.keystore.entry.KeyCredential;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.keystore.entry.KeyCredentialKey;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+@Component(service = CredentialProvider.class)
+public final class DefaultCredentialProvider
+ implements CredentialProvider, ClusteredDataTreeChangeListener<Keystore>, AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(DefaultCredentialProvider.class);
+
+ private final @NonNull Registration reg;
+
+ private volatile @NonNull Map<KeyCredentialKey, KeyCredential> credentials = Map.of();
+
+ @Inject
+ @Activate
+ public DefaultCredentialProvider(@Reference final DataBroker dataBroker) {
+ reg = dataBroker.registerDataTreeChangeListener(
+ DataTreeIdentifier.create(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Keystore.class)),
+ this);
+ }
+
+ @Deactivate
+ @PreDestroy
+ @Override
+ public void close() {
+ reg.close();
+ }
+
+ @Override
+ public KeyCredential credentialForId(final String id) {
+ return credentials.get(new KeyCredentialKey(id));
+ }
+
+ @Override
+ public void onDataTreeChanged(final Collection<DataTreeModification<Keystore>> changes) {
+ final var keystore = Iterables.getLast(changes).getRootNode().getDataAfter();
+ final var newCredentials = keystore != null ? keystore.nonnullKeyCredential()
+ : Map.<KeyCredentialKey, KeyCredential>of();
+ LOG.debug("Updating to {} credentials", newCredentials.size());
+ credentials = newCredentials;
+ }
+}
*/
package org.opendaylight.netconf.client.mdsal.impl;
-import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;
import java.io.ByteArrayInputStream;
import java.io.IOException;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.VarHandle;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
-import java.util.Optional;
import java.util.Set;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
import org.opendaylight.mdsal.binding.api.DataTreeModification;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.Keystore;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017._private.keys.PrivateKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.keystore.entry.KeyCredential;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.trusted.certificates.TrustedCertificate;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.LoggerFactory;
@Singleton
-@Component(service = NetconfKeystoreAdapter.class)
-public final class DefaultNetconfKeystoreAdapter
- implements NetconfKeystoreAdapter, ClusteredDataTreeChangeListener<Keystore>, AutoCloseable {
+@Component(service = KeyStoreProvider.class)
+public final class DefaultKeyStoreProvider
+ implements KeyStoreProvider, ClusteredDataTreeChangeListener<Keystore>, AutoCloseable {
/**
* Internal state, updated atomically.
*/
private record State(
- @NonNull Map<String, KeyCredential> pairs,
@NonNull Map<String, PrivateKey> privateKeys,
@NonNull Map<String, TrustedCertificate> trustedCertificates) {
State {
- requireNonNull(pairs);
requireNonNull(privateKeys);
requireNonNull(trustedCertificates);
}
@NonNull StateBuilder newBuilder() {
- return new StateBuilder(new HashMap<>(pairs), new HashMap<>(privateKeys),
- new HashMap<>(trustedCertificates));
+ return new StateBuilder(new HashMap<>(privateKeys), new HashMap<>(trustedCertificates));
}
}
* Intermediate builder for State.
*/
private record StateBuilder(
- @NonNull HashMap<String, KeyCredential> pairs,
@NonNull HashMap<String, PrivateKey> privateKeys,
@NonNull HashMap<String, TrustedCertificate> trustedCertificates) {
StateBuilder {
- requireNonNull(pairs);
requireNonNull(privateKeys);
requireNonNull(trustedCertificates);
}
@NonNull State build() {
- return new State(Map.copyOf(pairs), Map.copyOf(privateKeys), Map.copyOf(trustedCertificates));
+ return new State(Map.copyOf(privateKeys), Map.copyOf(trustedCertificates));
}
}
}
}
- private static final Logger LOG = LoggerFactory.getLogger(DefaultNetconfKeystoreAdapter.class);
+ private static final Logger LOG = LoggerFactory.getLogger(DefaultKeyStoreProvider.class);
private static final char[] EMPTY_CHARS = { };
- private static final VarHandle STATE_VH;
-
- static {
- try {
- STATE_VH = MethodHandles.lookup().findVarHandle(DefaultNetconfKeystoreAdapter.class, "state", State.class);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- throw new ExceptionInInitializerError(e);
- }
- }
private final @NonNull Registration reg;
- @SuppressWarnings("unused")
- private volatile @NonNull State state = new State(Map.of(), Map.of(), Map.of());
+ private volatile @NonNull State state = new State(Map.of(), Map.of());
@Inject
@Activate
- public DefaultNetconfKeystoreAdapter(@Reference final DataBroker dataBroker) {
+ public DefaultKeyStoreProvider(@Reference final DataBroker dataBroker) {
reg = dataBroker.registerDataTreeChangeListener(
DataTreeIdentifier.create(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Keystore.class)),
this);
reg.close();
}
- @Override
- public Optional<KeyCredential> getKeypairFromId(final String keyId) {
- return Optional.ofNullable(currentState().pairs.get(keyId));
- }
-
@Override
public KeyStore getJavaKeyStore(final Set<String> allowedKeys) throws GeneralSecurityException, IOException {
requireNonNull(allowedKeys);
- final var current = currentState();
+ final var current = state;
if (current.privateKeys.isEmpty()) {
throw new KeyStoreException("No keystore private key found");
}
return keyStore;
}
- private @NonNull State currentState() {
- return verifyNotNull((@NonNull State) STATE_VH.getAcquire(this));
- }
-
private static byte[] base64Decode(final String base64) {
return Base64.getMimeDecoder().decode(base64.getBytes(StandardCharsets.US_ASCII));
}
@Override
public void onDataTreeChanged(final Collection<DataTreeModification<Keystore>> changes) {
LOG.debug("Starting update with {} changes", changes.size());
- final var builder = currentState().newBuilder();
+ final var builder = state.newBuilder();
onDataTreeChanged(builder, changes);
- STATE_VH.setRelease(this, builder.build());
+ state = builder.build();
LOG.debug("Update finished");
}
final var rootNode = change.getRootNode();
for (var changedChild : rootNode.getModifiedChildren()) {
- if (changedChild.getDataType().equals(KeyCredential.class)) {
- final var dataAfter = rootNode.getDataAfter();
- builder.pairs.clear();
- if (dataAfter != null) {
- dataAfter.nonnullKeyCredential().values()
- .forEach(pair -> builder.pairs.put(pair.key().getKeyId(), pair));
- }
- } else if (changedChild.getDataType().equals(PrivateKey.class)) {
+ if (changedChild.getDataType().equals(PrivateKey.class)) {
onPrivateKeyChanged(builder.privateKeys, (DataObjectModification<PrivateKey>)changedChild);
} else if (changedChild.getDataType().equals(TrustedCertificate.class)) {
onTrustedCertificateChanged(builder.trustedCertificates,
import javax.net.ssl.TrustManagerFactory;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.netconf.client.SslHandlerFactory;
-import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
+import org.opendaylight.netconf.client.mdsal.api.KeyStoreProvider;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.connection.parameters.protocol.Specification;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.connection.parameters.protocol.specification.TlsCase;
public final class SslHandlerFactoryImpl implements SslHandlerFactory {
- private final NetconfKeystoreAdapter keystoreAdapter;
+ private final KeyStoreProvider keyStoreProvider;
private final @Nullable Specification specification;
- public SslHandlerFactoryImpl(final NetconfKeystoreAdapter keystoreAdapter) {
- this(keystoreAdapter, null);
+ public SslHandlerFactoryImpl(final KeyStoreProvider keyStoreProvider) {
+ this(keyStoreProvider, null);
}
- public SslHandlerFactoryImpl(final NetconfKeystoreAdapter keystoreAdapter, final Specification specification) {
- this.keystoreAdapter = requireNonNull(keystoreAdapter);
+ public SslHandlerFactoryImpl(final KeyStoreProvider keyStoreProvider, final Specification specification) {
+ this.keyStoreProvider = requireNonNull(keyStoreProvider);
this.specification = specification;
}
@Override
public SslHandler createSslHandler(final Set<String> allowedKeys) {
try {
- final KeyStore keyStore = keystoreAdapter.getJavaKeyStore(allowedKeys);
+ final KeyStore keyStore = keyStoreProvider.getJavaKeyStore(allowedKeys);
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, "".toCharArray());
import org.w3c.dom.NodeList;
@RunWith(MockitoJUnitRunner.StrictStubs.class)
-public class DefaultNetconfKeystoreAdapterTest {
+public class DefaultKeyStoreProviderTest {
private static final String XML_ELEMENT_PRIVATE_KEY = "private-key";
private static final String XML_ELEMENT_NAME = "name";
private static final String XML_ELEMENT_DATA = "data";
@Before
public void setUp() {
doReturn(listenerRegistration).when(dataBroker)
- .registerDataTreeChangeListener(any(DataTreeIdentifier.class), any(DefaultNetconfKeystoreAdapter.class));
+ .registerDataTreeChangeListener(any(DataTreeIdentifier.class), any(DefaultKeyStoreProvider.class));
}
@Test
public void testKeystoreAdapterInit() throws Exception {
- final DefaultNetconfKeystoreAdapter keystoreAdapter = new DefaultNetconfKeystoreAdapter(dataBroker);
+ final DefaultKeyStoreProvider keystoreAdapter = new DefaultKeyStoreProvider(dataBroker);
final var ex = assertThrows(KeyStoreException.class, keystoreAdapter::getJavaKeyStore);
assertThat(ex.getMessage(), startsWith("No keystore private key found"));
}
final var privateKey = getPrivateKey();
doReturn(privateKey).when(childObjectModification).getDataAfter();
- final var keystoreAdapter = new DefaultNetconfKeystoreAdapter(dataBroker);
+ final var keystoreAdapter = new DefaultKeyStoreProvider(dataBroker);
keystoreAdapter.onDataTreeChanged(List.of(dataTreeModification));
final var keyStore = keystoreAdapter.getJavaKeyStore();
doReturn(trustedCertificate).when(childObjectModification2).getDataAfter();
// Apply configurations
- final var keystoreAdapter = new DefaultNetconfKeystoreAdapter(dataBroker);
+ final var keystoreAdapter = new DefaultKeyStoreProvider(dataBroker);
keystoreAdapter.onDataTreeChanged(List.of(dataTreeModification1, dataTreeModification2));
// Check result