Skip to content

Commit

Permalink
Merge pull request #522 from gnuoy/correct-ca-name
Browse files Browse the repository at this point in the history
Correct name of CA cert file
  • Loading branch information
lourot committed Nov 27, 2020
2 parents 3d991d4 + e3fbd15 commit a012fe7
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 6 deletions.
6 changes: 5 additions & 1 deletion charmhelpers/contrib/hahelpers/apache.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
INFO,
)

# This file contains the CA cert from the charms ssl_ca configuration
# option, in future the file name should be updated reflect that.
CONFIG_CA_CERT_FILE = 'keystone_juju_ca_cert'


def get_cert(cn=None):
# TODO: deal with multiple https endpoints via charm config
Expand Down Expand Up @@ -83,4 +87,4 @@ def retrieve_ca_cert(cert_file):


def install_ca_cert(ca_cert):
host.install_ca_cert(ca_cert, 'keystone_juju_ca_cert')
host.install_ca_cert(ca_cert, CONFIG_CA_CERT_FILE)
35 changes: 33 additions & 2 deletions charmhelpers/contrib/openstack/cert_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import os
import json
from base64 import b64decode

from charmhelpers.contrib.network.ip import (
get_hostname,
Expand All @@ -28,10 +29,12 @@
related_units,
relation_get,
relation_ids,
remote_service_name,
unit_get,
NoNetworkBinding,
log,
WARNING,
INFO,
)
from charmhelpers.contrib.openstack.ip import (
resolve_address,
Expand All @@ -44,12 +47,14 @@
)

from charmhelpers.core.host import (
CA_CERT_DIR,
install_ca_cert,
mkdir,
write_file,
)

from charmhelpers.contrib.hahelpers.apache import (
install_ca_cert
CONFIG_CA_CERT_FILE,
)


Expand Down Expand Up @@ -274,6 +279,32 @@ def install_certs(ssl_dir, certs, chain=None, user='root', group='root'):
content=bundle['key'], perms=0o640)


def _manage_ca_certs(ca, cert_relation_id):
"""Manage CA certs.
:param ca: CA Certificate from certificate relation.
:type ca: str
:param cert_relation_id: Relation id providing the certs
:type cert_relation_id: str
"""
config_ssl_ca = config('ssl_ca')
config_cert_file = '{}/{}.crt'.format(CA_CERT_DIR, CONFIG_CA_CERT_FILE)
if config_ssl_ca:
log("Installing CA certificate from charm ssl_ca config to {}".format(
config_cert_file), INFO)
install_ca_cert(
b64decode(config_ssl_ca).rstrip(),
name=CONFIG_CA_CERT_FILE)
elif os.path.exists(config_cert_file):
log("Removing CA certificate {}".format(config_cert_file), INFO)
os.remove(config_cert_file)
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)))


def process_certificates(service_name, relation_id, unit,
custom_hostname_link=None, user='root', group='root'):
"""Process the certificates supplied down the relation
Expand All @@ -298,7 +329,7 @@ def process_certificates(service_name, relation_id, unit,
ca = data.get('ca')
if certs:
certs = json.loads(certs)
install_ca_cert(ca.encode())
_manage_ca_certs(ca, relation_id)
install_certs(ssl_dir, certs, chain, user=user, group=group)
create_ip_cert_links(
ssl_dir,
Expand Down
3 changes: 2 additions & 1 deletion charmhelpers/core/host.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
) # flake8: noqa -- ignore F401 for this import

UPDATEDB_PATH = '/etc/updatedb.conf'
CA_CERT_DIR = '/usr/local/share/ca-certificates'


def service_start(service_name, **kwargs):
Expand Down Expand Up @@ -1082,7 +1083,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 = '/usr/local/share/ca-certificates/{}.crt'.format(name)
cert_file = '{}/{}.crt'.format(CA_CERT_DIR, name)
new_hash = hashlib.md5(ca_cert).hexdigest()
if file_hash(cert_file) == new_hash:
return
Expand Down
48 changes: 46 additions & 2 deletions tests/contrib/openstack/test_cert_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,8 @@ def test_install_certs_ca(self, write_file):
]
write_file.assert_has_calls(expected)

@mock.patch.object(cert_utils, '_manage_ca_certs')
@mock.patch.object(cert_utils, 'remote_service_name')
@mock.patch.object(cert_utils, 'local_unit')
@mock.patch.object(cert_utils, 'create_ip_cert_links')
@mock.patch.object(cert_utils, 'install_certs')
Expand All @@ -251,7 +253,9 @@ def test_install_certs_ca(self, write_file):
@mock.patch.object(cert_utils, 'relation_get')
def test_process_certificates(self, relation_get, mkdir, install_ca_cert,
install_certs, create_ip_cert_links,
local_unit):
local_unit, remote_service_name,
_manage_ca_certs):
remote_service_name.return_value = 'vault'
local_unit.return_value = 'devnull/2'
certs = {
'admin.openstack.local': {
Expand All @@ -274,7 +278,8 @@ def test_process_certificates(self, relation_get, mkdir, install_ca_cert,
'certificates:2',
'vault/0',
custom_hostname_link='funky-name'))
install_ca_cert.assert_called_once_with(b'ROOTCA')
_manage_ca_certs.assert_called_once_with(
'ROOTCA', 'certificates:2')
install_certs.assert_called_once_with(
'/etc/apache2/ssl/myservice',
{'admin.openstack.local': {
Expand All @@ -284,6 +289,45 @@ def test_process_certificates(self, relation_get, mkdir, install_ca_cert,
'/etc/apache2/ssl/myservice',
custom_hostname_link='funky-name')

@mock.patch.object(cert_utils, 'remote_service_name')
@mock.patch.object(cert_utils.os, 'remove')
@mock.patch.object(cert_utils.os.path, 'exists')
@mock.patch.object(cert_utils, 'config')
@mock.patch.object(cert_utils, 'install_ca_cert')
def test__manage_ca_certs(self, install_ca_cert, config, os_exists,
os_remove, remote_service_name):
remote_service_name.return_value = 'vault'
_config = {}
config.side_effect = lambda x: _config.get(x)
os_exists.return_value = False
cert_utils._manage_ca_certs('CA', 'certificates:2')
install_ca_cert.assert_called_once_with(
b'CA',
name='vault_juju_ca_cert')
self.assertFalse(os_remove.called)
# Test old cert removed.
install_ca_cert.reset_mock()
os_exists.reset_mock()
os_exists.return_value = True
cert_utils._manage_ca_certs('CA', 'certificates:2')
install_ca_cert.assert_called_once_with(
b'CA',
name='vault_juju_ca_cert')
os_remove.assert_called_once_with(
'/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt')
# Test cert is installed from config
_config['ssl_ca'] = 'Q0FGUk9NQ09ORklHCg=='
install_ca_cert.reset_mock()
os_remove.reset_mock()
os_exists.reset_mock()
os_exists.return_value = True
cert_utils._manage_ca_certs('CA', 'certificates:2')
expected = [
mock.call(b'CAFROMCONFIG', name='keystone_juju_ca_cert'),
mock.call(b'CA', name='vault_juju_ca_cert')]
install_ca_cert.assert_has_calls(expected)
self.assertFalse(os_remove.called)

@mock.patch.object(cert_utils, 'local_unit')
@mock.patch.object(cert_utils, 'related_units')
@mock.patch.object(cert_utils, 'relation_ids')
Expand Down

0 comments on commit a012fe7

Please sign in to comment.