Charmed-Kubernetes/nrpe/mod/charmhelpers/tests/contrib/openstack/test_cert_utils.py

725 lines
32 KiB
Python

import json
import mock
import unittest
import charmhelpers.contrib.openstack.cert_utils as cert_utils
class CertUtilsTests(unittest.TestCase):
def test_CertRequest(self):
cr = cert_utils.CertRequest()
self.assertEqual(cr.entries, [])
self.assertIsNone(cr.hostname_entry)
@mock.patch.object(cert_utils, 'local_unit', return_value='unit/2')
def test_CertRequest_add_entry(self, local_unit):
cr = cert_utils.CertRequest()
cr.add_entry('admin', 'admin.openstack.local', ['10.10.10.10'])
self.assertEqual(
cr.get_request(),
{'cert_requests':
'{"admin.openstack.local": {"sans": ["10.10.10.10"]}}',
'unit_name': 'unit_2'})
@mock.patch.object(cert_utils, 'local_unit', return_value='unit/2')
@mock.patch.object(cert_utils, 'resolve_network_cidr')
@mock.patch.object(cert_utils, 'get_vip_in_network')
@mock.patch.object(cert_utils, 'get_hostname')
@mock.patch.object(cert_utils, 'local_address')
def test_CertRequest_add_hostname_cn(self, local_address, get_hostname,
get_vip_in_network,
resolve_network_cidr, local_unit):
resolve_network_cidr.side_effect = lambda x: x
get_vip_in_network.return_value = '10.1.2.100'
local_address.return_value = '10.1.2.3'
get_hostname.return_value = 'juju-unit-2'
cr = cert_utils.CertRequest()
cr.add_hostname_cn()
self.assertEqual(
cr.get_request(),
{'cert_requests':
'{"juju-unit-2": {"sans": ["10.1.2.100", "10.1.2.3"]}}',
'unit_name': 'unit_2'})
@mock.patch.object(cert_utils, 'local_unit', return_value='unit/2')
@mock.patch.object(cert_utils, 'resolve_network_cidr')
@mock.patch.object(cert_utils, 'get_vip_in_network')
@mock.patch.object(cert_utils, 'get_hostname')
@mock.patch.object(cert_utils, 'local_address')
def test_CertRequest_add_hostname_cn_ip(self, local_address, get_hostname,
get_vip_in_network,
resolve_network_cidr, local_unit):
resolve_network_cidr.side_effect = lambda x: x
get_vip_in_network.return_value = '10.1.2.100'
local_address.return_value = '10.1.2.3'
get_hostname.return_value = 'juju-unit-2'
cr = cert_utils.CertRequest()
cr.add_hostname_cn()
cr.add_hostname_cn_ip(['10.1.2.4'])
self.assertEqual(
cr.get_request(),
{'cert_requests':
('{"juju-unit-2": {"sans": ["10.1.2.100", "10.1.2.3", '
'"10.1.2.4"]}}'),
'unit_name': 'unit_2'})
@mock.patch.object(cert_utils, 'get_certificate_sans')
@mock.patch.object(cert_utils, 'local_unit', return_value='unit/2')
@mock.patch.object(cert_utils, 'resolve_network_cidr')
@mock.patch.object(cert_utils, 'get_vip_in_network')
@mock.patch.object(cert_utils, 'network_get_primary_address')
@mock.patch.object(cert_utils, 'resolve_address')
@mock.patch.object(cert_utils, 'config')
@mock.patch.object(cert_utils, 'get_hostname')
@mock.patch.object(cert_utils, 'local_address')
def test_get_certificate_request(self, local_address, get_hostname,
config, resolve_address,
network_get_primary_address,
get_vip_in_network, resolve_network_cidr,
local_unit, get_certificate_sans):
local_address.return_value = '10.1.2.3'
get_hostname.return_value = 'juju-unit-2'
_config = {
'os-internal-hostname': 'internal.openstack.local',
'os-admin-hostname': 'admin.openstack.local',
'os-public-hostname': 'public.openstack.local',
}
_resolve_address = {
'int': '10.0.0.2',
'internal': '10.0.0.2',
'admin': '10.10.0.2',
'public': '10.20.0.2',
}
_npa = {
'internal': '10.0.0.3',
'admin': '10.10.0.3',
'public': '10.20.0.3',
}
_vips = {
'10.0.0.0/16': '10.0.0.100',
'10.10.0.0/16': '10.10.0.100',
'10.20.0.0/16': '10.20.0.100',
}
_resolve_nets = {
'10.0.0.3': '10.0.0.0/16',
'10.10.0.3': '10.10.0.0/16',
'10.20.0.3': '10.20.0.0/16',
}
get_certificate_sans.return_value = list(set(
list(_resolve_address.values()) +
list(_npa.values()) +
list(_vips.values())))
expect = {
'admin.openstack.local': {
'sans': ['10.10.0.100', '10.10.0.2', '10.10.0.3']},
'internal.openstack.local': {
'sans': ['10.0.0.100', '10.0.0.2', '10.0.0.3']},
'juju-unit-2': {'sans': ['10.1.2.3']},
'public.openstack.local': {
'sans': ['10.20.0.100', '10.20.0.2', '10.20.0.3']}}
self.maxDiff = None
config.side_effect = lambda x: _config.get(x)
get_vip_in_network.side_effect = lambda x: _vips.get(x)
resolve_network_cidr.side_effect = lambda x: _resolve_nets.get(x)
network_get_primary_address.side_effect = lambda x: _npa.get(x)
resolve_address.side_effect = \
lambda endpoint_type: _resolve_address[endpoint_type]
output = json.loads(
cert_utils.get_certificate_request()['cert_requests'])
self.assertEqual(
output,
expect)
get_certificate_sans.assert_called_once_with(
bindings=['internal', 'admin', 'public'])
@mock.patch.object(cert_utils, 'get_certificate_sans')
@mock.patch.object(cert_utils, 'local_unit', return_value='unit/2')
@mock.patch.object(cert_utils, 'resolve_network_cidr')
@mock.patch.object(cert_utils, 'get_vip_in_network')
@mock.patch.object(cert_utils, 'network_get_primary_address')
@mock.patch.object(cert_utils, 'resolve_address')
@mock.patch.object(cert_utils, 'config')
@mock.patch.object(cert_utils, 'get_hostname')
@mock.patch.object(cert_utils, 'local_address')
def test_get_certificate_request_no_hostnames(
self, local_address, get_hostname, config, resolve_address,
network_get_primary_address, get_vip_in_network,
resolve_network_cidr, local_unit, get_certificate_sans):
local_address.return_value = '10.1.2.3'
get_hostname.return_value = 'juju-unit-2'
_config = {
'os-admin-hostname': 'admin.openstack.local',
'os-public-hostname': 'public.openstack.local',
}
_resolve_address = {
'int': '10.0.0.2',
'internal': '10.0.0.2',
'admin': '10.10.0.2',
'public': '10.20.0.2',
}
_npa = {
'internal': '10.0.0.3',
'admin': '10.10.0.3',
'public': '10.20.0.3',
'mybinding': '10.30.0.3',
}
_vips = {
'10.0.0.0/16': '10.0.0.100',
'10.10.0.0/16': '10.10.0.100',
'10.20.0.0/16': '10.20.0.100',
}
_resolve_nets = {
'10.0.0.3': '10.0.0.0/16',
'10.10.0.3': '10.10.0.0/16',
'10.20.0.3': '10.20.0.0/16',
}
get_certificate_sans.return_value = list(set(
list(_resolve_address.values()) +
list(_npa.values()) +
list(_vips.values())))
expect = {
'admin.openstack.local': {
'sans': ['10.10.0.100', '10.10.0.2', '10.10.0.3']},
'juju-unit-2': {'sans': [
'10.0.0.100', '10.0.0.2', '10.0.0.3', '10.1.2.3', '10.30.0.3']},
'public.openstack.local': {
'sans': ['10.20.0.100', '10.20.0.2', '10.20.0.3']}}
self.maxDiff = None
config.side_effect = lambda x: _config.get(x)
get_vip_in_network.side_effect = lambda x: _vips.get(x)
resolve_network_cidr.side_effect = lambda x: _resolve_nets.get(x)
network_get_primary_address.side_effect = lambda x: _npa.get(x)
resolve_address.side_effect = \
lambda endpoint_type: _resolve_address[endpoint_type]
output = json.loads(
cert_utils.get_certificate_request(
bindings=['mybinding'])['cert_requests'])
self.assertEqual(
output,
expect)
get_certificate_sans.assert_called_once_with(
bindings=['mybinding', 'internal', 'admin', 'public'])
@mock.patch.object(cert_utils, 'get_certificate_request')
@mock.patch.object(cert_utils, 'local_address')
@mock.patch.object(cert_utils.os, 'symlink')
@mock.patch.object(cert_utils.os.path, 'isfile')
@mock.patch.object(cert_utils, 'get_hostname')
def test_create_ip_cert_links(self, get_hostname, isfile,
symlink, local_address, get_cert_request):
cert_request = {'cert_requests': {
'admin.openstack.local': {
'sans': ['10.10.0.100', '10.10.0.2', '10.10.0.3']},
'internal.openstack.local': {
'sans': ['10.0.0.100', '10.0.0.2', '10.0.0.3']},
'juju-unit-2': {'sans': ['10.1.2.3']},
'public.openstack.local': {
'sans': ['10.20.0.100', '10.20.0.2', '10.20.0.3']}}}
get_cert_request.return_value = cert_request
_files = {
'/etc/ssl/cert_juju-unit-2': True,
'/etc/ssl/cert_10.1.2.3': False,
'/etc/ssl/cert_admin.openstack.local': True,
'/etc/ssl/cert_10.10.0.100': False,
'/etc/ssl/cert_10.10.0.2': False,
'/etc/ssl/cert_10.10.0.3': False,
'/etc/ssl/cert_internal.openstack.local': True,
'/etc/ssl/cert_10.0.0.100': False,
'/etc/ssl/cert_10.0.0.2': False,
'/etc/ssl/cert_10.0.0.3': False,
'/etc/ssl/cert_public.openstack.local': True,
'/etc/ssl/cert_10.20.0.100': False,
'/etc/ssl/cert_10.20.0.2': False,
'/etc/ssl/cert_10.20.0.3': False,
'/etc/ssl/cert_funky-name': False,
}
isfile.side_effect = lambda x: _files[x]
expected = [
mock.call('/etc/ssl/cert_admin.openstack.local', '/etc/ssl/cert_10.10.0.100'),
mock.call('/etc/ssl/key_admin.openstack.local', '/etc/ssl/key_10.10.0.100'),
mock.call('/etc/ssl/cert_admin.openstack.local', '/etc/ssl/cert_10.10.0.2'),
mock.call('/etc/ssl/key_admin.openstack.local', '/etc/ssl/key_10.10.0.2'),
mock.call('/etc/ssl/cert_admin.openstack.local', '/etc/ssl/cert_10.10.0.3'),
mock.call('/etc/ssl/key_admin.openstack.local', '/etc/ssl/key_10.10.0.3'),
mock.call('/etc/ssl/cert_internal.openstack.local', '/etc/ssl/cert_10.0.0.100'),
mock.call('/etc/ssl/key_internal.openstack.local', '/etc/ssl/key_10.0.0.100'),
mock.call('/etc/ssl/cert_internal.openstack.local', '/etc/ssl/cert_10.0.0.2'),
mock.call('/etc/ssl/key_internal.openstack.local', '/etc/ssl/key_10.0.0.2'),
mock.call('/etc/ssl/cert_internal.openstack.local', '/etc/ssl/cert_10.0.0.3'),
mock.call('/etc/ssl/key_internal.openstack.local', '/etc/ssl/key_10.0.0.3'),
mock.call('/etc/ssl/cert_juju-unit-2', '/etc/ssl/cert_10.1.2.3'),
mock.call('/etc/ssl/key_juju-unit-2', '/etc/ssl/key_10.1.2.3'),
mock.call('/etc/ssl/cert_public.openstack.local', '/etc/ssl/cert_10.20.0.100'),
mock.call('/etc/ssl/key_public.openstack.local', '/etc/ssl/key_10.20.0.100'),
mock.call('/etc/ssl/cert_public.openstack.local', '/etc/ssl/cert_10.20.0.2'),
mock.call('/etc/ssl/key_public.openstack.local', '/etc/ssl/key_10.20.0.2'),
mock.call('/etc/ssl/cert_public.openstack.local', '/etc/ssl/cert_10.20.0.3'),
mock.call('/etc/ssl/key_public.openstack.local', '/etc/ssl/key_10.20.0.3')]
cert_utils.create_ip_cert_links('/etc/ssl')
symlink.assert_has_calls(expected, any_order=True)
# Customer hostname
symlink.reset_mock()
get_hostname.return_value = 'juju-unit-2'
cert_utils.create_ip_cert_links(
'/etc/ssl',
custom_hostname_link='funky-name')
expected.extend([
mock.call('/etc/ssl/cert_juju-unit-2', '/etc/ssl/cert_funky-name'),
mock.call('/etc/ssl/key_juju-unit-2', '/etc/ssl/key_funky-name'),
])
symlink.assert_has_calls(expected, any_order=True)
get_cert_request.assert_called_with(
json_encode=False, bindings=['internal', 'admin', 'public'])
@mock.patch.object(cert_utils, 'get_certificate_request')
@mock.patch.object(cert_utils, 'local_address')
@mock.patch.object(cert_utils.os, 'symlink')
@mock.patch.object(cert_utils.os.path, 'isfile')
@mock.patch.object(cert_utils, 'get_hostname')
def test_create_ip_cert_links_bindings(
self, get_hostname, isfile, symlink, local_address, get_cert_request):
cert_request = {'cert_requests': {
'admin.openstack.local': {
'sans': ['10.10.0.100', '10.10.0.2', '10.10.0.3']},
'internal.openstack.local': {
'sans': ['10.0.0.100', '10.0.0.2', '10.0.0.3']},
'juju-unit-2': {'sans': ['10.1.2.3']},
'public.openstack.local': {
'sans': ['10.20.0.100', '10.20.0.2', '10.20.0.3']}}}
get_cert_request.return_value = cert_request
_files = {
'/etc/ssl/cert_juju-unit-2': True,
'/etc/ssl/cert_10.1.2.3': False,
'/etc/ssl/cert_admin.openstack.local': True,
'/etc/ssl/cert_10.10.0.100': False,
'/etc/ssl/cert_10.10.0.2': False,
'/etc/ssl/cert_10.10.0.3': False,
'/etc/ssl/cert_internal.openstack.local': True,
'/etc/ssl/cert_10.0.0.100': False,
'/etc/ssl/cert_10.0.0.2': False,
'/etc/ssl/cert_10.0.0.3': False,
'/etc/ssl/cert_public.openstack.local': True,
'/etc/ssl/cert_10.20.0.100': False,
'/etc/ssl/cert_10.20.0.2': False,
'/etc/ssl/cert_10.20.0.3': False,
'/etc/ssl/cert_funky-name': False,
}
isfile.side_effect = lambda x: _files[x]
expected = [
mock.call('/etc/ssl/cert_admin.openstack.local', '/etc/ssl/cert_10.10.0.100'),
mock.call('/etc/ssl/key_admin.openstack.local', '/etc/ssl/key_10.10.0.100'),
mock.call('/etc/ssl/cert_admin.openstack.local', '/etc/ssl/cert_10.10.0.2'),
mock.call('/etc/ssl/key_admin.openstack.local', '/etc/ssl/key_10.10.0.2'),
mock.call('/etc/ssl/cert_admin.openstack.local', '/etc/ssl/cert_10.10.0.3'),
mock.call('/etc/ssl/key_admin.openstack.local', '/etc/ssl/key_10.10.0.3'),
mock.call('/etc/ssl/cert_internal.openstack.local', '/etc/ssl/cert_10.0.0.100'),
mock.call('/etc/ssl/key_internal.openstack.local', '/etc/ssl/key_10.0.0.100'),
mock.call('/etc/ssl/cert_internal.openstack.local', '/etc/ssl/cert_10.0.0.2'),
mock.call('/etc/ssl/key_internal.openstack.local', '/etc/ssl/key_10.0.0.2'),
mock.call('/etc/ssl/cert_internal.openstack.local', '/etc/ssl/cert_10.0.0.3'),
mock.call('/etc/ssl/key_internal.openstack.local', '/etc/ssl/key_10.0.0.3'),
mock.call('/etc/ssl/cert_juju-unit-2', '/etc/ssl/cert_10.1.2.3'),
mock.call('/etc/ssl/key_juju-unit-2', '/etc/ssl/key_10.1.2.3'),
mock.call('/etc/ssl/cert_public.openstack.local', '/etc/ssl/cert_10.20.0.100'),
mock.call('/etc/ssl/key_public.openstack.local', '/etc/ssl/key_10.20.0.100'),
mock.call('/etc/ssl/cert_public.openstack.local', '/etc/ssl/cert_10.20.0.2'),
mock.call('/etc/ssl/key_public.openstack.local', '/etc/ssl/key_10.20.0.2'),
mock.call('/etc/ssl/cert_public.openstack.local', '/etc/ssl/cert_10.20.0.3'),
mock.call('/etc/ssl/key_public.openstack.local', '/etc/ssl/key_10.20.0.3')]
cert_utils.create_ip_cert_links('/etc/ssl', bindings=['mybindings'])
symlink.assert_has_calls(expected, any_order=True)
# Customer hostname
symlink.reset_mock()
get_hostname.return_value = 'juju-unit-2'
cert_utils.create_ip_cert_links(
'/etc/ssl',
custom_hostname_link='funky-name', bindings=['mybinding'])
expected.extend([
mock.call('/etc/ssl/cert_juju-unit-2', '/etc/ssl/cert_funky-name'),
mock.call('/etc/ssl/key_juju-unit-2', '/etc/ssl/key_funky-name'),
])
symlink.assert_has_calls(expected, any_order=True)
get_cert_request.assert_called_with(
json_encode=False, bindings=['mybinding', 'internal', 'admin', 'public'])
@mock.patch.object(cert_utils, 'write_file')
def test_install_certs(self, write_file):
certs = {
'admin.openstack.local': {
'cert': 'ADMINCERT',
'key': 'ADMINKEY'}}
cert_utils.install_certs('/etc/ssl', certs, chain='CHAIN')
expected = [
mock.call(
path='/etc/ssl/cert_admin.openstack.local',
content='ADMINCERT\nCHAIN',
owner='root', group='root',
perms=0o640),
mock.call(
path='/etc/ssl/key_admin.openstack.local',
content='ADMINKEY',
owner='root', group='root',
perms=0o640),
]
write_file.assert_has_calls(expected)
@mock.patch.object(cert_utils, 'write_file')
def test_install_certs_ca(self, write_file):
certs = {
'admin.openstack.local': {
'cert': 'ADMINCERT',
'key': 'ADMINKEY'}}
ca = 'MYCA'
cert_utils.install_certs('/etc/ssl', certs, ca)
expected = [
mock.call(
path='/etc/ssl/cert_admin.openstack.local',
content='ADMINCERT\nMYCA',
owner='root', group='root',
perms=0o640),
mock.call(
path='/etc/ssl/key_admin.openstack.local',
content='ADMINKEY',
owner='root', group='root',
perms=0o640),
]
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')
@mock.patch.object(cert_utils, 'install_ca_cert')
@mock.patch.object(cert_utils, 'mkdir')
@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, remote_service_name,
_manage_ca_certs):
remote_service_name.return_value = 'vault'
local_unit.return_value = 'devnull/2'
certs = {
'admin.openstack.local': {
'cert': 'ADMINCERT',
'key': 'ADMINKEY'}}
_relation_info = {
'keystone_2.processed_requests': json.dumps(certs),
'chain': 'MYCHAIN',
'ca': 'ROOTCA',
}
relation_get.return_value = _relation_info
self.assertFalse(cert_utils.process_certificates(
'myservice',
'certificates:2',
'vault/0',
custom_hostname_link='funky-name'))
local_unit.return_value = 'keystone/2'
self.assertTrue(cert_utils.process_certificates(
'myservice',
'certificates:2',
'vault/0',
custom_hostname_link='funky-name'))
_manage_ca_certs.assert_called_once_with(
'ROOTCA', 'certificates:2')
install_certs.assert_called_once_with(
'/etc/apache2/ssl/myservice',
{'admin.openstack.local': {
'key': 'ADMINKEY', 'cert': 'ADMINCERT'}},
'MYCHAIN', user='root', group='root')
create_ip_cert_links.assert_called_once_with(
'/etc/apache2/ssl/myservice',
custom_hostname_link='funky-name',
bindings=['internal', 'admin', 'public'])
@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')
@mock.patch.object(cert_utils, 'install_ca_cert')
@mock.patch.object(cert_utils, 'mkdir')
@mock.patch.object(cert_utils, 'relation_get')
def test_process_certificates_bindings(
self, relation_get, mkdir, install_ca_cert,
install_certs, create_ip_cert_links,
local_unit, remote_service_name, _manage_ca_certs):
remote_service_name.return_value = 'vault'
local_unit.return_value = 'devnull/2'
certs = {
'admin.openstack.local': {
'cert': 'ADMINCERT',
'key': 'ADMINKEY'}}
_relation_info = {
'keystone_2.processed_requests': json.dumps(certs),
'chain': 'MYCHAIN',
'ca': 'ROOTCA',
}
relation_get.return_value = _relation_info
self.assertFalse(cert_utils.process_certificates(
'myservice',
'certificates:2',
'vault/0',
custom_hostname_link='funky-name'))
local_unit.return_value = 'keystone/2'
self.assertTrue(cert_utils.process_certificates(
'myservice',
'certificates:2',
'vault/0',
custom_hostname_link='funky-name',
bindings=['mybinding']))
_manage_ca_certs.assert_called_once_with(
'ROOTCA', 'certificates:2')
install_certs.assert_called_once_with(
'/etc/apache2/ssl/myservice',
{'admin.openstack.local': {
'key': 'ADMINKEY', 'cert': 'ADMINCERT'}},
'MYCHAIN', user='root', group='root')
create_ip_cert_links.assert_called_once_with(
'/etc/apache2/ssl/myservice',
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')
@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')
@mock.patch.object(cert_utils, 'relation_get')
def test_get_requests_for_local_unit(self, relation_get, relation_ids,
related_units, local_unit):
local_unit.return_value = 'rabbitmq-server/2'
relation_ids.return_value = ['certificates:12']
related_units.return_value = ['vault/0']
certs = {
'juju-cd4bb3-5.lxd': {
'cert': 'BASECERT',
'key': 'BASEKEY'},
'juju-cd4bb3-5.internal': {
'cert': 'INTERNALCERT',
'key': 'INTERNALKEY'}}
_relation_info = {
'rabbitmq-server_2.processed_requests': json.dumps(certs),
'chain': 'MYCHAIN',
'ca': 'ROOTCA',
}
relation_get.return_value = _relation_info
self.assertEqual(
cert_utils.get_requests_for_local_unit(),
[{
'ca': 'ROOTCA',
'certs': {
'juju-cd4bb3-5.lxd': {
'cert': 'BASECERT',
'key': 'BASEKEY'},
'juju-cd4bb3-5.internal': {
'cert': 'INTERNALCERT',
'key': 'INTERNALKEY'}},
'chain': 'MYCHAIN'}]
)
@mock.patch.object(cert_utils, 'get_requests_for_local_unit')
def test_get_bundle_for_cn(self, get_requests_for_local_unit):
get_requests_for_local_unit.return_value = [{
'ca': 'ROOTCA',
'certs': {
'juju-cd4bb3-5.lxd': {
'cert': 'BASECERT',
'key': 'BASEKEY'},
'juju-cd4bb3-5.internal': {
'cert': 'INTERNALCERT',
'key': 'INTERNALKEY'}},
'chain': 'MYCHAIN'}]
self.assertEqual(
cert_utils.get_bundle_for_cn('juju-cd4bb3-5.internal'),
{
'ca': 'ROOTCA',
'cert': 'INTERNALCERT',
'chain': 'MYCHAIN',
'key': 'INTERNALKEY'})
@mock.patch.object(cert_utils, 'local_unit', return_value='unit/2')
@mock.patch.object(cert_utils, 'resolve_network_cidr')
@mock.patch.object(cert_utils, 'get_vip_in_network')
@mock.patch.object(cert_utils, 'get_relation_ip')
@mock.patch.object(cert_utils, 'resolve_address')
@mock.patch.object(cert_utils, 'config')
@mock.patch.object(cert_utils, 'get_hostname')
@mock.patch.object(cert_utils, 'local_address')
def test_get_certificate_sans(self, local_address, get_hostname,
config, resolve_address,
get_relation_ip,
get_vip_in_network, resolve_network_cidr,
local_unit):
local_address.return_value = '10.1.2.3'
get_hostname.return_value = 'juju-unit-2'
_config = {
'os-internal-hostname': 'internal.openstack.local',
'os-admin-hostname': 'admin.openstack.local',
'os-public-hostname': 'public.openstack.local',
}
_resolve_address = {
'int': '10.0.0.2',
'internal': '10.0.0.2',
'admin': '10.10.0.2',
'public': '10.20.0.2',
}
_npa = {
'internal': '10.0.0.3',
'admin': '10.10.0.3',
'public': '10.20.0.3',
}
_vips = {
'10.0.0.0/16': '10.0.0.100',
'10.10.0.0/16': '10.10.0.100',
'10.20.0.0/16': '10.20.0.100',
}
_resolve_nets = {
'10.0.0.3': '10.0.0.0/16',
'10.10.0.3': '10.10.0.0/16',
'10.20.0.3': '10.20.0.0/16',
}
expect = list(set([
'10.10.0.100', '10.10.0.2', '10.10.0.3',
'10.0.0.100', '10.0.0.2', '10.0.0.3',
'10.1.2.3',
'10.20.0.100', '10.20.0.2', '10.20.0.3']))
self.maxDiff = None
config.side_effect = lambda x: _config.get(x)
get_vip_in_network.side_effect = lambda x: _vips.get(x)
resolve_network_cidr.side_effect = lambda x: _resolve_nets.get(x)
get_relation_ip.side_effect = lambda x, cidr_network: _npa.get(x)
resolve_address.side_effect = \
lambda endpoint_type: _resolve_address[endpoint_type]
expected_get_relation_ip_calls = [
mock.call('internal', cidr_network=None),
mock.call('admin', cidr_network=None),
mock.call('public', cidr_network=None)]
self.assertEqual(cert_utils.get_certificate_sans().sort(),
expect.sort())
get_relation_ip.assert_has_calls(
expected_get_relation_ip_calls, any_order=True)
@mock.patch.object(cert_utils, 'local_unit', return_value='unit/2')
@mock.patch.object(cert_utils, 'resolve_network_cidr')
@mock.patch.object(cert_utils, 'get_vip_in_network')
@mock.patch.object(cert_utils, 'get_relation_ip')
@mock.patch.object(cert_utils, 'resolve_address')
@mock.patch.object(cert_utils, 'config')
@mock.patch.object(cert_utils, 'get_hostname')
@mock.patch.object(cert_utils, 'local_address')
def test_get_certificate_sans_bindings(
self, local_address, get_hostname, config, resolve_address,
get_relation_ip, get_vip_in_network, resolve_network_cidr, local_unit):
local_address.return_value = '10.1.2.3'
get_hostname.return_value = 'juju-unit-2'
_config = {
'os-internal-hostname': 'internal.openstack.local',
'os-admin-hostname': 'admin.openstack.local',
'os-public-hostname': 'public.openstack.local',
}
_resolve_address = {
'int': '10.0.0.2',
'internal': '10.0.0.2',
'admin': '10.10.0.2',
'public': '10.20.0.2',
}
_npa = {
'internal': '10.0.0.3',
'admin': '10.10.0.3',
'public': '10.20.0.3',
}
_vips = {
'10.0.0.0/16': '10.0.0.100',
'10.10.0.0/16': '10.10.0.100',
'10.20.0.0/16': '10.20.0.100',
}
_resolve_nets = {
'10.0.0.3': '10.0.0.0/16',
'10.10.0.3': '10.10.0.0/16',
'10.20.0.3': '10.20.0.0/16',
}
expect = list(set([
'10.10.0.100', '10.10.0.2', '10.10.0.3',
'10.0.0.100', '10.0.0.2', '10.0.0.3',
'10.1.2.3',
'10.20.0.100', '10.20.0.2', '10.20.0.3']))
self.maxDiff = None
config.side_effect = lambda x: _config.get(x)
get_vip_in_network.side_effect = lambda x: _vips.get(x)
resolve_network_cidr.side_effect = lambda x: _resolve_nets.get(x)
get_relation_ip.side_effect = lambda x, cidr_network: _npa.get(x)
resolve_address.side_effect = \
lambda endpoint_type: _resolve_address[endpoint_type]
expected_get_relation_ip_calls = [
mock.call('internal', cidr_network=None),
mock.call('admin', cidr_network=None),
mock.call('public', cidr_network=None),
mock.call('mybinding', cidr_network=None)]
self.assertEqual(
cert_utils.get_certificate_sans(bindings=['mybinding']).sort(),
expect.sort())
get_relation_ip.assert_has_calls(
expected_get_relation_ip_calls, any_order=True)