Merge "Bug 460 - Fix warning throughout netconf subsystem"
[controller.git] / opendaylight / netconf / netconf-util / src / main / java / org / opendaylight / controller / netconf / util / osgi / NetconfConfigUtil.java
index 76068399c17f470b249c0ba35027f89d723b5d81..b23a2d6697b2ab5623431741fb0ecb374cb22411 100644 (file)
 package org.opendaylight.controller.netconf.util.osgi;
 
 import com.google.common.base.Optional;
-import org.opendaylight.protocol.util.SSLUtil;
 import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
 import java.net.InetSocketAddress;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
 
-public class NetconfConfigUtil {
+public final class NetconfConfigUtil {
+    private static final Logger logger = LoggerFactory.getLogger(NetconfConfigUtil.class);
+
     private static final String PREFIX_PROP = "netconf.";
 
+    private NetconfConfigUtil() {}
+
     private enum InfixProp {
-        tcp, tls
+        tcp, ssh
     }
 
     private static final String PORT_SUFFIX_PROP = ".port";
     private static final String ADDRESS_SUFFIX_PROP = ".address";
+    private static final String CLIENT_PROP = ".client";
+    private static final String PRIVATE_KEY_PATH_PROP = ".pk.path";
 
-    private static final String NETCONF_TLS_KEYSTORE_PROP = PREFIX_PROP + InfixProp.tls + ".keystore";
-    private static final String NETCONF_TLS_KEYSTORE_PASSWORD_PROP = NETCONF_TLS_KEYSTORE_PROP + ".password";
+    private static final String CONNECTION_TIMEOUT_MILLIS_PROP = "connectionTimeoutMillis";
+    private static final long DEFAULT_TIMEOUT_MILLIS = 5000;
 
-    public static Optional<InetSocketAddress> extractTCPNetconfAddress(BundleContext context) {
-        return extractSomeNetconfAddress(context, InfixProp.tcp);
-    }
-
-    public static Optional<TLSConfiguration> extractTLSConfiguration(BundleContext context) {
-        Optional<InetSocketAddress> address = extractSomeNetconfAddress(context, InfixProp.tls);
-        if (address.isPresent()) {
-            String keystoreFileName = context.getProperty(NETCONF_TLS_KEYSTORE_PROP);
-            File keystoreFile = new File(keystoreFileName);
-            checkState(keystoreFile.exists() && keystoreFile.isFile() && keystoreFile.canRead(),
-                    "Keystore file %s does not exist or is not readable file", keystoreFileName);
-            keystoreFile = keystoreFile.getAbsoluteFile();
-            String keystorePassword = context.getProperty(NETCONF_TLS_KEYSTORE_PASSWORD_PROP);
-            checkNotNull(keystoreFileName, "Property %s must be defined for tls netconf server",
-                    NETCONF_TLS_KEYSTORE_PROP);
-            keystorePassword = keystorePassword != null ? keystorePassword : "";
-            return Optional.of(new TLSConfiguration(address.get(), keystoreFile, keystorePassword));
-        } else {
-            return Optional.absent();
+    public static long extractTimeoutMillis(BundleContext bundleContext) {
+        String key = PREFIX_PROP + CONNECTION_TIMEOUT_MILLIS_PROP;
+        String timeoutString = bundleContext.getProperty(key);
+        if (timeoutString == null || timeoutString.length() == 0) {
+            return DEFAULT_TIMEOUT_MILLIS;
+        }
+        try {
+            return Long.parseLong(timeoutString);
+        }catch(NumberFormatException e) {
+            logger.warn("Cannot parse {} property: {}, using defaults", key, timeoutString, e);
+            return DEFAULT_TIMEOUT_MILLIS;
         }
     }
 
-    public static class TLSConfiguration {
-        private final InetSocketAddress address;
-        private final File keystoreFile;
-        private final String keystorePassword;
-        private final SSLContext sslContext;
-
-        TLSConfiguration(InetSocketAddress address, File keystoreFile, String keystorePassword) {
-            this.address = address;
-            this.keystoreFile = keystoreFile;
-            this.keystorePassword = keystorePassword;
-            try {
-                try (InputStream keyStoreIS = new FileInputStream(keystoreFile)) {
-                    try (InputStream trustStoreIS = new FileInputStream(keystoreFile)) {
-                        sslContext = SSLUtil.initializeSecureContext("password", keyStoreIS, trustStoreIS, KeyManagerFactory.getDefaultAlgorithm());
-                    }
-                }
-            } catch (Exception e) {
-                throw new RuntimeException("Cannot initialize ssl context for netconf file " + keystoreFile, e);
-            }
-        }
+    public static InetSocketAddress extractTCPNetconfAddress(BundleContext context, String exceptionMessageIfNotFound, boolean forClient) {
 
-        public SSLContext getSslContext() {
-            return sslContext;
-        }
+        Optional<InetSocketAddress> inetSocketAddressOptional = extractSomeNetconfAddress(context, InfixProp.tcp, exceptionMessageIfNotFound, forClient);
 
-        public InetSocketAddress getAddress() {
-            return address;
+        if (!inetSocketAddressOptional.isPresent()) {
+            throw new IllegalStateException("Netconf tcp address not found." + exceptionMessageIfNotFound);
         }
-
-        public File getKeystoreFile() {
-            return keystoreFile;
+        InetSocketAddress inetSocketAddress = inetSocketAddressOptional.get();
+        if (inetSocketAddress.getAddress().isAnyLocalAddress()) {
+            logger.warn("Unprotected netconf TCP address is configured to ANY local address. This is a security risk. " +
+                    "Consider changing {} to 127.0.0.1", PREFIX_PROP + InfixProp.tcp + ADDRESS_SUFFIX_PROP);
         }
+        return inetSocketAddress;
+    }
 
-        public String getKeystorePassword() {
-            return keystorePassword;
-        }
+    public static Optional<InetSocketAddress> extractSSHNetconfAddress(BundleContext context, String exceptionMessage) {
+        return extractSomeNetconfAddress(context, InfixProp.ssh, exceptionMessage, false);
     }
 
+    public static String getPrivateKeyPath(BundleContext context){
+        return getPropertyValue(context,PREFIX_PROP + InfixProp.ssh +PRIVATE_KEY_PATH_PROP);
+    }
+    private static String getPropertyValue(BundleContext context, String propertyName){
+        String propertyValue = context.getProperty(propertyName);
+        if (propertyValue == null){
+            throw new IllegalStateException("Cannot find initial property with name '"+propertyName+"'");
+        }
+        return propertyValue;
+    }
     /**
      * @param context
      *            from which properties are being read.
      * @param infixProp
-     *            either tcp or tls
-     * @return absent if address is missing, value if address and port are
-     *         valid.
+     *            either tcp or ssh
+     * @return value if address and port are valid.
      * @throws IllegalStateException
-     *             if address or port are invalid
+     *             if address or port are invalid, or configuration is missing
      */
     private static Optional<InetSocketAddress> extractSomeNetconfAddress(BundleContext context,
-            InfixProp infixProp) {
-        String address = context.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
-        if (address == null) {
-            return Optional.absent();
+                                                                         InfixProp infixProp,
+                                                                         String exceptionMessage,
+                                                                         boolean client) {
+        String address = "";
+        if (client) {
+            address = context.getProperty(PREFIX_PROP + infixProp + CLIENT_PROP + ADDRESS_SUFFIX_PROP);
+        }
+        if (address == null || address.equals("")){
+            address = context.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
+        }
+        if (address == null || address.equals("")) {
+            throw new IllegalStateException("Cannot find initial netconf configuration for parameter    "
+                    +PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP
+                    +" in config.ini. "+exceptionMessage);
+        }
+        String portKey = "";
+        if (client) {
+            portKey = PREFIX_PROP + infixProp + CLIENT_PROP + PORT_SUFFIX_PROP;
+        }
+        if (portKey == null || portKey.equals("")){
+            portKey = PREFIX_PROP + infixProp + PORT_SUFFIX_PROP;
         }
-        String portKey = PREFIX_PROP + infixProp + PORT_SUFFIX_PROP;
         String portString = context.getProperty(portKey);
         checkNotNull(portString, "Netconf port must be specified in properties file with " + portKey);
         try {