Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring around _manage_ca_certs() (#570) #571

Open
wants to merge 1 commit into
base: stable/21.01
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions charmhelpers/contrib/openstack/cert_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
)

from charmhelpers.core.host import (
CA_CERT_DIR,
ca_cert_absolute_path,
install_ca_cert,
mkdir,
write_file,
Expand Down Expand Up @@ -307,6 +307,26 @@ def install_certs(ssl_dir, certs, chain=None, user='root', group='root'):
content=bundle['key'], perms=0o640)


def get_cert_relation_ca_name(cert_relation_id=None):
"""Determine CA certificate name as provided by relation.

The filename on disk depends on the name chosen for the application on the
providing end of the certificates relation.

:param cert_relation_id: (Optional) Relation id providing the certs
:type cert_relation_id: str
:returns: CA certificate filename without path nor extension
:rtype: str
"""
if cert_relation_id is None:
try:
cert_relation_id = relation_ids('certificates')[0]
except IndexError:
return ''
return '{}_juju_ca_cert'.format(
remote_service_name(relid=cert_relation_id))


def _manage_ca_certs(ca, cert_relation_id):
"""Manage CA certs.

Expand All @@ -316,7 +336,7 @@ def _manage_ca_certs(ca, cert_relation_id):
:type cert_relation_id: str
"""
config_ssl_ca = config('ssl_ca')
config_cert_file = '{}/{}.crt'.format(CA_CERT_DIR, CONFIG_CA_CERT_FILE)
config_cert_file = ca_cert_absolute_path(CONFIG_CA_CERT_FILE)
if config_ssl_ca:
log("Installing CA certificate from charm ssl_ca config to {}".format(
config_cert_file), INFO)
Expand All @@ -329,8 +349,7 @@ def _manage_ca_certs(ca, cert_relation_id):
log("Installing CA certificate from certificate relation", INFO)
install_ca_cert(
ca.encode(),
name='{}_juju_ca_cert'.format(
remote_service_name(relid=cert_relation_id)))
name=get_cert_relation_ca_name(cert_relation_id))


def process_certificates(service_name, relation_id, unit,
Expand Down
13 changes: 12 additions & 1 deletion charmhelpers/core/host.py
Original file line number Diff line number Diff line change
Expand Up @@ -1068,6 +1068,17 @@ def modulo_distribution(modulo=3, wait=30, non_zero_wait=False):
return calculated_wait_time


def ca_cert_absolute_path(basename_without_extension):
"""Returns absolute path to CA certificate.

:param basename_without_extension: Filename without extension
:type basename_without_extension: str
:returns: Absolute full path
:rtype: str
"""
return '{}/{}.crt'.format(CA_CERT_DIR, basename_without_extension)


def install_ca_cert(ca_cert, name=None):
"""
Install the given cert as a trusted CA.
Expand All @@ -1083,7 +1094,7 @@ def install_ca_cert(ca_cert, name=None):
ca_cert = ca_cert.encode('utf8')
if not name:
name = 'juju-{}'.format(charm_name())
cert_file = '{}/{}.crt'.format(CA_CERT_DIR, name)
cert_file = ca_cert_absolute_path(name)
new_hash = hashlib.md5(ca_cert).hexdigest()
if file_hash(cert_file) == new_hash:
return
Expand Down
23 changes: 23 additions & 0 deletions tests/contrib/openstack/test_cert_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,29 @@ def test_process_certificates_bindings(
custom_hostname_link='funky-name',
bindings=['mybinding', 'internal', 'admin', 'public'])

@mock.patch.object(cert_utils, 'remote_service_name')
@mock.patch.object(cert_utils, 'relation_ids')
def test_get_cert_relation_ca_name(self, relation_ids, remote_service_name):
remote_service_name.return_value = 'vault'

# Test with argument:
self.assertEqual(cert_utils.get_cert_relation_ca_name('certificates:1'),
'vault_juju_ca_cert')
remote_service_name.assert_called_once_with(relid='certificates:1')
remote_service_name.reset_mock()

# Test without argument:
relation_ids.return_value = ['certificates:2']
self.assertEqual(cert_utils.get_cert_relation_ca_name(),
'vault_juju_ca_cert')
remote_service_name.assert_called_once_with(relid='certificates:2')
remote_service_name.reset_mock()

# Test without argument nor 'certificates' relation:
relation_ids.return_value = []
self.assertEqual(cert_utils.get_cert_relation_ca_name(), '')
remote_service_name.assert_not_called()

@mock.patch.object(cert_utils, 'remote_service_name')
@mock.patch.object(cert_utils.os, 'remove')
@mock.patch.object(cert_utils.os.path, 'exists')
Expand Down