]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Add support for https requests on nova metadata
authorJakub Libosvar <libosvar@redhat.com>
Mon, 17 Mar 2014 14:02:58 +0000 (15:02 +0100)
committerJakub Libosvar <libosvar@redhat.com>
Mon, 31 Mar 2014 11:34:14 +0000 (13:34 +0200)
Adds new config value for accessing nova metadata api with SSL. In case
nova api requires client certificate other config values were added
providing client certificate and client private key.

DocImpact

Closes-bug: #1293587
Change-Id: I782a12eb77553f4369b782071b4ad19efb82e5e2

etc/metadata_agent.ini
neutron/agent/metadata/agent.py
neutron/tests/unit/test_metadata_agent.py

index c2f59cd283f8eec6891c9ee122943f315b298ba4..2cd429aba0548b5e589305e8eda304349a6ab59c 100644 (file)
@@ -22,6 +22,20 @@ admin_password = %SERVICE_PASSWORD%
 # TCP Port used by Nova metadata server
 # nova_metadata_port = 8775
 
+# Which protocol to use for requests to Nova metadata server, http or https
+# nova_metadata_protocol = http
+
+# Whether insecure SSL connection should be accepted for Nova metadata server
+# requests
+# nova_metadata_insecure = False
+
+# Client certificate for nova api, needed when nova api requires client
+# certificates
+# nova_client_cert =
+
+# Private key for nova client certificate
+# nova_client_priv_key =
+
 # When proxying metadata requests, Neutron signs the Instance-ID header with a
 # shared secret to prevent spoofing.  You may select any string for a secret,
 # but it must match here and in the configuration used by the Nova Metadata
index 23f4f2793723c0607ada6f89680ea76229a17e21..dd54a59959416d215c02894210af646d8742907a 100644 (file)
@@ -79,7 +79,20 @@ class MetadataProxyHandler(object):
         cfg.StrOpt('metadata_proxy_shared_secret',
                    default='',
                    help=_('Shared secret to sign instance-id request'),
-                   secret=True)
+                   secret=True),
+        cfg.StrOpt('nova_metadata_protocol',
+                   default='http',
+                   choices=['http', 'https'],
+                   help=_("Protocol to access nova metadata, http or https")),
+        cfg.BoolOpt('nova_metadata_insecure', default=False,
+                    help=_("Allow to perform insecure SSL (https) requests to "
+                           "nova metadata")),
+        cfg.StrOpt('nova_client_cert',
+                   default='',
+                   help=_("Client certificate for nova metadata api server.")),
+        cfg.StrOpt('nova_client_priv_key',
+                   default='',
+                   help=_("Private key of client certificate."))
     ]
 
     def __init__(self, conf):
@@ -152,15 +165,22 @@ class MetadataProxyHandler(object):
             'X-Instance-ID-Signature': self._sign_instance_id(instance_id)
         }
 
+        nova_ip_port = '%s:%s' % (self.conf.nova_metadata_ip,
+                                  self.conf.nova_metadata_port)
         url = urlparse.urlunsplit((
-            'http',
-            '%s:%s' % (self.conf.nova_metadata_ip,
-                       self.conf.nova_metadata_port),
+            self.conf.nova_metadata_protocol,
+            nova_ip_port,
             req.path_info,
             req.query_string,
             ''))
 
-        h = httplib2.Http()
+        h = httplib2.Http(ca_certs=self.conf.auth_ca_cert,
+                          disable_ssl_certificate_validation=
+                          self.conf.nova_metadata_insecure)
+        if self.conf.nova_client_cert and self.conf.nova_client_priv_key:
+            h.add_certificate(self.conf.nova_client_priv_key,
+                              self.conf.nova_client_cert,
+                              nova_ip_port)
         resp, content = h.request(url, method=req.method, headers=headers,
                                   body=req.body)
 
index a87cdfd3f9d2192e90b8554817b6a198c0a59c7d..d7fab34a21ea1e2134794cd9bc76435e268bef29 100644 (file)
@@ -41,6 +41,10 @@ class FakeConf(object):
     nova_metadata_ip = '9.9.9.9'
     nova_metadata_port = 8775
     metadata_proxy_shared_secret = 'secret'
+    nova_metadata_protocol = 'http'
+    nova_metadata_insecure = True
+    nova_client_cert = 'nova_cert'
+    nova_client_priv_key = 'nova_priv_key'
 
 
 class TestMetadataProxyHandler(base.BaseTestCase):
@@ -211,7 +215,15 @@ class TestMetadataProxyHandler(base.BaseTestCase):
 
                 retval = self.handler._proxy_request('the_id', 'tenant_id',
                                                      req)
+                mock_http.assert_called_once_with(
+                    ca_certs=None, disable_ssl_certificate_validation=True)
                 mock_http.assert_has_calls([
+                    mock.call().add_certificate(
+                        FakeConf.nova_client_priv_key,
+                        FakeConf.nova_client_cert,
+                        "%s:%s" % (FakeConf.nova_metadata_ip,
+                                   FakeConf.nova_metadata_port)
+                    ),
                     mock.call().request(
                         'http://9.9.9.9:8775/the_path',
                         method=method,