Add SSL support

* Change charm to inherit layer:openstack-api as this is an API charm
  This adds the SSL config options to the charms config.yaml
* Barbican now servers the API service through Apache so add code
  to manage /etc/apache2/conf-available/barbican-api.conf
* Switch BarbicanConfigurationAdapter to be a child of
  APIConfigurationAdapter to inherit methods for configuring haproxy
  and apache2.
* Add reactive handle to configure ssl when identity relation is
  complete
* Move Juno template dir to mitaka as mitaka is the earliest
  supported release.
* Updated host_href in barbican.conf to specify the correct external
  url for accessing the service. Without this clients are redirected
  to the wrong location.
This commit is contained in:
Liam Young 2016-07-18 12:21:11 +00:00
parent 6edcea4d2e
commit d36a55f4ac
10 changed files with 59 additions and 9 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ layers
interfaces
trusty
.testrepository
__pycache__

View File

@ -1,5 +1,5 @@
includes:
- layer:openstack
- layer:openstack-api
- interface:mysql-shared
- interface:rabbitmq
- interface:keystone

View File

@ -33,6 +33,7 @@ PACKAGES = ['barbican-common', 'barbican-api', 'barbican-worker',
BARBICAN_DIR = '/etc/barbican/'
BARBICAN_CONF = BARBICAN_DIR + "barbican.conf"
BARBICAN_API_PASTE_CONF = BARBICAN_DIR + "barbican-api-paste.ini"
BARBICAN_WSGI_CONF = '/etc/apache2/conf-available/barbican-api.conf'
OPENSTACK_RELEASE_KEY = 'barbican-charm.openstack-release-version'
@ -92,14 +93,24 @@ def assess_status():
BarbicanCharm.singleton.assess_status()
def configure_ssl(keystone=None):
"""Use the singleton from the BarbicanCharm to configure ssl
:param keystone: KeystoneRequires() interface class
"""
BarbicanCharm.singleton.configure_ssl(keystone)
###
# Implementation of the Barbican Charm classes
class BarbicanConfigurationAdapter(
charms_openstack.adapters.ConfigurationAdapter):
charms_openstack.adapters.APIConfigurationAdapter):
def __init__(self):
super(BarbicanConfigurationAdapter, self).__init__()
def __init__(self, port_map=None):
super(BarbicanConfigurationAdapter, self).__init__(
service_name='barbican',
port_map=port_map)
if self.keystone_api_version not in ['2', '3', 'none']:
raise ValueError(
"Unsupported keystone-api-version ({}). It should be 2 or 3"
@ -176,10 +187,12 @@ class BarbicanAdapters(charms_openstack.adapters.OpenStackAPIRelationAdapters):
def __init__(self, relations):
super(BarbicanAdapters, self).__init__(
relations, options_instance=BarbicanConfigurationAdapter())
relations,
options_instance=BarbicanConfigurationAdapter(
port_map=BarbicanCharm.api_ports))
class BarbicanCharm(charms_openstack.charm.OpenStackCharm):
class BarbicanCharm(charms_openstack.charm.HAOpenStackCharm):
"""BarbicanCharm provides the specialisation of the OpenStackCharm
functionality to manage a barbican unit.
"""
@ -204,9 +217,11 @@ class BarbicanCharm(charms_openstack.charm.OpenStackCharm):
restart_map = {
BARBICAN_CONF: services,
BARBICAN_API_PASTE_CONF: services,
BARBICAN_WSGI_CONF: services,
}
adapters_class = BarbicanAdapters
ha_resources = ['vips', 'haproxy']
def install(self):
"""Customise the installation, configure the source and then call the

View File

@ -81,3 +81,9 @@ def config_changed():
"""When the configuration changes, assess the unit's status to update any
juju state required"""
barbican.assess_status()
@reactive.when('identity-service.available')
def configure_ssl(keystone):
'''Configure SSL access to Barbican if requested'''
barbican.configure_ssl(keystone)

View File

@ -0,0 +1,18 @@
Listen {{ options.service_listen_info.barbican_worker.public_port }}
Listen {{ options.service_listen_info.barbican_worker.admin_port }}
<VirtualHost *:{{ options.service_listen_info.barbican_worker.public_port }}>
WSGIScriptAlias / /usr/share/barbican/app.wsgi
WSGIDaemonProcess barbican-api user=barbican group=barbican processes=3 threads=10
WSGIProcessGroup barbican-api
ErrorLog /var/log/barbican/barbican-api.log
CustomLog /var/log/barbican/barbican-api.log combined
</VirtualHost>
<VirtualHost *:{{ options.service_listen_info.barbican_worker.admin_port }}>
WSGIScriptAlias / /usr/share/barbican/app.wsgi
WSGIDaemonProcess barbican-api-admin user=barbican group=barbican processes=3 threads=10
WSGIProcessGroup barbican-api-admin
ErrorLog /var/log/barbican/barbican-api.log
CustomLog /var/log/barbican/barbican-api.log combined
</VirtualHost>

View File

@ -6,15 +6,16 @@ verbose = {{ options.verbose }}
debug = {{ options.debug }}
# Address to bind the API server
bind_host = 0.0.0.0
# {{ options.service_listen_info }}
bind_host = {{ options.service_listen_info.barbican_worker.ip }}
# Port to bind the API server to
bind_port = 9311
bind_port = {{ options.service_listen_info.barbican_worker.port }}
# Host name, for use in HATEOAS-style references
# Note: Typically this would be the load balanced endpoint that clients would use
# communicate back with this service.
host_href = http://localhost:9311
host_href = {{ options.external_endpoints.barbican_worker.url }}
# Log to this file. Make sure you do not set the same log
# file for both the API and registry servers!

View File

@ -21,6 +21,8 @@ sys.path.append('src/lib')
# Mock out charmhelpers so that we can test without it.
# also stops sideeffects from occuring.
charmhelpers = mock.MagicMock()
apt_pkg = mock.MagicMock()
sys.modules['apt_pkg'] = apt_pkg
sys.modules['charmhelpers'] = charmhelpers
sys.modules['charmhelpers.core'] = charmhelpers.core
sys.modules['charmhelpers.core.hookenv'] = charmhelpers.core.hookenv

View File

@ -108,6 +108,7 @@ class TestBarbicanHandlers(unittest.TestCase):
'identity-service.available',
'amqp.available',),
'config_changed': ('config.changed', ),
'configure_ssl': ('identity-service.available', ),
}
when_not_patterns = {
'install_packages': ('charm.installed', ),

View File

@ -52,11 +52,13 @@ class Helper(unittest.TestCase):
class TestOpenStackBarbican(Helper):
def test_install(self):
self.patch(barbican.BarbicanCharm, 'set_config_defined_certs_and_keys')
self.patch(barbican.BarbicanCharm.singleton, 'install')
barbican.install()
self.install.assert_called_once_with()
def test_setup_endpoint(self):
self.patch(barbican.BarbicanCharm, 'set_config_defined_certs_and_keys')
self.patch(barbican.BarbicanCharm, 'service_type',
new_callable=mock.PropertyMock)
self.patch(barbican.BarbicanCharm, 'region',
@ -78,6 +80,7 @@ class TestOpenStackBarbican(Helper):
'type1', 'region1', 'public_url', 'internal_url', 'admin_url')
def test_render_configs(self):
self.patch(barbican.BarbicanCharm, 'set_config_defined_certs_and_keys')
self.patch(barbican.BarbicanCharm.singleton, 'render_with_interfaces')
barbican.render_configs('interfaces-list')
self.render_with_interfaces.assert_called_once_with(
@ -88,6 +91,9 @@ class TestBarbicanConfigurationAdapter(Helper):
@mock.patch('charmhelpers.core.hookenv.config')
def test_barbican_configuration_adapter(self, config):
self.patch(
barbican.charms_openstack.adapters.APIConfigurationAdapter,
'get_network_addresses')
reply = {
'keystone-api-version': '2',
}