Fix CA certificate on cloud-compute relation

Note that part of this fix belongs in c-h, but let's add it here
as a tactical measure given we are practically frozen.

Enable TLS in the functional test for focal-ussuri and onwards.

Also switch to focal-ussuri as target for smoke.

Drop Trusty/Mitaka as it currently does not pass with symptoms
like https://bugs.launchpad.net/charm-nova-compute/+bug/1861094

Closes-Bug: #1911902
Change-Id: I7b12479ce3afb94a0fb21c26b1ac78736b81aba2
This commit is contained in:
Frode Nordahl 2021-01-15 15:04:37 +01:00
parent a29e54b99f
commit 93efd6e81d
No known key found for this signature in database
GPG Key ID: 6A5D59A3BA48373F
9 changed files with 178 additions and 125 deletions

View File

@ -578,9 +578,9 @@ def keystone_compute_settings():
if ks_auth_config:
rel_settings.update(ks_auth_config)
rel_settings.update(neutron_settings())
ks_ca = ncc_utils.keystone_ca_cert_b64()
if ks_auth_config and ks_ca:
rel_settings['ca_cert'] = ks_ca
ca = ncc_utils.get_ca_cert_b64()
if ca:
rel_settings['ca_cert'] = ca
return rel_settings
@ -984,10 +984,10 @@ def quantum_joined(rid=None, remote_restart=False):
ks_auth_config = _auth_config()
rel_settings.update(ks_auth_config)
# must pass the keystone CA cert, if it exists.
ks_ca = ncc_utils.keystone_ca_cert_b64()
if ks_auth_config and ks_ca:
rel_settings['ca_cert'] = ks_ca
# pass CA cert, if one exists.
ca = ncc_utils.get_ca_cert_b64()
if ca:
rel_settings['ca_cert'] = ca
# update relation setting if we're attempting to restart remote
# services

View File

