import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
+import java.util.Collections;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import org.opendaylight.mdsal.binding.api.DataBroker;
import org.opendaylight.netconf.callhome.protocol.AuthorizedKeysDecoder;
import org.opendaylight.netconf.callhome.protocol.StatusRecorder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.callhome.device.status.rev170112.Device1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.callhome.device.status.rev170112.Device1.DeviceStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.callhome.device.status.rev170112.Device1Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev161109.NetconfCallhomeServer;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev161109.netconf.callhome.server.AllowedDevices;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev161109.netconf.callhome.server.allowed.devices.Device;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev161109.netconf.callhome.server.allowed.devices.DeviceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev161109.netconf.callhome.server.allowed.devices.DeviceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev201015.NetconfCallhomeServer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev201015.netconf.callhome.server.AllowedDevices;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev201015.netconf.callhome.server.allowed.devices.Device;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev201015.netconf.callhome.server.allowed.devices.DeviceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev201015.netconf.callhome.server.allowed.devices.DeviceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev201015.netconf.callhome.server.allowed.devices.device.Transport;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev201015.netconf.callhome.server.allowed.devices.device.transport.Ssh;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev201015.netconf.callhome.server.allowed.devices.device.transport.SshBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev201015.netconf.callhome.server.allowed.devices.device.transport.ssh.SshClientParams;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev201015.netconf.callhome.server.allowed.devices.device.transport.ssh.SshClientParamsBuilder;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-class CallhomeStatusReporter implements DataTreeChangeListener<Node>, StatusRecorder, AutoCloseable {
+final class CallhomeStatusReporter implements DataTreeChangeListener<Node>, StatusRecorder, AutoCloseable {
private static final InstanceIdentifier<Topology> NETCONF_TOPO_IID =
InstanceIdentifier.create(NetworkTopology.class).child(Topology.class,
new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName())));
@Override
public void onDataTreeChanged(final Collection<DataTreeModification<Node>> changes) {
- for (DataTreeModification<Node> change: changes) {
+ for (DataTreeModification<Node> change : changes) {
final DataObjectModification<Node> rootNode = change.getRootNode();
final InstanceIdentifier<Node> identifier = change.getRootPath().getRootIdentifier();
switch (rootNode.getModificationType()) {
}
private static Device newDevice(final String id, final PublicKey serverKey, final Device1.DeviceStatus status) {
+ // used only for netconf devices that are connected via SSH transport and global credentials
String sshEncodedKey = serverKey.toString();
try {
sshEncodedKey = AuthorizedKeysDecoder.encodePublicKey(serverKey);
} catch (IOException e) {
LOG.warn("Unable to encode public key to ssh format.", e);
}
- Device1 d1 = new Device1Builder().setDeviceStatus(Device1.DeviceStatus.FAILEDNOTALLOWED).build();
- DeviceBuilder builder = new DeviceBuilder()
+ final SshClientParams sshParams = new SshClientParamsBuilder().setHostKey(sshEncodedKey).build();
+ final Transport transport = new SshBuilder().setSshClientParams(sshParams).build();
+ return new DeviceBuilder()
.setUniqueId(id)
.withKey(new DeviceKey(id))
- .setSshHostKey(sshEncodedKey)
- .addAugmentation(Device1.class, d1);
-
- return builder.build();
+ .setTransport(transport)
+ .addAugmentation(new Device1Builder().setDeviceStatus(status).build())
+ .build();
}
private Device readAndGetDevice(final NodeId nodeId) {
private static InstanceIdentifier<Device> buildDeviceInstanceIdentifier(final NodeId nodeId) {
return InstanceIdentifier.create(NetconfCallhomeServer.class)
- .child(AllowedDevices.class)
- .child(Device.class, new DeviceKey(nodeId.getValue()));
+ .child(AllowedDevices.class)
+ .child(Device.class, new DeviceKey(nodeId.getValue()));
}
private static Device withConnectedStatus(final Device opDev) {
- Device1 status = new Device1Builder().setDeviceStatus(Device1.DeviceStatus.CONNECTED).build();
- return new DeviceBuilder().addAugmentation(Device1.class, status).setUniqueId(opDev.getUniqueId())
- .setSshHostKey(opDev.getSshHostKey()).build();
+ return deviceWithStatus(opDev, Device1.DeviceStatus.CONNECTED);
}
private static Device withFailedStatus(final Device opDev) {
- Device1 status = new Device1Builder().setDeviceStatus(Device1.DeviceStatus.FAILED).build();
- return new DeviceBuilder().addAugmentation(Device1.class, status).setUniqueId(opDev.getUniqueId())
- .setSshHostKey(opDev.getSshHostKey()).build();
+ return deviceWithStatus(opDev, DeviceStatus.FAILED);
}
private static Device withDisconnectedStatus(final Device opDev) {
- Device1 status = new Device1Builder().setDeviceStatus(Device1.DeviceStatus.DISCONNECTED).build();
- return new DeviceBuilder().addAugmentation(Device1.class, status).setUniqueId(opDev.getUniqueId())
- .setSshHostKey(opDev.getSshHostKey()).build();
+ return deviceWithStatus(opDev, DeviceStatus.DISCONNECTED);
}
private static Device withFailedAuthStatus(final Device opDev) {
- Device1 status = new Device1Builder().setDeviceStatus(Device1.DeviceStatus.FAILEDAUTHFAILURE).build();
- return new DeviceBuilder().addAugmentation(Device1.class, status).setUniqueId(opDev.getUniqueId())
- .setSshHostKey(opDev.getSshHostKey()).build();
+ return deviceWithStatus(opDev, DeviceStatus.FAILEDAUTHFAILURE);
+ }
+
+ private static Device deviceWithStatus(final Device opDev, final DeviceStatus status) {
+ final DeviceBuilder deviceBuilder = new DeviceBuilder()
+ .setUniqueId(opDev.getUniqueId())
+ .addAugmentation(new Device1Builder().setDeviceStatus(status).build());
+ if (opDev.getTransport() != null) {
+ deviceBuilder.setTransport(opDev.getTransport());
+ } else {
+ deviceBuilder.setSshHostKey(opDev.getSshHostKey());
+ }
+ return deviceBuilder.build();
}
private void setDeviceStatus(final Device device) {
return rxTransaction.read(LogicalDatastoreType.OPERATIONAL, IetfZeroTouchCallHomeServerProvider.ALL_DEVICES)
.get().orElse(null);
} catch (ExecutionException | InterruptedException e) {
- LOG.error("Error trying to read the whitelist devices", e);
+ LOG.error("Error trying to read the allowlist devices", e);
return null;
}
}
- private List<Device> getDevicesAsList() {
+ private Collection<Device> getDevicesAsList() {
AllowedDevices devices = getDevices();
- return devices == null ? new ArrayList<>() : devices.getDevice();
+ return devices == null ? Collections.emptyList() : devices.nonnullDevice().values();
}
@Override
public void reportFailedAuth(final PublicKey sshKey) {
AuthorizedKeysDecoder decoder = new AuthorizedKeysDecoder();
- for (Device device : getDevicesAsList()) {
- String keyString = device.getSshHostKey();
+ for (final Device device : getDevicesAsList()) {
+ final String keyString;
+ if (device.getTransport() instanceof Ssh) {
+ keyString = ((Ssh) device.getTransport()).getSshClientParams().getHostKey();
+ } else {
+ keyString = device.getSshHostKey();
+ }
if (keyString == null) {
- LOG.info("Whitelist device {} does not have a host key, skipping it", device.getUniqueId());
+ LOG.info("Allowlist device {} does not have a host key, skipping it", device.getUniqueId());
continue;
}
}
}
- LOG.error("No match found for the failed auth device (should have been filtered by whitelist). Key: {}",
+ LOG.error("No match found for the failed auth device (should have been filtered by allowlist). Key: {}",
sshKey);
}