Add support for pluggable secrets backend

Secrets configuration will be provided from a subordinate charm
utilizing the barbican-secrets interface.

Switch to .stestr.conf

Depends-On: I9d52243ab0ccc60eade6c8023d9c5831a1637338
Change-Id: Ibac7465f30c9a6d3e838d38b80df4092b737251b
This commit is contained in:
Frode Nordahl 2018-10-17 16:58:55 +02:00
parent 3082897e9e
commit fea4e7e77a
No known key found for this signature in database
GPG Key ID: 6A5D59A3BA48373F
10 changed files with 74 additions and 12 deletions

3
.stestr.conf Normal file
View File

@ -0,0 +1,3 @@
[DEFAULT]
test_path=./unit_tests
top_dir=./

View File

@ -1,8 +0,0 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
${PYTHON:-python} -m subunit.run discover -t ./ ./unit_tests $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list

View File

@ -4,6 +4,7 @@ includes:
- interface:rabbitmq
- interface:keystone
- interface:barbican-hsm
- interface:barbican-secrets
repo: https://github.com/openstack/charm-barbican
options:
basic:

View File

@ -78,6 +78,18 @@ def slot_id(hsm):
return ''
@charms_openstack.adapters.adapter_property('secrets')
def plugins(secrets):
"""Provide a plugins property to the template if it exists"""
return secrets.relation.plugins
@charms_openstack.adapters.adapter_property('secrets')
def plugins_string(secrets):
"""Provide a plugins_string property to the template if it exists"""
return secrets.relation.plugins_string
class BarbicanCharm(charms_openstack.charm.HAOpenStackCharm):
"""BarbicanCharm provides the specialisation of the OpenStackCharm
functionality to manage a barbican unit.

View File

@ -24,3 +24,6 @@ requires:
hsm:
interface: barbican-hsm
optional: true
secrets:
interface: barbican-secrets
optional: true

View File

@ -53,5 +53,16 @@ def render_stuff(*args):
hookenv.log("about to call the render_configs with {}".format(args))
with charm.provide_charm_instance() as barbican_charm:
barbican_charm.render_with_interfaces(
charm.optional_interfaces(args, 'hsm.available'))
charm.optional_interfaces(args,
'hsm.available',
'secrets.available'))
barbican_charm.assess_status()
@reactive.when('secrets.new-plugin')
def secrets_plugin_configure():
hookenv.log('Received information about secrets plugin',
level=hookenv.INFO)
reactive.clear_flag('secrets.new-plugin')
reactive.set_flag('secrets.available')
reactive.set_flag('config.changed')

View File

@ -15,7 +15,20 @@ host_href = {{ options.external_endpoints.barbican_worker.url }}
[secretstore]
namespace = barbican.secretstore.plugin
{% if secrets and secrets.plugins_string -%}
enabled_secretstore_plugins = {{ secrets.plugins_string }}
{% else %}
enabled_secretstore_plugins = store_crypto
{%- endif %}
{% if secrets -%}
{% for plugin in secrets.plugins -%}
[{{ plugin.name }}_plugin]
{% for key, value in plugin.data.items() -%}
{{ key }} = {{ value }}
{% endfor %}
{% endfor %}
{%- endif %}
[crypto]
namespace = barbican.crypto.plugin

View File

@ -48,7 +48,7 @@ deps = -r{toxinidir}/test-requirements.txt
commands = ostestr {posargs}
[testenv:pep8]
basepython = python3.5
basepython = python3
deps = -r{toxinidir}/test-requirements.txt
commands = flake8 {posargs} src unit_tests

View File

@ -38,6 +38,7 @@ class TestRegisteredHooks(test_utils.TestRegisteredHooks):
'render_stuff': ('shared-db.available',
'identity-service.available',
'amqp.available',),
'secrets_plugin_configure': ('secrets.new-plugin',),
}
}
# test that the hooks were registered via the
@ -45,7 +46,7 @@ class TestRegisteredHooks(test_utils.TestRegisteredHooks):
self.registered_hooks_test_helper(handlers, hook_set, defaults)
class TestRenderStuff(test_utils.PatchHelper):
class TestBarbicanHandlers(test_utils.PatchHelper):
def test_render_stuff(self):
barbican_charm = mock.MagicMock()
@ -56,7 +57,8 @@ class TestRenderStuff(test_utils.PatchHelper):
self.patch_object(handlers.charm, 'optional_interfaces')
def _optional_interfaces(args, *interfaces):
self.assertEqual(interfaces, ('hsm.available', ))
self.assertEqual(interfaces, ('hsm.available',
'secrets.available', ))
return args + ('hsm', )
self.optional_interfaces.side_effect = _optional_interfaces
@ -65,3 +67,13 @@ class TestRenderStuff(test_utils.PatchHelper):
barbican_charm.render_with_interfaces.assert_called_once_with(
('arg1', 'arg2', 'hsm'))
barbican_charm.assess_status.assert_called_once_with()
def test_secrets_plugin_configure(self):
self.patch_object(handlers.reactive, 'clear_flag')
self.patch_object(handlers.reactive, 'set_flag')
handlers.secrets_plugin_configure()
self.clear_flag.assert_called_once_with('secrets.new-plugin')
self.set_flag.assert_has_calls([
mock.call('secrets.available'),
mock.call('config.changed'),
])

View File

@ -61,6 +61,21 @@ class TestHSMProperties(Helper):
self.assertEqual(barbican.slot_id(hsm), 'a-slot_id')
class TestSecretsProperties(Helper):
def test_plugins(self):
secrets = mock.MagicMock()
plugins = {'name': 'a-name'}
secrets.relation.plugins = plugins
self.assertEqual(barbican.plugins(secrets), plugins)
def test_plugins_string(self):
secrets = mock.MagicMock()
plugins_string = 'a-name_plugin'
secrets.relation.plugins_string = plugins_string
self.assertEqual(barbican.plugins_string(secrets), plugins_string)
class TestBarbicanCharm(Helper):
def test_action_generate_mkek(self):