Add CA Cert file config option to validate against SSL endpoints

Currently Octavia cannot validate against SSL service endpoints,
which would be keystone, neutron, nova and glance in this case.

This patch adds a config option under nova, neutron and glance
sections to read the specified CA certificate files
for validation. It's slightly different in the case of glance,
because glance session method invocations depend on the endpoint
URL whether it starts with HTTP or HTTPS.

Also added is the "insecure" option for these services in case
the cert validation needs to be skipped.

For keystone, we read config params from keystone middleware. Thus,
instead of defining a new config option, we can make use of it's
pre-defined "cafile".

Barbican is not added because we do not yet have a barbican endpoint
override in it's config. This could be added in the future as a
separate patch, if needed.

Lastly, unrelated to the above, fixes the amphora REST api default
bind_port in octavia.conf

Change-Id: Id57672a3dc7c962b8ee07db0cb7a743041082c66
Closes-Bug: #1552987
This commit is contained in:
Bharath M 2016-03-04 01:14:54 -08:00
parent 79669c925c
commit f4da51c27d
8 changed files with 71 additions and 14 deletions

View File

@ -50,11 +50,14 @@
[keystone_authtoken]
# This group of config options are imported from keystone middleware. Thus the
# option names should match the names declared in the middleware.
# auth_uri = https://localhost:5000/v3
# admin_user = octavia
# admin_password = password
# admin_tenant_name = service
# insecure = False
# cafile =
[keystone_authtoken_v3]
# If using Keystone v3
@ -113,7 +116,7 @@
# REST Driver specific
# bind_host = 0.0.0.0
# bind_port = 9191
# bind_port = 9443
# haproxy_cmd = /usr/sbin/haproxy
# respawn_count = 2
# respawn_interval = 2
@ -230,6 +233,10 @@
# the OpenStack services.
# endpoint_type = publicURL
# CA certificates file to verify glance connections when TLS is enabled
# insecure = False
# ca_certificates_file =
[nova]
# The name of the nova service in the keystone catalog
# service_name =
@ -243,6 +250,10 @@
# the OpenStack services.
# endpoint_type = publicURL
# CA certificates file to verify nova connections when TLS is enabled
# insecure = False
# ca_certificates_file =
# Flag to enable nova anti-affinity capabilities to place amphorae on
# different hosts
# enable_anti_affinity = False
@ -259,3 +270,7 @@
# Endpoint type in Identity service catalog to use for communication with
# the OpenStack services.
# endpoint_type = publicURL
# CA certificates file to verify neutron connections when TLS is enabled
# insecure = False
# ca_certificates_file =

View File

@ -30,24 +30,30 @@ class NovaAuth(object):
@classmethod
def get_nova_client(cls, region, service_name=None, endpoint=None,
endpoint_type='publicURL'):
endpoint_type='publicURL', insecure=False,
cacert=None):
"""Create nova client object.
:param region: The region of the service
:param service_name: The name of the nova service in the catalog
:param endpoint: The endpoint of the service
:param endpoint_type: The type of the endpoint
:param insecure: Turn off certificate validation
:param cacert: CA Cert file path
:return: a Nova Client object.
:raises Exception: if the client cannot be created
"""
if not cls.nova_client:
kwargs = {'region_name': region,
'session': keystone.get_session(),
'endpoint_type': endpoint_type}
'endpoint_type': endpoint_type,
'insecure': insecure}
if service_name:
kwargs['service_name'] = service_name
if endpoint:
kwargs['endpoint_override'] = endpoint
if cacert:
kwargs['cacert'] = cacert
try:
cls.nova_client = nova_client.Client(
NOVA_VERSION, **kwargs)
@ -62,24 +68,30 @@ class NeutronAuth(object):
@classmethod
def get_neutron_client(cls, region, service_name=None, endpoint=None,
endpoint_type='publicURL'):
endpoint_type='publicURL', insecure=False,
ca_cert=None):
"""Create neutron client object.
:param region: The region of the service
:param service_name: The name of the neutron service in the catalog
:param endpoint: The endpoint of the service
:param endpoint_type: The endpoint_type of the service
:param insecure: Turn off certificate validation
:param ca_cert: CA Cert file path
:return: a Neutron Client object.
:raises Exception: if the client cannot be created
"""
if not cls.neutron_client:
kwargs = {'region_name': region,
'session': keystone.get_session(),
'endpoint_type': endpoint_type}
'endpoint_type': endpoint_type,
'insecure': insecure}
if service_name:
kwargs['service_name'] = service_name
if endpoint:
kwargs['endpoint_override'] = endpoint
if ca_cert:
kwargs['ca_cert'] = ca_cert
try:
cls.neutron_client = neutron_client.Client(
NEUTRON_VERSION, **kwargs)
@ -94,13 +106,16 @@ class GlanceAuth(object):
@classmethod
def get_glance_client(cls, region, service_name=None, endpoint=None,
endpoint_type='publicURL'):
endpoint_type='publicURL', insecure=False,
cacert=None):
"""Create glance client object.
:param region: The region of the service
:param service_name: The name of the glance service in the catalog
:param endpoint: The endpoint of the service
:param endpoint_type: The endpoint_type of the service
:param insecure: Turn off certificate validation
:param cacert: CA Cert file path
:return: a Glance Client object.
:raises Exception: if the client cannot be created
"""
@ -112,6 +127,9 @@ class GlanceAuth(object):
kwargs['service_name'] = service_name
if endpoint:
kwargs['endpoint'] = endpoint
if endpoint.startswith("https"):
kwargs['insecure'] = insecure
kwargs['cacert'] = cacert
try:
cls.glance_client = glance_client.Client(
GLANCE_VERSION, **kwargs)

