Add support for certs from the tls-certs relation
* Add method for requesting certificates: get_certificate_requests * Update get_certs_and_keys to process certs from vault relation * Create a default handler for certificates_available Change-Id: If24621f2e72b66d58ea15cadeb458cadaf86a483
This commit is contained in:
parent
33fd6a52b5
commit
323edcc8c9
|
@ -10,6 +10,7 @@ import subprocess
|
|||
import charmhelpers.contrib.network.ip as ch_ip
|
||||
import charmhelpers.contrib.openstack.utils as os_utils
|
||||
import charmhelpers.contrib.openstack.ha as os_ha
|
||||
import charmhelpers.contrib.openstack.cert_utils as cert_utils
|
||||
import charmhelpers.core.hookenv as hookenv
|
||||
import charmhelpers.core.host as ch_host
|
||||
import charmhelpers.fetch as fetch
|
||||
|
@ -272,6 +273,12 @@ class OpenStackAPICharm(OpenStackCharm):
|
|||
"get_database_setup() needs to be overriden in the derived "
|
||||
"class")
|
||||
|
||||
def get_certificate_requests(self):
|
||||
"""Return a dict of certificate requests
|
||||
"""
|
||||
return cert_utils.get_certificate_request(
|
||||
json_encode=False).get('cert_requests', {})
|
||||
|
||||
@property
|
||||
def all_packages(self):
|
||||
"""List of packages to be installed
|
||||
|
@ -563,7 +570,8 @@ class HAOpenStackCharm(OpenStackAPICharm):
|
|||
addresses.append(laddr)
|
||||
return sorted(list(set(addresses)))
|
||||
|
||||
def get_certs_and_keys(self, keystone_interface=None):
|
||||
def get_certs_and_keys(self, keystone_interface=None,
|
||||
certificates_interface=None):
|
||||
"""Collect SSL config for local endpoints
|
||||
|
||||
SSL keys and certs may come from user specified configuration for this
|
||||
|
@ -601,6 +609,21 @@ class HAOpenStackCharm(OpenStackAPICharm):
|
|||
'ca': ca,
|
||||
'cn': addr})
|
||||
return keys_and_certs
|
||||
elif certificates_interface:
|
||||
keys_and_certs = []
|
||||
reqs = certificates_interface.get_batch_requests()
|
||||
ca = certificates_interface.get_ca()
|
||||
chain = certificates_interface.get_chain()
|
||||
for cn, data in sorted(reqs.items()):
|
||||
cert = data['cert']
|
||||
if chain:
|
||||
cert = cert + chain
|
||||
keys_and_certs.append({
|
||||
'key': data['key'],
|
||||
'cert': cert,
|
||||
'ca': ca,
|
||||
'cn': cn})
|
||||
return keys_and_certs
|
||||
else:
|
||||
return []
|
||||
|
||||
|
@ -645,8 +668,11 @@ class HAOpenStackCharm(OpenStackAPICharm):
|
|||
relations.endpoint_from_flag('identity-service.available.ssl') or
|
||||
relations
|
||||
.endpoint_from_flag('identity-service.available.ssl_legacy'))
|
||||
certificates_interface = relations.endpoint_from_flag(
|
||||
'certificates.batch.cert.available')
|
||||
ssl_objects = self.get_certs_and_keys(
|
||||
keystone_interface=keystone_interface)
|
||||
keystone_interface=keystone_interface,
|
||||
certificates_interface=certificates_interface)
|
||||
with is_data_changed('configure_ssl.ssl_objects',
|
||||
ssl_objects) as changed:
|
||||
if ssl_objects:
|
||||
|
@ -656,7 +682,8 @@ class HAOpenStackCharm(OpenStackAPICharm):
|
|||
self.configure_cert(
|
||||
ssl['cert'], ssl['key'], cn=ssl['cn'])
|
||||
self.configure_ca(ssl['ca'])
|
||||
|
||||
cert_utils.create_ip_cert_links(
|
||||
os.path.join('/etc/apache2/ssl/', self.name))
|
||||
if not os_utils.snap_install_requested():
|
||||
self.configure_apache()
|
||||
ch_host.service_reload('apache2')
|
||||
|
|
|
@ -18,6 +18,7 @@ ALLOWED_DEFAULT_HANDLERS = [
|
|||
'charm.default-select-package-type',
|
||||
'update-status',
|
||||
'upgrade-charm',
|
||||
'certificates.available',
|
||||
]
|
||||
|
||||
# Where to store the default handler functions for each default state
|
||||
|
@ -136,6 +137,16 @@ def make_default_amqp_connection_handler():
|
|||
reactive.set_state('charms.openstack.do-default-amqp.connected')
|
||||
|
||||
|
||||
@_map_default_handler('certificates.available')
|
||||
def make_default_certificates_available_handler():
|
||||
"""Set the default certificates.available state so that the default handler in
|
||||
layer-openstack can run.
|
||||
Convoluted, because charms.reactive will only run handlers in the reactive
|
||||
or hooks directory.
|
||||
"""
|
||||
reactive.set_state('charms.openstack.do-default-certificates.available')
|
||||
|
||||
|
||||
@_map_default_handler('shared-db.connected')
|
||||
def make_default_setup_database_handler():
|
||||
"""Set the default shared-db.connected state so that the default handler in
|
||||
|
|
|
@ -31,6 +31,8 @@ sys.modules['charmhelpers.contrib'] = charmhelpers.contrib
|
|||
sys.modules['charmhelpers.contrib.openstack'] = charmhelpers.contrib.openstack
|
||||
sys.modules['charmhelpers.contrib.openstack.ha'] = (
|
||||
charmhelpers.contrib.openstack.ha)
|
||||
sys.modules['charmhelpers.contrib.openstack.cert_utils'] = (
|
||||
charmhelpers.contrib.openstack.cert_utils)
|
||||
sys.modules['charmhelpers.contrib.openstack.utils'] = (
|
||||
charmhelpers.contrib.openstack.utils)
|
||||
sys.modules['charmhelpers.contrib.openstack.templating'] = (
|
||||
|
|
|
@ -344,6 +344,24 @@ class TestOpenStackAPICharm(BaseOpenStackCharmTest):
|
|||
with self.assertRaises(RuntimeError):
|
||||
self.target.get_database_setup()
|
||||
|
||||
def test_get_certificate_requests(self):
|
||||
self.patch_object(
|
||||
chm.cert_utils,
|
||||
'get_certificate_request',
|
||||
return_value={'cert_requests': {'test.e.c': {'sans': ['san1']}}})
|
||||
self.assertEqual(
|
||||
self.target.get_certificate_requests(),
|
||||
{'test.e.c': {'sans': ['san1']}})
|
||||
|
||||
def test_get_certificate_requests_empty(self):
|
||||
self.patch_object(
|
||||
chm.cert_utils,
|
||||
'get_certificate_request',
|
||||
return_value={})
|
||||
self.assertEqual(
|
||||
self.target.get_certificate_requests(),
|
||||
{})
|
||||
|
||||
def test_all_packages(self):
|
||||
self.patch_target('enable_memcache')
|
||||
self.patch_target('packages', new=['pkg1', 'pkg2'])
|
||||
|
@ -761,6 +779,61 @@ class TestHAOpenStackCharm(BaseOpenStackCharmTest):
|
|||
self.target.get_certs_and_keys(keystone_interface=KSInterface()),
|
||||
expect)
|
||||
|
||||
def test_get_certs_and_keys_certs_interface(self):
|
||||
class CertsInterface(object):
|
||||
|
||||
def get_batch_requests(self):
|
||||
req = {
|
||||
'int_addr': {
|
||||
'cert': 'int_cert',
|
||||
'key': 'int_key'},
|
||||
'priv_addr': {
|
||||
'cert': 'priv_cert',
|
||||
'key': 'priv_key'},
|
||||
'pub_addr': {
|
||||
'cert': 'pub_cert',
|
||||
'key': 'pub_key'},
|
||||
'admin_addr': {
|
||||
'cert': 'admin_cert',
|
||||
'key': 'admin_key'}}
|
||||
return req
|
||||
|
||||
def get_ca(self):
|
||||
return 'CA'
|
||||
|
||||
def get_chain(self):
|
||||
return 'CHAIN'
|
||||
|
||||
self.patch_object(chm.os_utils, 'snap_install_requested',
|
||||
return_value=False)
|
||||
expect = [
|
||||
{
|
||||
'ca': 'CA',
|
||||
'cert': 'admin_certCHAIN',
|
||||
'cn': 'admin_addr',
|
||||
'key': 'admin_key'},
|
||||
{
|
||||
'ca': 'CA',
|
||||
'cert': 'int_certCHAIN',
|
||||
'cn': 'int_addr',
|
||||
'key': 'int_key'},
|
||||
{
|
||||
'ca': 'CA',
|
||||
'cert': 'priv_certCHAIN',
|
||||
'cn': 'priv_addr',
|
||||
'key': 'priv_key'},
|
||||
{
|
||||
'ca': 'CA',
|
||||
'cert': 'pub_certCHAIN',
|
||||
'cn': 'pub_addr',
|
||||
'key': 'pub_key'},
|
||||
]
|
||||
|
||||
self.assertEqual(
|
||||
self.target.get_certs_and_keys(
|
||||
certificates_interface=CertsInterface()),
|
||||
expect)
|
||||
|
||||
def test_config_defined_certs_and_keys(self):
|
||||
# test that the cached parameters do what we expect
|
||||
config = {
|
||||
|
|
Loading…
Reference in New Issue