vswitch: Provide option to pull cert from SSL table
authorJustin Pettit <jpettit@nicira.com>
Tue, 28 Dec 2010 01:44:33 +0000 (17:44 -0800)
committerJustin Pettit <jpettit@nicira.com>
Wed, 29 Dec 2010 00:26:48 +0000 (16:26 -0800)
Introduce "use_ssl_cert" option to "ipsec_gre" interface types, which
will pull certificate and private key options from the SSL table.  In
the future, multiple SSL entries will be supported through the
configuration database, so use of this option is strongly discouraged as
this "feature" will be retired.

debian/ovs-monitor-ipsec
lib/netdev-vport.c

index 00fcd3c460497c2a8c0013bfdd9157e007a2a4fb..07ad3982377204a31ea279b8d9c27ee64584fe14 100755 (executable)
@@ -202,9 +202,9 @@ path certificate "%s";
         if host in self.psk_hosts:
             raise error.Error("host %s already defined for psk" % host)
 
-        if "certificate" not in vals:
+        if vals["certificate"] == None:
             raise error.Error("'certificate' not defined for %s" % host)
-        elif "private_key" not in vals:
+        elif vals["private_key"] == None:
             # Assume the private key is stored in the same PEM file as 
             # the certificate.  We make a copy of "vals" so that we don't
             # modify the original "vals", which would cause the script
@@ -371,6 +371,8 @@ def keep_table_columns(schema, table_name, column_types):
  
 def monitor_uuid_schema_cb(schema):
     string_type = types.Type(types.BaseType(types.StringType))
+    optional_ssl_type = types.Type(types.BaseType(types.UuidType,
+                                                  ref_table='SSL'), None, 0, 1)
     string_map_type = types.Type(types.BaseType(types.StringType),
                                  types.BaseType(types.StringType),
                                  0, sys.maxint)
@@ -380,6 +382,11 @@ def monitor_uuid_schema_cb(schema):
         schema, "Interface", {"name": string_type,
                               "type": string_type,
                               "options": string_map_type})
+    new_tables["Open_vSwitch"] = keep_table_columns(
+        schema, "Open_vSwitch", {"ssl": optional_ssl_type})
+    new_tables["SSL"] = keep_table_columns(
+        schema, "SSL", {"certificate": string_type,
+                        "private_key": string_type})
     schema.tables = new_tables
 
 def usage():
@@ -410,6 +417,15 @@ def update_ipsec(ipsec, interfaces, new_interfaces):
         except error.Error, msg:
             s_log.warning("skipping ipsec config for %s: %s" % (name, msg))
 
+def get_ssl_cert(data):
+    for ovs_rec in data["Open_vSwitch"].itervalues():
+        if ovs_rec.ssl.as_list():
+            ssl_rec = data["SSL"][ovs_rec.ssl.as_scalar()]
+            return (ssl_rec.certificate.as_scalar(),
+                    ssl_rec.private_key.as_scalar())
+
+    return None
+
 def main(argv):
     try:
         options, args = getopt.gnu_getopt(
@@ -447,30 +463,42 @@ def main(argv):
             idl.wait(poller)
             poller.block()
             continue
+
+        ssl_cert = get_ssl_cert(idl.data)
  
         new_interfaces = {}
         for rec in idl.data["Interface"].itervalues():
             if rec.type.as_scalar() == "ipsec_gre":
                 name = rec.name.as_scalar()
-                peer_cert = rec.options.get("peer_cert")
-                psk = rec.options.get("psk")
+                entry = {
+                    "remote_ip": rec.options.get("remote_ip"),
+                    "local_ip": rec.options.get("local_ip", "0.0.0.0/0"),
+                    "certificate": rec.options.get("certificate"),
+                    "private_key": rec.options.get("private_key"),
+                    "use_ssl_cert": rec.options.get("use_ssl_cert"),
+                    "peer_cert": rec.options.get("peer_cert"),
+                    "psk": rec.options.get("psk") }
 
-                if peer_cert and psk:
+                if entry["peer_cert"] and entry["psk"]:
                     s_log.warning("both 'peer_cert' and 'psk' defined for %s" 
                             % name)
                     continue
-                elif not peer_cert and not psk: 
+                elif not entry["peer_cert"] and not entry["psk"]:
                     s_log.warning("no 'peer_cert' or 'psk' defined for %s" 
                             % name)
                     continue
 
-                new_interfaces[name] = {
-                    "remote_ip": rec.options.get("remote_ip"),
-                    "local_ip": rec.options.get("local_ip", "0.0.0.0/0"),
-                    "certificate": rec.options.get("certificate"),
-                    "private_key": rec.options.get("private_key"),
-                    "peer_cert": peer_cert,
-                    "psk": psk }
+                # The "use_ssl_cert" option is deprecated and will
+                # likely go away in the near future.
+                if entry["use_ssl_cert"] == "true":
+                    if not ssl_cert:
+                        s_log.warning("no valid SSL entry for %s" % name)
+                        continue
+
+                    entry["certificate"] = ssl_cert[0]
+                    entry["private_key"] = ssl_cert[1]
+
+                new_interfaces[name] = entry
  
         if interfaces != new_interfaces:
             update_ipsec(ipsec, interfaces, new_interfaces)
index 9ae21d1208e76c15214ef0b2e46796c0c004ed3e..11db0999deae071868c55b799fdf8c403a3c7ace 100644 (file)
@@ -518,15 +518,28 @@ parse_tunnel_config(const struct netdev_dev *dev, const struct shash *args,
             if (shash_find(args, "certificate")) {
                 ipsec_mech_set = true;
             } else {
-                VLOG_WARN("%s: 'peer_cert' requires 'certificate' argument",
-                          name);
-                return EINVAL;
+                const char *use_ssl_cert;
+
+                /* If the "use_ssl_cert" is true, then "certificate" and
+                 * "private_key" will be pulled from the SSL table.  The
+                 * use of this option is strongly discouraged, since it
+                 * will like be removed when multiple SSL configurations
+                 * are supported by OVS.
+                 */
+                use_ssl_cert = shash_find_data(args, "use_ssl_cert");
+                if (!use_ssl_cert || strcmp(use_ssl_cert, "true")) {
+                    VLOG_WARN("%s: 'peer_cert' requires 'certificate' argument",
+                              name);
+                    return EINVAL;
+                }
+                ipsec_mech_set = true;
             }
         } else if (!strcmp(node->name, "psk") && is_ipsec) {
             ipsec_mech_set = true;
         } else if (is_ipsec 
                 && (!strcmp(node->name, "certificate")
-                    || !strcmp(node->name, "private_key"))) {
+                    || !strcmp(node->name, "private_key")
+                    || !strcmp(node->name, "use_ssl_cert"))) {
             /* Ignore options not used by the netdev. */
         } else {
             VLOG_WARN("%s: unknown %s argument '%s'",