From fbda4766316c670dcd6de564e291aabab990e530 Mon Sep 17 00:00:00 2001 From: Marcelo Loebens Date: Mon, 6 Nov 2023 10:32:50 -0400 Subject: [PATCH] Send system-local-ca secret ca.crt (DX sc upgrade) The sysinv API call for certificate installation with type openldap_ca will extract ca data included in the certificate bundle and include it in the 'system-local-ca' ca.crt field. Modified dcmanager to perform the call using this structure, passing a bundle with TLS cert + CA cert + TLS key from the 'system-local-ca' in the SystemController. This code is called during DX subcloud upgrade and is used to keep the current 'system-local-ca' on the subcloud consistent with the one in the SystemController. Test plan: PASS: In a DC w/ DX subcloud in stx 9: - Perform cert-manager migration. - Upgrade the SystemController. - Verify system-local-ca secret content in the SystemController and the subcloud. - Start orchestrated upgraded for th DX subcloud. - Verify dcmanager/state.log. After the step "Stage: 2, State: transferring CA certificate" verify the system-local-ca secret content in the subcloud. The secret should have been replaced to match the one in the SystemController. Story: 2009811 Task: 49044 Change-Id: I42e6308f066126f903738f4e3c319c6027c8cb0b Signed-off-by: Marcelo Loebens --- distributedcloud/dcmanager/common/utils.py | 9 ++++++++- .../states/upgrade/transfer_ca_certificate.py | 9 +++++---- .../states/upgrade/test_transferring_ca_certificate.py | 8 ++++---- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/distributedcloud/dcmanager/common/utils.py b/distributedcloud/dcmanager/common/utils.py index 1c681ceea..9f9afba54 100644 --- a/distributedcloud/dcmanager/common/utils.py +++ b/distributedcloud/dcmanager/common/utils.py @@ -1076,6 +1076,7 @@ def get_certificate_from_secret(secret_name, secret_ns): :return: tls_crt: the certificate. tls_key: the corresponding private key of the certificate. + ca_crt: the CA certificate that issued tls_crt if available. raise Exception for kubernetes data errors """ @@ -1093,11 +1094,17 @@ def get_certificate_from_secret(secret_name, secret_ns): try: tls_crt = base64.decode_as_text(data['tls.crt']) tls_key = base64.decode_as_text(data['tls.key']) + if 'ca.crt' in data: + ca_crt = base64.decode_as_text(data['ca.crt']) + else: + LOG.warning("Secret does't have required CA data stored: %s\\%s" % + (secret_ns, secret_name)) + ca_crt = '' except TypeError: raise Exception('Certificate secret data is invalid %s\\%s' % (secret_ns, secret_name)) - return tls_crt, tls_key + return tls_crt, tls_key, ca_crt def get_management_subnet(payload): diff --git a/distributedcloud/dcmanager/orchestrator/states/upgrade/transfer_ca_certificate.py b/distributedcloud/dcmanager/orchestrator/states/upgrade/transfer_ca_certificate.py index e92202ae8..c1c4e6048 100644 --- a/distributedcloud/dcmanager/orchestrator/states/upgrade/transfer_ca_certificate.py +++ b/distributedcloud/dcmanager/orchestrator/states/upgrade/transfer_ca_certificate.py @@ -53,12 +53,13 @@ class TransferCACertificateState(BaseState): self.get_sysinv_client(strategy_step.subcloud.region_name) data = {'mode': 'openldap_ca'} - ldap_ca_cert, ldap_ca_key = utils.get_certificate_from_secret( - consts.OPENLDAP_CA_CERT_SECRET_NAME, - consts.CERT_NAMESPACE_PLATFORM_CA_CERTS) + ldap_ca_cert, ldap_ca_key, rca_crt = \ + utils.get_certificate_from_secret( + consts.OPENLDAP_CA_CERT_SECRET_NAME, + consts.CERT_NAMESPACE_PLATFORM_CA_CERTS) sysinv_client.update_certificate( - '', ldap_ca_cert + ldap_ca_key, data) + '', ldap_ca_cert + rca_crt + ldap_ca_key, data) break except Exception as e: self.warn_log(strategy_step, diff --git a/distributedcloud/dcmanager/tests/unit/orchestrator/states/upgrade/test_transferring_ca_certificate.py b/distributedcloud/dcmanager/tests/unit/orchestrator/states/upgrade/test_transferring_ca_certificate.py index f25ea4d42..1aabac8f7 100644 --- a/distributedcloud/dcmanager/tests/unit/orchestrator/states/upgrade/test_transferring_ca_certificate.py +++ b/distributedcloud/dcmanager/tests/unit/orchestrator/states/upgrade/test_transferring_ca_certificate.py @@ -83,7 +83,7 @@ class TestSwUpgradeDuplexTransferringCACertificateStage(TestSwUpgradeState): # simulate get_certificate_from_secret finding the openldap ca certificate p = mock.patch('dcmanager.common.utils.get_certificate_from_secret') self.mock_cert_file = p.start() - self.mock_cert_file.return_value = (FAKE_CERT, FAKE_KEY) + self.mock_cert_file.return_value = (FAKE_CERT, FAKE_KEY, FAKE_CERT) self.addCleanup(p.stop) # invoke the strategy state operation on the orch thread @@ -91,7 +91,7 @@ class TestSwUpgradeDuplexTransferringCACertificateStage(TestSwUpgradeState): # verify update_certificate was invoked self.sysinv_client.update_certificate.assert_called_with( - '', FAKE_CERT + FAKE_KEY, {'mode': 'openldap_ca'}) + '', FAKE_CERT + FAKE_CERT + FAKE_KEY, {'mode': 'openldap_ca'}) # On success, the state should transition to the next state self.assert_step_updated(self.strategy_step.subcloud_id, @@ -125,7 +125,7 @@ class TestSwUpgradeDuplexTransferringCACertificateStage(TestSwUpgradeState): # simulate get_certificate_from_secret finding the openldap ca certificate p = mock.patch('dcmanager.common.utils.get_certificate_from_secret') self.mock_cert_file = p.start() - self.mock_cert_file.return_value = (FAKE_CERT, FAKE_KEY) + self.mock_cert_file.return_value = (FAKE_CERT, FAKE_KEY, FAKE_CERT) self.addCleanup(p.stop) # simulate update_certificate failing to update @@ -137,7 +137,7 @@ class TestSwUpgradeDuplexTransferringCACertificateStage(TestSwUpgradeState): # verify update_certificate was invoked self.sysinv_client.update_certificate.assert_called_with( - '', FAKE_CERT + FAKE_KEY, {'mode': 'openldap_ca'}) + '', FAKE_CERT + FAKE_CERT + FAKE_KEY, {'mode': 'openldap_ca'}) # verify the update_certificate was invoked: 1 + max_retries times self.assertEqual(transfer_ca_certificate.DEFAULT_MAX_RETRIES + 1,