Merge "Add support for certificates interface."

This commit is contained in:
Zuul 2018-07-17 21:16:28 +00:00 committed by Gerrit Code Review
commit 5083662c27
9 changed files with 99 additions and 42 deletions

View File

@ -0,0 +1 @@
horizon_hooks.py

View File

@ -0,0 +1 @@
horizon_hooks.py

View File

@ -0,0 +1 @@
horizon_hooks.py

View File

@ -52,6 +52,9 @@ VALID_ENDPOINT_TYPES = {
'ADMINURL': 'adminURL',
}
SSL_CERT_FILE = '/etc/apache2/ssl/horizon/cert_dashboard'
SSL_KEY_FILE = '/etc/apache2/ssl/horizon/key_dashboard'
class HorizonHAProxyContext(OSContextGenerator):
def __call__(self):
@ -231,27 +234,37 @@ class ApacheContext(OSContextGenerator):
class ApacheSSLContext(OSContextGenerator):
def __call__(self):
''' Grab cert and key from configuration for SSL config '''
ca_cert = get_ca_cert()
if ca_cert:
ctxt = {'ssl_configured': False}
use_local_ca = True
for rid in relation_ids('certificates'):
if related_units(rid):
use_local_ca = False
if use_local_ca:
ca_cert = get_ca_cert()
if not ca_cert:
return ctxt
install_ca_cert(b64decode(ca_cert))
ssl_cert, ssl_key = get_cert()
if all([ssl_cert, ssl_key]):
with open('/etc/ssl/certs/dashboard.cert', 'w') as cert_out:
cert_out.write(b64decode(ssl_cert))
with open('/etc/ssl/private/dashboard.key', 'w') as key_out:
key_out.write(b64decode(ssl_key))
os.chmod('/etc/ssl/private/dashboard.key', 0600)
ctxt = {
'ssl_configured': True,
'ssl_cert': '/etc/ssl/certs/dashboard.cert',
'ssl_key': '/etc/ssl/private/dashboard.key',
}
ssl_cert, ssl_key = get_cert()
if all([ssl_cert, ssl_key]):
with open('/etc/ssl/certs/dashboard.cert', 'w') as cert_out:
cert_out.write(b64decode(ssl_cert))
with open('/etc/ssl/private/dashboard.key', 'w') as key_out:
key_out.write(b64decode(ssl_key))
os.chmod('/etc/ssl/private/dashboard.key', 0600)
ctxt = {
'ssl_configured': True,
'ssl_cert': '/etc/ssl/certs/dashboard.cert',
'ssl_key': '/etc/ssl/private/dashboard.key',
}
else:
# Use snakeoil ones by default
ctxt = {
'ssl_configured': False,
}
if os.path.exists(SSL_CERT_FILE) and os.path.exists(SSL_KEY_FILE):
ctxt = {
'ssl_configured': True,
'ssl_cert': SSL_CERT_FILE,
'ssl_key': SSL_KEY_FILE,
}
return ctxt

View File

