From ef7ee76a416cb9fa489651bb365d6f80673a1a82 Mon Sep 17 00:00:00 2001 From: Justin Pettit Date: Mon, 27 Dec 2010 17:44:33 -0800 Subject: [PATCH] vswitch: Provide option to pull cert from SSL table 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 00fcd3c4..07ad3982 100755 --- a/debian/ovs-monitor-ipsec +++ b/debian/ovs-monitor-ipsec @@ -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) diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 9ae21d12..11db0999 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'", -- 2.30.2