Bug 5306: Enable the SSL connection for ovs manager 82/48482/11
authormelserngawy <melserngawy@inocybe.com>
Fri, 18 Nov 2016 14:47:25 +0000 (09:47 -0500)
committerAnil Vishnoi <vishnoianil@gmail.com>
Thu, 2 Feb 2017 17:04:36 +0000 (17:04 +0000)
Use the aaa-cert feature to manage the TLS connection
certificates and add configuration to the southbound-impl
to allow SSL communication.

Change-Id: I1354644b7a4cb30493ce2bc5b33a2d1d504aaae0
Signed-off-by: melserngawy <melserngawy@inocybe.com>
16 files changed:
library/features/pom.xml
library/features/src/main/features/features.xml
library/impl/pom.xml
library/impl/src/main/java/org/opendaylight/ovsdb/lib/OvsdbConnection.java
library/impl/src/main/java/org/opendaylight/ovsdb/lib/impl/OvsdbConnectionService.java
library/impl/src/main/resources/initial/library.cfg
library/impl/src/main/resources/org/opendaylight/blueprint/library.xml
southbound/southbound-features/pom.xml
southbound/southbound-features/src/main/features/features.xml
southbound/southbound-impl/pom.xml
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionManager.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundProvider.java
southbound/southbound-impl/src/main/resources/initial/southbound.cfg
southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionManagerTest.java
southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/OvsdbDataTreeChangeListenerTest.java
southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/SouthboundProviderTest.java

index bb6cc12cb8f7ca28b9de36e93046a3e39250fbac..76d69031b82fcec393970db0805e6b18ad9cd42e 100644 (file)
@@ -24,6 +24,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
     <mdsal.model.version>0.10.0-SNAPSHOT</mdsal.model.version>
     <controller.mdsal.version>1.5.0-SNAPSHOT</controller.mdsal.version>
     <yangtools.version>1.1.0-SNAPSHOT</yangtools.version>
+    <aaa.version>0.5.0-SNAPSHOT</aaa.version>
     <configfile.directory>etc/opendaylight/karaf</configfile.directory>
   </properties>
   <dependencyManagement>
@@ -36,6 +37,13 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
         <type>pom</type>
         <scope>import</scope>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.aaa</groupId>