@ -39,6 +39,7 @@ from charmhelpers.fetch import (
)
from charmhelpers.core.host import (
lsb_release,
service_reload,
)
from charmhelpers.contrib.openstack.utils import (
configure_installation_source,
@ -72,6 +73,10 @@ from charmhelpers.contrib.network.ip import (
is_ipv6,
get_relation_ip,
)
from charmhelpers.contrib.openstack.cert_utils import (
get_certificate_request,
process_certificates,
)
from charmhelpers.contrib.hahelpers.apache import install_ca_cert
from charmhelpers.contrib.hahelpers.cluster import get_hacluster_config
from charmhelpers.payload.execd import execd_preinstall
@ -155,6 +160,9 @@ def config_changed():
check_custom_theme()
open_port(80)
open_port(443)
for relid in relation_ids('certificates'):
for unit in related_units(relid):
certs_changed(relation_id=relid, unit=unit)
websso_trusted_dashboard_changed()
@ -397,5 +405,21 @@ def main():
assess_status(CONFIGS)
@hooks.hook('certificates-relation-joined')
def certs_joined(relation_id=None):
relation_set(
relation_id=relation_id,
relation_settings=get_certificate_request())
@hooks.hook('certificates-relation-changed')
def certs_changed(relation_id=None, unit=None):
process_certificates('horizon', relation_id, unit,
custom_hostname_link='dashboard')
CONFIGS.write_all()
service_reload('apache2')
enable_ssl()
if __name__ == '__main__':
main()

View File

@ -35,6 +35,8 @@ requires:
interface: mysql-shared
websso-fid-service-provider:
interface: websso-fid-service-provider
certificates:
interface: tls-certificates
peers:
cluster:
interface: openstack-dashboard-ha

View File

@ -36,6 +36,8 @@ from test_utils import (
)
TO_PATCH = [
'CONFIGS',
'do_action_openstack_upgrade',
'do_openstack_upgrade',
'config_changed',
]
@ -47,28 +49,25 @@ class TestHorizonUpgradeActions(CharmTestCase):
super(TestHorizonUpgradeActions, self).setUp(openstack_upgrade,
TO_PATCH)
@patch('charmhelpers.contrib.openstack.utils.config')
@patch('charmhelpers.contrib.openstack.utils.action_set')
@patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available')
def test_openstack_upgrade_true(self, upgrade_avail,
action_set, config):
upgrade_avail.return_value = True
config.return_value = True
openstack_upgrade.openstack_upgrade()
self.assertTrue(self.do_openstack_upgrade.called)
self.assertTrue(self.config_changed.called)
@patch('charmhelpers.contrib.openstack.utils.config')
@patch('charmhelpers.contrib.openstack.utils.action_set')
@patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available')
def test_openstack_upgrade_false(self, upgrade_avail,
action_set, config):
upgrade_avail.return_value = True
config.return_value = False
def test_openstack_upgrade_true(self):
self.do_action_openstack_upgrade.return_value = True
openstack_upgrade.openstack_upgrade()
self.do_action_openstack_upgrade.assert_called_once_with(
'openstack-dashboard',
self.do_openstack_upgrade,
self.CONFIGS)
self.config_changed.assert_called_once_with()
def test_openstack_upgrade_false(self):
self.do_action_openstack_upgrade.return_value = False
openstack_upgrade.openstack_upgrade()
self.do_action_openstack_upgrade.assert_called_once_with(
'openstack-dashboard',
self.do_openstack_upgrade,
self.CONFIGS)
self.assertFalse(self.do_openstack_upgrade.called)
self.assertFalse(self.config_changed.called)

View File

@ -95,11 +95,13 @@ class TestHorizonContexts(CharmTestCase):
'hsts_max_age_seconds': 15768000,
'custom_theme': False})
@patch.object(horizon_contexts, 'get_ca_cert', lambda: None)
@patch.object(horizon_contexts, 'get_ca_cert', lambda: 'ca_cert')
@patch.object(horizon_contexts, 'install_ca_cert')
@patch('os.chmod')
def test_ApacheSSLContext_enabled(self, _chmod):
def test_ApacheSSLContext_enabled(self, _chmod, _install_ca_cert):
self.relation_ids.return_value = []
self.get_cert.return_value = ('cert', 'key')
self.b64decode.side_effect = ['cert', 'key']
self.b64decode.side_effect = ['ca', 'cert', 'key']
with patch_open() as (_open, _file):
self.assertEqual(horizon_contexts.ApacheSSLContext()(),
{'ssl_configured': True,
@ -115,13 +117,27 @@ class TestHorizonContexts(CharmTestCase):
])
# Security check on key permissions
_chmod.assert_called_with('/etc/ssl/private/dashboard.key', 0o600)
_install_ca_cert.assert_called_once()
@patch.object(horizon_contexts, 'get_ca_cert', lambda: None)
def test_ApacheSSLContext_disabled(self):
self.relation_ids.return_value = []
self.get_cert.return_value = (None, None)
self.assertEqual(horizon_contexts.ApacheSSLContext()(),
{'ssl_configured': False})
@patch.object(horizon_contexts.os.path, 'exists')
def test_ApacheSSLContext_vault(self, _exists):
_exists.return_value = True
self.relation_ids.return_value = ['certificates:60']
self.related_units.return_value = ['vault/0']
self.assertEqual(
horizon_contexts.ApacheSSLContext()(),
{
'ssl_configured': True,
'ssl_cert': '/etc/apache2/ssl/horizon/cert_dashboard',
'ssl_key': '/etc/apache2/ssl/horizon/key_dashboard'})
def test_HorizonContext_defaults(self):
self.assertEqual(horizon_contexts.HorizonContext()(),
{'compress_offline': True, 'debug': False,

View File

@ -273,6 +273,7 @@ class TestHorizonHooks(CharmTestCase):
'identity-service': [
'identity/0',
],
'certificates': [],
}[rname]
self.relation_ids.side_effect = relation_ids_side_effect
@ -287,7 +288,6 @@ class TestHorizonHooks(CharmTestCase):
'webroot': '/horizon',
}[key]
self.config.side_effect = config_side_effect
self.openstack_upgrade_available.return_value = False
self._call_hook('config-changed')
_joined.assert_called_with('identity/0')