[ovs-dev] [PATCH 2/2] vswitch: Provide option to pull cert from SSL table

Justin Pettit jpettit at nicira.com
Wed Dec 29 00:07:30 UTC 2010


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 |   54 ++++++++++++++++++++++++++++++++++-----------
 lib/netdev-vport.c       |   21 ++++++++++++++---
 2 files changed, 58 insertions(+), 17 deletions(-)

diff --git a/debian/ovs-monitor-ipsec b/debian/ovs-monitor-ipsec
index 360053d..7f7b70c 100755
--- a/debian/ovs-monitor-ipsec
+++ b/debian/ovs-monitor-ipsec
@@ -199,9 +199,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
@@ -368,6 +368,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)
@@ -377,6 +379,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():
@@ -407,6 +414,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(
@@ -444,30 +460,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)
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 9ae21d1..11db099 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -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'",
-- 
1.7.1





More information about the dev mailing list