+        <artifactId>features-aaa</artifactId>
+        <version>${aaa.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
     </dependencies>
   </dependencyManagement>
   <dependencies>
@@ -47,6 +55,13 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <type>xml</type>
       <scope>runtime</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.aaa</groupId>
+      <artifactId>features-aaa</artifactId>
+      <version>${aaa.version}</version>
+      <type>xml</type>
+      <classifier>features</classifier>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>features-mdsal</artifactId>
index 36995ad0e714082f9cf75bd605430416b29d0230..dc4d3549bc7ef48af81837ffd767618c24d35634 100644 (file)
@@ -13,9 +13,12 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   <repository>mvn:org.opendaylight.yangtools/features-yangtools/{{VERSION}}/xml/features</repository>
   <repository>mvn:org.opendaylight.controller/features-mdsal/{{VERSION}}/xml/features</repository>
   <repository>mvn:org.opendaylight.mdsal.model/features-mdsal-model/{{VERSION}}/xml/features</repository>
+  <repository>mvn:org.opendaylight.aaa/features-aaa/{{VERSION}}/xml/features</repository>
+
   <feature name='odl-ovsdb-library' version='${project.version}' description='OpenDaylight :: library'>
     <feature version='${controller.mdsal.version}'>odl-mdsal-broker</feature>
     <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
+    <feature version="${aaa.version}">odl-aaa-cert</feature>
     <bundle>mvn:org.opendaylight.ovsdb/library/{{VERSION}}</bundle>
     <!-- Test only (move to another feature) -->
     <bundle>mvn:org.opendaylight.ovsdb/utils.servicehelper/{{VERSION}}</bundle>
index 9f8c92484d3bff84380e19e45252847ba5043707..e1ed7988a92037c20e2fac0f93f124f898954793 100644 (file)
@@ -66,6 +66,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-binding-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.aaa</groupId>
+      <artifactId>aaa-cert</artifactId>
+      <version>0.5.0-SNAPSHOT</version>
+    </dependency>
 
     <!-- Testing Dependencies -->
     <dependency>
index 6d5a35269f2105f9f837b3a7aade15cdad1cbdba..adbe99bbf6ce6a089abb0d1b9fe54fc52f2af7fa 100644 (file)
@@ -33,7 +33,7 @@ public interface OvsdbConnection {
      * @param port Layer 4 port on which the remote ovsdb server is listening on.
      * @return OvsDBClient The primary Client interface for the ovsdb connection.
      */
-    OvsdbClient connect(InetAddress address, int port);
+    OvsdbClient connect(final InetAddress address, final int port);
 
     /**
      * connect API can be used by the applications to initiate Active ssl
@@ -43,7 +43,8 @@ public interface OvsdbConnection {
      * @param sslContext Netty sslContext for channel configuration
      * @return OvsDBClient The primary Client interface for the ovsdb connection.
      */
-    OvsdbClient connectWithSsl(InetAddress address, int port, SSLContext sslContext);
+    OvsdbClient connectWithSsl(final InetAddress address, final int port,
+                               final SSLContext sslContext);
 
     /**
      * Method to disconnect an existing connection.
@@ -54,12 +55,13 @@ public interface OvsdbConnection {
     /**
      * Method to start ovsdb server for passive connection.
      */
-    boolean startOvsdbManager(int ovsdbListenPort);
+    boolean startOvsdbManager(final int ovsdbListenPort);
 
     /**
      * Method to start ovsdb server for passive connection with SSL.
      */
-    boolean startOvsdbManagerWithSsl(int ovsdbListenPort, SSLContext sslContext);
+    boolean startOvsdbManagerWithSsl(final int ovsdbListenPort,
+                                     final SSLContext sslContext, String[] protocols, String[] cipherSuites);
 
     /**
      * Method to register a Passive Connection Listener with the ConnectionService.
index 0191b5c439ae61b73d37b1f40eb2f20f99b81852..76e43cf8aff72308e3cf979966b37978020fb89e 100644 (file)
@@ -53,6 +53,7 @@ import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLEngineResult.HandshakeStatus;
 import javax.net.ssl.SSLPeerUnverifiedException;
+import org.opendaylight.aaa.cert.api.ICertificateManager;
 import org.opendaylight.ovsdb.lib.OvsdbClient;
 import org.opendaylight.ovsdb.lib.OvsdbConnection;
 import org.opendaylight.ovsdb.lib.OvsdbConnectionInfo.ConnectionType;
@@ -102,6 +103,9 @@ public class OvsdbConnectionService implements AutoCloseable, OvsdbConnection {
     private static final int IDLE_READER_TIMEOUT = 30;
     private static final int READ_TIMEOUT = 180;
     private static final String OVSDB_RPC_TASK_TIMEOUT_PARAM = "ovsdb-rpc-task-timeout";
+    private static final String USE_SSL = "use-ssl";
+    private static boolean useSSL = false;
+    private static ICertificateManager certManagerSrv = null;
 
     private static final StalePassiveConnectionService STALE_PASSIVE_CONNECTION_SERVICE =
             new StalePassiveConnectionService(executorService);
@@ -116,9 +120,21 @@ public class OvsdbConnectionService implements AutoCloseable, OvsdbConnection {
         return connectionService;
     }
 
+    /**
+     * If the SSL flag is enabled, the method internally will establish TLS communication using the default
+     * ODL certificateManager SSLContext and attributes.
+     */
     @Override
     public OvsdbClient connect(final InetAddress address, final int port) {
-        return connectWithSsl(address, port, null /* SslContext */);
+        if (useSSL) {
+            if (certManagerSrv == null) {
+                LOG.error("Certificate Manager service is not available cannot establish the SSL communication.");
+                return null;
+            }
+            return connectWithSsl(address, port, certManagerSrv.getServerContext());
+        } else {
+            return connectWithSsl(address, port, null /* SslContext */);
+        }
     }
 
     @Override
@@ -245,12 +261,12 @@ public class OvsdbConnectionService implements AutoCloseable, OvsdbConnection {
      */
     @Override
     public synchronized boolean startOvsdbManagerWithSsl(final int ovsdbListenPort,
-                                     final SSLContext sslContext) {
+                                     final SSLContext sslContext, String[] protocols, String[] cipherSuites) {
         if (!singletonCreated) {
             new Thread() {
                 @Override
                 public void run() {
-                    ovsdbManagerWithSsl(ovsdbListenPort, sslContext);
+                    ovsdbManagerWithSsl(ovsdbListenPort, sslContext, protocols, cipherSuites);
                 }
             }.start();
             singletonCreated = true;
@@ -263,16 +279,28 @@ public class OvsdbConnectionService implements AutoCloseable, OvsdbConnection {
     /**
      * OVSDB Passive listening thread that uses Netty ServerBootstrap to open
      * passive connection handle channel callbacks.
+     * If the SSL flag is enabled, the method internally will establish TLS communication using the default
+     * ODL certificateManager SSLContext and attributes.
      */
     private static void ovsdbManager(int port) {
-        ovsdbManagerWithSsl(port, null /* SslContext */);
+        if (useSSL) {
+            if (certManagerSrv == null) {
+                LOG.error("Certificate Manager service is not available cannot establish the SSL communication.");
+                return;
+            }
+            ovsdbManagerWithSsl(port, certManagerSrv.getServerContext(), certManagerSrv.getTlsProtocols(),
+                    certManagerSrv.getCipherSuites());
+        } else {
+            ovsdbManagerWithSsl(port, null /* SslContext */, null, null);
+        }
     }
 
     /**
      * OVSDB Passive listening thread that uses Netty ServerBootstrap to open
      * passive connection with Ssl and handle channel callbacks.
      */
-    private static void ovsdbManagerWithSsl(int port, final SSLContext sslContext) {
+    private static void ovsdbManagerWithSsl(int port, final SSLContext sslContext, final String[] protocols,
+            final String[] cipherSuites) {
         EventLoopGroup bossGroup = new NioEventLoopGroup();
         EventLoopGroup workerGroup = new NioEventLoopGroup();
         try {
@@ -290,23 +318,20 @@ public class OvsdbConnectionService implements AutoCloseable, OvsdbConnection {
                                 SSLEngine engine = sslContext.createSSLEngine();
                                 engine.setUseClientMode(false); // work in a server mode
                                 engine.setNeedClientAuth(true); // need client authentication
-                                //Disable SSLv3, TLSv1 and enable all other supported protocols
-                                String[] protocols = {"SSLv2Hello", "TLSv1.1", "TLSv1.2"};
-                                LOG.debug("Set enable protocols {}", Arrays.toString(protocols));
-                                engine.setEnabledProtocols(protocols);
-                                LOG.debug("Supported ssl protocols {}",
-                                        Arrays.toString(engine.getSupportedProtocols()));
-                                LOG.debug("Enabled ssl protocols {}",
-                                        Arrays.toString(engine.getEnabledProtocols()));
-                                //Set cipher suites
-                                String[] cipherSuites = {"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
-                                                         "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
-                                                         "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
-                                                         "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
-                                                         "TLS_RSA_WITH_AES_128_CBC_SHA256"};
-                                engine.setEnabledCipherSuites(cipherSuites);
-                                LOG.debug("Enabled cipher suites {}",
-                                        Arrays.toString(engine.getEnabledCipherSuites()));
+                                if (protocols != null && protocols.length > 0) {
+                                    //Set supported protocols
+                                    engine.setEnabledProtocols(protocols);
+                                    LOG.debug("Supported ssl protocols {}",
+                                            Arrays.toString(engine.getSupportedProtocols()));
+                                    LOG.debug("Enabled ssl protocols {}",
+                                            Arrays.toString(engine.getEnabledProtocols()));
+                                }
+                                if (cipherSuites != null && cipherSuites.length > 0) {
+                                    //Set supported cipher suites
+                                    engine.setEnabledCipherSuites(cipherSuites);
+                                    LOG.debug("Enabled cipher suites {}",
+                                            Arrays.toString(engine.getEnabledCipherSuites()));
+                                }
                                 channel.pipeline().addLast("ssl", new SslHandler(engine));
                             }
 
@@ -521,15 +546,32 @@ public class OvsdbConnectionService implements AutoCloseable, OvsdbConnection {
         JsonRpcEndpoint.setReaperInterval(timeout);
     }
 
+    /**
+     * Set useSSL flag.
+     *
+     * @param flag boolean for using ssl
+     */
+    public void setUseSsl(boolean flag) {
+        useSSL = flag;
+    }
+
+    /**
+     * Set default Certificate manager service.
+     *
+     * @param certificateManagerSrv reference
+     */
+    public void setCertificatManager(ICertificateManager certificateManagerSrv) {
+        certManagerSrv = certificateManagerSrv;
+    }
+
     public void updateConfigParameter(Map<String, Object> configParameters) {
         LOG.debug("Config parameters received : {}", configParameters.entrySet());
         if (configParameters != null && !configParameters.isEmpty()) {
             for (Map.Entry<String, Object> paramEntry : configParameters.entrySet()) {
                 if (paramEntry.getKey().equalsIgnoreCase(OVSDB_RPC_TASK_TIMEOUT_PARAM)) {
                     setOvsdbRpcTaskTimeout(Integer.parseInt((String)paramEntry.getValue()));
-
-                    //Please remove the break if you add more config nobs.
-                    break;
+                } else if (paramEntry.getKey().equalsIgnoreCase(USE_SSL)) {
+                    useSSL = Boolean.parseBoolean(paramEntry.getValue().toString());
                 }
             }
         }
index 79ba8a77e378b32ebf294d40afb2d84e662be110..7622593f7bfb365d323d4d8d33396f3adfb27de5 100644 (file)
@@ -1,4 +1,6 @@
 #Timeout value (in millisecond) after which OVSDB rpc task will be cancelled.
 #Default value is set to 1000ms, please uncomment and override the value if requires
 #Changing the value don't require controller restart.
-#ovsdb-rpc-task-timeout = 1000
\ No newline at end of file
+# ovsdb-rpc-task-timeout = 1000
+#This flag will be enforced across all the connection's (passive and active) if set to true
+# use-ssl = false
index 3f73ab0cf2d8be4d2e6f61ef63798945120349ec..29ca7d924bc27d18076c9f295b18d09dda707fe3 100644 (file)
     specify the property in library.cfg file-->
     <cm:default-properties>
       <cm:property name="ovsdb-rpc-task-timeout" value="1000"/>
+      <cm:property name="use-ssl" value="false"/>
     </cm:default-properties>
   </cm:property-placeholder>
 
+  <reference id="aaaCertificateManager"
+        interface="org.opendaylight.aaa.cert.api.ICertificateManager"
+        odl:type="default-certificate-manager"/>
+
   <bean id="library" class="org.opendaylight.ovsdb.lib.impl.OvsdbConnectionService">
     <property name="ovsdbRpcTaskTimeout" value="${ovsdb-rpc-task-timeout}"/>
+    <property name="useSsl" value="${use-ssl}"/>
+    <property name="certificatManager" ref="aaaCertificateManager"/>
   </bean>
 
   <!-- Notify OvsdbConnectionService with any change in the config properties value-->
@@ -23,6 +30,7 @@
     <cm:managed-properties persistent-id="org.opendaylight.ovsdb.library"
                            update-strategy="component-managed"
                            update-method="updateConfigParameter"/>
+     <property name="certificatManager" ref="aaaCertificateManager"/>
   </bean>
 
   <service ref="ovsdbConnectionService" interface="org.opendaylight.ovsdb.lib.OvsdbConnection"
index 946828a6a3c636452c6261c71d305275b5944001..a4da1019e4a290aa4f162b7c1b9ffe69c43e9db2 100644 (file)
@@ -152,4 +152,4 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <url>${nexus.site.url}/${project.artifactId}/</url>
     </site>
   </distributionManagement>
-</project>
+</project>
\ No newline at end of file
index 50cab4db63cede76ad2f8b2007cf2145d34376ae..27f49a3a07561f6ee50bb0ee62c10084be0ec3ee 100644 (file)
@@ -51,4 +51,4 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <bundle>mvn:org.opendaylight.ovsdb/utils.southbound-utils/{{VERSION}}</bundle>
     <configfile finalname="etc/org.opendaylight.ovsdb.southbound.cfg">mvn:org.opendaylight.ovsdb/southbound-impl/{{VERSION}}/cfg/config</configfile>
   </feature>
-</features>
+</features>
\ No newline at end of file
index a451ca2ee3f1f03b81e77eb7dae89c4931925bbe..1504f96a0f5d576cc1a3772120f0240d2f75eaf6 100644 (file)
@@ -185,4 +185,4 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <url>${nexus.site.url}/${project.artifactId}/</url>
     </site>
   </distributionManagement>
-</project>
+</project>
\ No newline at end of file
index b7964afdefaed50b51e2e31f656aea1b4be5e43f..cfad32d3fd6c9275920ec228064b91184ecf93bd 100644 (file)
@@ -650,4 +650,4 @@ public class OvsdbConnectionManager implements OvsdbConnectionListener, AutoClos
         */
         ON_DISCONNECT
     }
-}
+}
\ No newline at end of file
index 4fff92754af2a486e178c70e8d33beb0b9d846b7..d4a342884210094cbcef1b056034e0180c247b31 100644 (file)
@@ -186,4 +186,4 @@ public class SouthboundProvider implements AutoCloseable {
             SouthboundConstants.SKIP_COLUMN_FROM_TABLE.get("Manager").remove("status");
         }
     }
-}
+}
\ No newline at end of file
index 1299870ae688fe9b808cd7c4011715237415c58d..576d50148190612db4a476284f1db5dceb11682b 100644 (file)
@@ -11,4 +11,4 @@
 # setup. So please use this option when you are running OVSDB
 # southbound plugin in single node and want to achieve better
 # performance.
-#skip-monitoring-manager-status = false
+#skip-monitoring-manager-status = false
\ No newline at end of file
index cc0b71f0a1437245c54702b6aa24a55d94413474..3a44a306c920188d333d32d66779be12606c7e0a 100644 (file)
@@ -376,4 +376,4 @@ public class OvsdbConnectionManagerTest {
         Whitebox.invokeMethod(ovsdbConnManager, "handleOwnershipChanged", ownershipChange);
         PowerMockito.verifyPrivate(ovsdbConnManager, times(1)).invoke("putConnectionInstance", key, ovsdbConnInstance);
     }
-}
+}
\ No newline at end of file
index f66ee09e74f967e6375f9b96022a4b397a2f38b5..09df071b462e0a4c9626818c927a7520618af9c3 100644 (file)
@@ -72,4 +72,4 @@ public class OvsdbDataTreeChangeListenerTest extends AbstractDataBrokerTest {
         // Then the listener tries to open a connection
         Mockito.verify(ovsdbConnection).connect(inetAddress, port);
     }
-}
+}
\ No newline at end of file
index d9ac63a9a419e9e4e738a63d9e044ce636327737..8990f54a0b1883199493e4e56038d977c63ae2c6 100644 (file)
@@ -141,4 +141,4 @@ public class SouthboundProviderTest extends AbstractDataBrokerTest {
                     topologyIid).checkedGet().isPresent());
         }
     }
-}
+}
\ No newline at end of file