org.opendaylight.netconf.ssh.NetconfNorthboundSshServer Maven / Gradle / Ivy
/*
* Copyright (c) 2016 Inocybe Technologies 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.ssh;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.local.LocalAddress;
import io.netty.util.concurrent.EventExecutor;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.opendaylight.netconf.api.NetconfServerDispatcher;
import org.opendaylight.netconf.auth.AuthProvider;
import org.opendaylight.netconf.shaded.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NetconfNorthboundSshServer {
private static final Logger LOG = LoggerFactory.getLogger(NetconfNorthboundSshServer.class);
// Do not store unencrypted private key
private static final String DEFAULT_PRIVATE_KEY_PATH = null;
private static final String DEFAULT_ALGORITHM = "RSA";
private static final int DEFAULT_KEY_SIZE = 4096;
private final ChannelFuture localServer;
private final SshProxyServer sshProxyServer;
public NetconfNorthboundSshServer(final NetconfServerDispatcher netconfServerDispatcher,
final EventLoopGroup workerGroup,
final EventExecutor eventExecutor,
final String bindingAddress,
final String portNumber,
final AuthProvider authProvider) {
final LocalAddress localAddress = new LocalAddress(portNumber);
localServer = netconfServerDispatcher.createLocalServer(localAddress);
sshProxyServer = new SshProxyServer(Executors.newScheduledThreadPool(1), workerGroup, eventExecutor);
final InetSocketAddress inetAddress = getInetAddress(bindingAddress, portNumber);
final SshProxyServerConfigurationBuilder sshProxyServerConfigurationBuilder =
new SshProxyServerConfigurationBuilder();
sshProxyServerConfigurationBuilder.setBindingAddress(inetAddress);
sshProxyServerConfigurationBuilder.setLocalAddress(localAddress);
sshProxyServerConfigurationBuilder.setAuthenticator(authProvider);
sshProxyServerConfigurationBuilder.setIdleTimeout(Integer.MAX_VALUE);
sshProxyServerConfigurationBuilder.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());
localServer.addListener(future -> {
if (future.isDone() && !future.isCancelled()) {
try {
sshProxyServer.bind(sshProxyServerConfigurationBuilder.createSshProxyServerConfiguration());
LOG.info("Netconf SSH endpoint started successfully at {}", bindingAddress);
} catch (final IOException e) {
throw new IllegalStateException("Unable to start SSH netconf server", e);
}
} else {
LOG.warn("Unable to start SSH netconf server at {}", bindingAddress, future.cause());
throw new IllegalStateException("Unable to start SSH netconf server", future.cause());
}
});
}
private static InetSocketAddress getInetAddress(final String bindingAddress, final String portNumber) {
final IpAddress ipAddress = IetfInetUtil.ipAddressFor(bindingAddress);
final InetAddress inetAd = IetfInetUtil.INSTANCE.inetAddressFor(ipAddress);
return new InetSocketAddress(inetAd, Integer.parseInt(portNumber));
}
public void close() throws IOException {
sshProxyServer.close();
if (localServer.isDone()) {
localServer.channel().close();
} else {
localServer.cancel(true);
}
}
/*
* Called when the underlying reference to EventExecutor is about to be removed from the container allowing
* us to close the ssh server while it still exists.
*/
public void unbind(final ServiceReference> reference) {
LOG.debug("EventExecutor is being removed, closing netconf ssh server. {}", reference);
try {
close();
} catch (final IOException e) {
LOG.error("Closing of ssh server failed while unbinding reference listener.", e);
}
}
}