View File

@ -360,6 +360,11 @@ nova_opts = [
'communication with the OpenStack services.')),
cfg.StrOpt('endpoint_type', default='publicURL',
help=_('Endpoint interface in identity service to use')),
cfg.StrOpt('ca_certificates_file',
help=_('CA certificates file path')),
cfg.BoolOpt('insecure',
default=False,
help=_('Disable certificate validation on SSL connections ')),
cfg.BoolOpt('enable_anti_affinity', default=False,
help=_('Flag to indicate if nova anti-affinity feature is '
'turned on.'))
@ -376,6 +381,11 @@ neutron_opts = [
'communication with the OpenStack services.')),
cfg.StrOpt('endpoint_type', default='publicURL',
help=_('Endpoint interface in identity service to use')),
cfg.StrOpt('ca_certificates_file',
help=_('CA certificates file path')),
cfg.BoolOpt('insecure',
default=False,
help=_('Disable certificate validation on SSL connections ')),
]
glance_opts = [
@ -389,6 +399,11 @@ glance_opts = [
'communication with the OpenStack services.')),
cfg.StrOpt('endpoint_type', default='publicURL',
help=_('Endpoint interface in identity service to use')),
cfg.StrOpt('ca_certificates_file',
help=_('CA certificates file path')),
cfg.BoolOpt('insecure',
default=False,
help=_('Disable certificate validation on SSL connections ')),
]

View File

@ -61,7 +61,8 @@ def get_session():
try:
kc = client.Password(**kwargs)
_SESSION = session.Session(
auth=kc, verify=not cfg.CONF.keystone_authtoken.insecure)
auth=kc, verify=(cfg.CONF.keystone_authtoken.cafile or
not cfg.CONF.keystone_authtoken.insecure))
except Exception:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("Error creating Keystone session."))

View File

@ -69,12 +69,16 @@ class VirtualMachineManager(compute_base.ComputeBase):
self._nova_client = clients.NovaAuth.get_nova_client(
endpoint=CONF.nova.endpoint,
region=CONF.nova.region_name,
endpoint_type=CONF.nova.endpoint_type)
endpoint_type=CONF.nova.endpoint_type,
insecure=CONF.nova.insecure,
cacert=CONF.nova.ca_certificates_file)
self._glance_client = clients.GlanceAuth.get_glance_client(
service_name=CONF.glance.service_name,
endpoint=CONF.glance.endpoint,
region=CONF.glance.region_name,
endpoint_type=CONF.glance.endpoint_type)
endpoint_type=CONF.glance.endpoint_type,
insecure=CONF.glance.insecure,
cacert=CONF.glance.ca_certificates_file)
self.manager = self._nova_client.servers
self.server_groups = self._nova_client.server_groups

View File

@ -50,6 +50,8 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver):
region=CONF.nova.region_name,
endpoint_type=CONF.nova.endpoint_type,
service_name=CONF.nova.service_name,
insecure=CONF.nova.insecure,
cacert=CONF.nova.ca_certificates_file
)
def _check_aap_loaded(self):

View File

@ -39,7 +39,9 @@ class BaseNeutronDriver(base.AbstractNetworkDriver):
endpoint=CONF.neutron.endpoint,
region=CONF.neutron.region_name,
endpoint_type=CONF.neutron.endpoint_type,
service_name=CONF.neutron.service_name
service_name=CONF.neutron.service_name,
insecure=CONF.neutron.insecure,
ca_cert=CONF.neutron.ca_certificates_file
)
extensions = self.neutron_client.list_extensions()
self._extensions = extensions.get('extensions')

View File

@ -58,7 +58,7 @@ class TestNovaAuth(base.TestCase):
# Getting the session again should return the same object
bc2 = clients.NovaAuth.get_nova_client(
region="test-region", service_name='novaEndpoint1',
endpoint="test-endpoint", endpoint_type='adminURL')
endpoint="test-endpoint", endpoint_type='adminURL', insecure=True)
self.assertIs(bc1, bc2)
@ -97,7 +97,7 @@ class TestNeutronAuth(base.TestCase):
# Getting the session again should return the same object
bc2 = clients.NeutronAuth.get_neutron_client(
region="test-region", service_name="neutronEndpoint1",
endpoint="test-endpoint", endpoint_type='publicURL')
endpoint="test-endpoint", endpoint_type='publicURL', insecure=True)
self.assertIs(bc1, bc2)
@ -121,7 +121,7 @@ class TestGlanceAuth(base.TestCase):
# Mock out the keystone session and get the client
keystone._SESSION = mock.MagicMock()
bc1 = clients.GlanceAuth.get_glance_client(
region=None, endpoint_type='publicURL')
region=None, endpoint_type='publicURL', insecure=True)
# Our returned client should also be the saved client
self.assertIsInstance(
@ -136,5 +136,5 @@ class TestGlanceAuth(base.TestCase):
# Getting the session again should return the same object
bc2 = clients.GlanceAuth.get_glance_client(
region="test-region", service_name="glanceEndpoint1",
endpoint="test-endpoint", endpoint_type='publicURL')
endpoint="test-endpoint", endpoint_type='publicURL', insecure=True)
self.assertIs(bc1, bc2)