@ -21,6 +21,7 @@ import subprocess
from urllib.parse import urlparse
import uuid
import charmhelpers.contrib.hahelpers.apache as ch_apache
import charmhelpers.contrib.hahelpers.cluster as ch_cluster
import charmhelpers.contrib.network.ip as ch_ip
import charmhelpers.contrib.openstack.context as ch_context
@ -228,8 +229,6 @@ def get_base_resource_map():
return _BASE_RESOURCE_MAP
CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt'
NOVA_SSH_DIR = '/etc/nova/compute_ssh/'
SERIAL_CONSOLE = {
@ -1036,12 +1035,44 @@ def auth_token_config(setting):
return value
def keystone_ca_cert_b64():
'''Returns the local Keystone-provided CA cert if it exists, or None.'''
if not os.path.isfile(CA_CERT_PATH):
return None
with open(CA_CERT_PATH, 'rb') as _in:
return base64.b64encode(_in.read()).decode('utf-8')
def get_cert_relation_ca_filename():
"""Determine absolute path to CA certificate file as provided by relation.
The filename on disk depends on the name chosen for the application on the
providing end of the certificates relation.
:type cert_relation_id: str
:returns: Absolute path to CA certificate file
:rtype: str
"""
# NOTE(fnordahl): this function belongs together with the c-h cert_utils
# module, however given we at the time of this writing are frozen I'll add
# it here as a tactical measure.
# TODO: move to c-h.contrib.openstack.cert_utils
for cert_relation_id in hookenv.relation_ids('certificates'):
return os.path.join(
ch_host.CA_CERT_DIR,
'{}_juju_ca_cert.crt'
.format(hookenv.remote_service_name(relid=cert_relation_id)))
return ''
def get_ca_cert_b64():
"""Retrieve CA-cert as provided by certificates relation or config.
:returns: Base64 encoded CA-certificate data
:rtype: str
"""
ca_cert_file = (get_cert_relation_ca_filename() or
ch_apache.CONFIG_CA_CERT_FILE)
try:
with open(ca_cert_file, 'rb') as _in:
return base64.b64encode(_in.read()).decode('utf-8')
except OSError as e:
hookenv.log('CA Certificate not found at expected location '
'("{}"): "{}"'
.format(ca_cert_file, str(e)))
return ''
def _ssh_directory_for_remote_service(remote_service, user=None):

View File

@ -25,6 +25,7 @@ machines:
constraints: mem=4096M cores=4
'11':
constraints: mem=4096M cores=4
'12':
applications:
@ -38,6 +39,8 @@ applications:
charm: cs:~openstack-charmers-next/mysql-router
placement-mysql-router:
charm: cs:~openstack-charmers-next/mysql-router
vault-mysql-router:
charm: cs:~openstack-charmers-next/mysql-router
mysql-innodb-cluster:
charm: cs:~openstack-charmers-next/mysql-innodb-cluster
@ -133,6 +136,12 @@ applications:
- '10'
- '11'
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
to:
- '12'
relations:
- - 'nova-compute:image-service'
@ -210,3 +219,23 @@ relations:
- - 'placement:placement'
- 'nova-cloud-controller:placement'
- - 'vault:shared-db'
- 'vault-mysql-router:shared-db'
- - 'vault-mysql-router:db-router'
- 'mysql-innodb-cluster:db-router'
- - 'vault:certificates'
- 'neutron-api:certificates'
- - 'vault:certificates'
- 'glance:certificates'
- - 'vault:certificates'
- 'keystone:certificates'
- - 'vault:certificates'
- 'nova-cloud-controller:certificates'
- - 'vault:certificates'
- 'placement:certificates'

View File

@ -25,6 +25,7 @@ machines:
constraints: mem=4096M cores=4
'11':
constraints: mem=4096M cores=4
'12':
applications:
@ -38,6 +39,8 @@ applications:
charm: cs:~openstack-charmers-next/mysql-router
placement-mysql-router:
charm: cs:~openstack-charmers-next/mysql-router
vault-mysql-router:
charm: cs:~openstack-charmers-next/mysql-router
mysql-innodb-cluster:
charm: cs:~openstack-charmers-next/mysql-innodb-cluster
@ -133,6 +136,12 @@ applications:
- '10'
- '11'
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
to:
- '12'
relations:
- - 'nova-compute:image-service'
@ -210,3 +219,23 @@ relations:
- - 'placement:placement'
- 'nova-cloud-controller:placement'
- - 'vault:shared-db'
- 'vault-mysql-router:shared-db'
- - 'vault-mysql-router:db-router'
- 'mysql-innodb-cluster:db-router'
- - 'vault:certificates'
- 'neutron-api:certificates'
- - 'vault:certificates'
- 'glance:certificates'
- - 'vault:certificates'
- 'keystone:certificates'
- - 'vault:certificates'
- 'nova-cloud-controller:certificates'
- - 'vault:certificates'
- 'placement:certificates'

View File

@ -25,6 +25,7 @@ machines:
constraints: mem=4096M cores=4
'11':
constraints: mem=4096M cores=4
'12':
applications:
@ -38,6 +39,8 @@ applications:
charm: cs:~openstack-charmers-next/mysql-router
placement-mysql-router:
charm: cs:~openstack-charmers-next/mysql-router
vault-mysql-router:
charm: cs:~openstack-charmers-next/mysql-router
mysql-innodb-cluster:
charm: cs:~openstack-charmers-next/mysql-innodb-cluster
@ -133,6 +136,12 @@ applications:
- '10'
- '11'
vault:
charm: cs:~openstack-charmers-next/vault
num_units: 1
to:
- '12'
relations:
- - 'nova-compute:image-service'
@ -210,3 +219,23 @@ relations:
- - 'placement:placement'
- 'nova-cloud-controller:placement'
- - 'vault:shared-db'
- 'vault-mysql-router:shared-db'
- - 'vault-mysql-router:db-router'
- 'mysql-innodb-cluster:db-router'
- - 'vault:certificates'
- 'neutron-api:certificates'
- - 'vault:certificates'
- 'glance:certificates'
- - 'vault:certificates'
- 'keystone:certificates'
- - 'vault:certificates'
- 'nova-cloud-controller:certificates'
- - 'vault:certificates'
- 'placement:certificates'

View File

@ -1,96 +0,0 @@
series: trusty
relations:
- - nova-compute:image-service
- glance:image-service
- - nova-compute:amqp
- rabbitmq-server:amqp
- - nova-cloud-controller:shared-db
- percona-cluster:shared-db
- - nova-cloud-controller:identity-service
- keystone:identity-service
- - nova-cloud-controller:amqp
- rabbitmq-server:amqp
- - nova-cloud-controller:cloud-compute
- nova-compute:cloud-compute
- - nova-cloud-controller:image-service
- glance:image-service
- - keystone:shared-db
- percona-cluster:shared-db
- - glance:identity-service
- keystone:identity-service
- - glance:shared-db
- percona-cluster:shared-db
- - glance:amqp
- rabbitmq-server:amqp
- - neutron-gateway:amqp
- rabbitmq-server:amqp
- - nova-cloud-controller:quantum-network-service
- neutron-gateway:quantum-network-service
- - neutron-api:shared-db
- percona-cluster:shared-db
- - neutron-api:amqp
- rabbitmq-server:amqp
- - neutron-api:neutron-api
- nova-cloud-controller:neutron-api
- - neutron-api:identity-service
- keystone:identity-service
- - nova-compute:neutron-plugin
- neutron-openvswitch:neutron-plugin
- - rabbitmq-server:amqp
- neutron-openvswitch:amqp
applications:
rabbitmq-server:
charm: cs:~openstack-charmers-next/rabbitmq-server
num_units: 1
percona-cluster:
charm: cs:trusty/percona-cluster
num_units: 1
options:
max-connections: 1000
innodb-buffer-pool-size: 256M
dataset-size: 25%
root-password: ChangeMe123
sst-password: ChangeMe123
nova-cloud-controller:
charm: ../../../nova-cloud-controller
num_units: 1
options:
openstack-origin: cloud:trusty-mitaka
api-rate-limit-rules: "( POST, '*', .*, 9999, MINUTE );"
network-manager: Neutron
debug: true
neutron-api:
charm: cs:~openstack-charmers-next/neutron-api
num_units: 1
options:
openstack-origin: cloud:trusty-mitaka
flat-network-providers: physnet1
neutron-security-groups: true
keystone:
charm: cs:~openstack-charmers-next/keystone
num_units: 1
options:
openstack-origin: cloud:trusty-mitaka
neutron-gateway:
charm: cs:~openstack-charmers-next/neutron-gateway
num_units: 1
options:
openstack-origin: cloud:trusty-mitaka
bridge-mappings: physnet1:br-ex
glance:
charm: cs:~openstack-charmers-next/glance
num_units: 1
options:
openstack-origin: cloud:trusty-mitaka
neutron-openvswitch:
charm: cs:~openstack-charmers-next/neutron-openvswitch
nova-compute:
charm: cs:~openstack-charmers-next/nova-compute
num_units: 2
constraints: mem=4G cores=4
options:
openstack-origin: cloud:trusty-mitaka
config-flags: auto_assign_floating_ip=False
enable-live-migration: false
aa-profile-mode: enforce
debug: true

View File

@ -1,9 +1,9 @@
charm_name: nova-cloud-controller
smoke_bundles:
- bionic-ussuri
- vault: focal-ussuri
gate_bundles:
- focal-victoria
- focal-ussuri
- vault: focal-victoria
- vault: focal-ussuri
- bionic-ussuri
- bionic-train
- bionic-stein
@ -13,19 +13,33 @@ gate_bundles:
- xenial-pike
- xenial-ocata
- xenial-mitaka
- trusty-mitaka
dev_bundles:
- groovy-victoria
- vault: groovy-victoria
target_deploy_status:
vault:
workload-status: blocked
workload-status-message: Vault needs to be initialized
configure:
- zaza.openstack.charm_tests.glance.setup.add_cirros_image
- zaza.openstack.charm_tests.keystone.setup.add_demo_user
- zaza.openstack.charm_tests.neutron.setup.basic_overcloud_network
- zaza.openstack.charm_tests.nova.setup.create_flavors
- zaza.openstack.charm_tests.nova.setup.manage_ssh_key
- vault:
- zaza.openstack.charm_tests.vault.setup.auto_initialize
- zaza.openstack.charm_tests.glance.setup.add_cirros_image
- zaza.openstack.charm_tests.keystone.setup.add_demo_user
- zaza.openstack.charm_tests.neutron.setup.basic_overcloud_network
- zaza.openstack.charm_tests.nova.setup.create_flavors
- zaza.openstack.charm_tests.nova.setup.manage_ssh_key
tests:
- zaza.openstack.charm_tests.nova.tests.CirrosGuestCreateTest
- zaza.openstack.charm_tests.nova.tests.SecurityTests
- zaza.openstack.charm_tests.nova.tests.NovaCloudController
- vault:
- zaza.openstack.charm_tests.nova.tests.CirrosGuestCreateTest
- zaza.openstack.charm_tests.nova.tests.SecurityTests
- zaza.openstack.charm_tests.nova.tests.NovaCloudController
tests_options:
force_deploy:
- groovy-victoria

View File

@ -67,7 +67,7 @@ TO_PATCH = [
'hooks.nova_cc_utils.determine_packages',
'hooks.nova_cc_utils.determine_ports',
'hooks.nova_cc_utils.do_openstack_upgrade',
'hooks.nova_cc_utils.keystone_ca_cert_b64',
'hooks.nova_cc_utils.get_ca_cert_b64',
'hooks.nova_cc_utils.migrate_nova_databases',
'hooks.nova_cc_utils.placement_api_enabled',
'hooks.nova_cc_utils.save_script_rc',
@ -441,6 +441,7 @@ class NovaCCHooksTests(CharmTestCase):
self.assertFalse(
hooks._goal_state_achieved_for_relid('aservice', None))
@patch('charmhelpers.contrib.openstack.utils.get_hostname')
@patch('charmhelpers.core.unitdata.Storage.set')
@patch('hooks.nova_cc_utils.add_authorized_key_if_doesnt_exist')
@patch('hooks.nova_cc_utils.ssh_compute_add_known_hosts')
@ -452,7 +453,9 @@ class NovaCCHooksTests(CharmTestCase):
mock__goal_state_achieved_for_relid,
mock_ssh_compute_add_known_hosts,
mock_add_authorized_key_if_doesnt_exist,
mock_db_set):
mock_db_set,
mock_get_hostname):
mock_get_hostname.return_value = None
mock_remote_service_from_unit.return_value = 'aservice'
mock__goal_state_achieved_for_relid.return_value = True
self.test_relation.set({
@ -489,6 +492,7 @@ class NovaCCHooksTests(CharmTestCase):
mock__goal_state_achieved_for_relid.assert_called_once_with(
'cloud-compute', None)
@patch('charmhelpers.contrib.openstack.utils.get_hostname')
@patch('charmhelpers.core.unitdata.Storage.set')
@patch('hooks.nova_cc_utils.add_authorized_key_if_doesnt_exist')
@patch('hooks.nova_cc_utils.ssh_compute_add_known_hosts')
@ -500,7 +504,9 @@ class NovaCCHooksTests(CharmTestCase):
mock__goal_state_achieved_for_relid,
mock_ssh_compute_add_known_hosts,
mock_add_authorized_key_if_doesnt_exist,
mock_db_set):
mock_db_set,
mock_get_hostname):
mock_get_hostname.return_value = None
mock_remote_service_from_unit.return_value = 'aservice'
mock__goal_state_achieved_for_relid.return_value = True
self.test_relation.set({
@ -594,7 +600,7 @@ class NovaCCHooksTests(CharmTestCase):
self.is_relation_made.return_value = False
self.network_manager.return_value = 'neutron'
self.is_leader = True
self.keystone_ca_cert_b64.return_value = 'foocert64'
self.get_ca_cert_b64.return_value = 'foocert64'
self.unit_get.return_value = 'nova-cc-host1'
self.serial_console_settings.return_value = {
'enable_serial_console': 'false',
@ -633,7 +639,7 @@ class NovaCCHooksTests(CharmTestCase):
self.is_relation_made.return_value = True
self.network_manager.return_value = 'neutron'
self.is_leader = True
self.keystone_ca_cert_b64.return_value = 'foocert64'
self.get_ca_cert_b64.return_value = 'foocert64'
self.unit_get.return_value = 'nova-cc-host1'
self.serial_console_settings.return_value = {
'enable_serial_console': 'false',

View File

@ -717,15 +717,26 @@ class NovaCCUtilsTests(CharmTestCase):
self.assertFalse(rm.called)
_file.write.assert_called_with('|1|= fookey\n')
@patch('os.path.isfile')
def test_keystone_ca_cert_b64(self, isfile):
isfile.return_value = True
@patch.object(utils.hookenv, 'remote_service_name')
def test_get_cert_relation_ca_filename(self, mock_remote_service_name):
mock_remote_service_name.return_value = 'namedvault'
self.relation_ids.return_value = ['aRelation']
self.assertEquals(
utils.get_cert_relation_ca_filename(),
'/usr/local/share/ca-certificates/namedvault_juju_ca_cert.crt')
def test_get_ca_cert_b64(self):
with patch_open() as (_open, _file):
_file.readlines = MagicMock()
_file.write = MagicMock()
_file.read.return_value = b'mycert'
_open.side_effect = OSError
self.assertEqual(
utils.keystone_ca_cert_b64(),
utils.get_ca_cert_b64(),
'')
_open.side_effect = None
self.assertEqual(
utils.get_ca_cert_b64(),
'bXljZXJ0')
@patch.object(utils, 'known_hosts')