From ac2604e9a03b29e6e9487fe89548a902d629d9e6 Mon Sep 17 00:00:00 2001 From: Carmen Rata Date: Thu, 3 Mar 2022 11:16:17 -0500 Subject: [PATCH] OpenLDAP certificate support in sysinv apis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A secure openldap server requires support for openldap certificates. Internal sysinv rest api "cerificate_install" and system certificate management CLIs "certificate-install" and "certificate-list" need to have sysinv cert-mon support for openldap certificate. This commit is the first step in making rest api "certificate-install" and CLI "certificate-list" fully functional. Subsequent "sysinv/conductor/manager.py" support code changes for openldap certificate configuration will complete the sysinv cert-mon implementation as they would need to be accompanied by openldap schema updates for ssl certificate and key, updates done using puppet configuration and part of a follow up commit. New “mode=openldap” was added to internal sysinv rest api "certificate_install" but it's usage is disallowed in the system CLI "certificate-install". The new secure endpoint for openldap/slapd is not yet being used. In future next step, when SSSD (System Security Services Daemon) client is introduced, security will be enhanced with use of LDAPS for openldap/slapd. Tests performed: PASS: Add new mode=openldap to sysinv rest api "certificate_install". Testing verifies the instrumentation of the rest api option "m=openldap" in the sysinv cert-mon code and does not verifies the full functionality of the option that is not enabled yet beyond cert-mon. Testing shows in debug mode that the option is working and cert-mon calls are logged. The option triggers cert-mon apis for openldap as expected. PASS: Disable mode-openldap in the system CLI "certificate-install". PASS: Create new certificate and secret. PASS: List all certificates. This test is to ensure installed certificates are listed and CLI "certificate-list" is not broken. The openldap certificate is expected not to be in the list. PASS: Delete a certificate and secret. Story: 2009834 Task: 44655 Change-Id: I01db5a7ea9848187655174b1b5451f73d9c5c220 Signed-off-by: Carmen Rata --- .../cgtsclient/v1/certificate_shell.py | 3 +++ .../sysinv/api/controllers/v1/certificate.py | 10 ++++---- .../cert_mon/certificate_mon_manager.py | 6 +++++ .../sysinv/sysinv/sysinv/cert_mon/watcher.py | 24 +++++++++++++++++++ .../sysinv/sysinv/sysinv/common/constants.py | 10 +++++--- 5 files changed, 46 insertions(+), 7 deletions(-) diff --git a/sysinv/cgts-client/cgts-client/cgtsclient/v1/certificate_shell.py b/sysinv/cgts-client/cgts-client/cgtsclient/v1/certificate_shell.py index aad105e2bf..7bfa02c8e3 100644 --- a/sysinv/cgts-client/cgts-client/cgtsclient/v1/certificate_shell.py +++ b/sysinv/cgts-client/cgts-client/cgtsclient/v1/certificate_shell.py @@ -81,6 +81,9 @@ def do_certificate_install(cc, args): data = {'passphrase': args.passphrase, 'mode': args.mode} + if data['mode'] == 'openldap': + raise exc.CommandError('Warning: Invalid mode: openldap') + has_private_key = False try: with open(certificate_file, 'r') as reader: diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/certificate.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/certificate.py index ce6461a686..5e5cb3b22b 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/certificate.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/certificate.py @@ -348,11 +348,12 @@ class CertificateController(rest.RestController): continue - # validation checking for ssl, docker_registry - # and openstack certficcates + # validation checking for ssl, docker_registry, openldap + # and openstack certificates if mode in [constants.CERT_MODE_SSL, constants.CERT_MODE_DOCKER_REGISTRY, constants.CERT_MODE_OPENSTACK, + constants.CERT_MODE_OPENLDAP, ]: try: hash_issuers.append(cutils.get_cert_issuer_hash(cert)) @@ -413,11 +414,12 @@ class CertificateController(rest.RestController): # information returned from conductor manager. certificate_dicts = [] for inv_cert in inv_certs: - # for ssl, tmp_mode, docker_registry and openstack certs, if the - # cert is ICA signed cert (ie, the pem_contents contains + # for ssl, tmp_mode, docker_registry, openldap and openstack certs, + # if the cert is ICA signed cert (ie, the pem_contents contains # intermediate CA certs), skip these intermediate CA certs. if mode in [constants.CERT_MODE_SSL, constants.CERT_MODE_DOCKER_REGISTRY, + constants.CERT_MODE_OPENLDAP, constants.CERT_MODE_OPENSTACK] \ and inv_cert.get('is_ca', None): continue diff --git a/sysinv/sysinv/sysinv/sysinv/cert_mon/certificate_mon_manager.py b/sysinv/sysinv/sysinv/sysinv/cert_mon/certificate_mon_manager.py index d968813424..3b501738fd 100644 --- a/sysinv/sysinv/sysinv/sysinv/cert_mon/certificate_mon_manager.py +++ b/sysinv/sysinv/sysinv/sysinv/cert_mon/certificate_mon_manager.py @@ -85,6 +85,7 @@ class CertificateMonManager(periodic_task.PeriodicTasks): self.dc_monitor = None self.restapicert_monitor = None self.registrycert_monitor = None + self.openldapcert_monitor = None self.reattempt_monitor_tasks = [] self.sc_audit_queue = subcloud_audit_queue.SubcloudAuditPriorityQueue() if CONF.certmon.audit_greenpool_size > 0: @@ -344,6 +345,10 @@ class CertificateMonManager(periodic_task.PeriodicTasks): self.registrycert_monitor = watcher.RegistryCert_CertWatcher() self.registrycert_monitor.initialize() + def init_openldapcert_monitor(self): + self.openldapcert_monitor = watcher.OpenldapCert_CertWatcher() + self.openldapcert_monitor.initialize() + def start_monitor(self): utils.init_keystone_auth_opts() dc_role = utils.get_dc_role() @@ -352,6 +357,7 @@ class CertificateMonManager(periodic_task.PeriodicTasks): # init platform cert monitors self.init_restapicert_monitor() self.init_registrycert_monitor() + self.init_openldapcert_monitor() # init dc monitor only if running in DC role if dc_role in (constants.DISTRIBUTED_CLOUD_ROLE_SYSTEMCONTROLLER, diff --git a/sysinv/sysinv/sysinv/sysinv/cert_mon/watcher.py b/sysinv/sysinv/sysinv/sysinv/cert_mon/watcher.py index 288a982735..9d427cbd7a 100644 --- a/sysinv/sysinv/sysinv/sysinv/cert_mon/watcher.py +++ b/sysinv/sysinv/sysinv/sysinv/cert_mon/watcher.py @@ -373,6 +373,20 @@ class RegistryCert_CertWatcher(CertWatcher): self.register_listener(RegistryCertRenew(self.context)) +class OpenldapCert_CertWatcher(CertWatcher): + def __init__(self): + super(OpenldapCert_CertWatcher, self).__init__() + + def initialize(self): + self.context.initialize() + + platcert_ns = constants.CERT_NAMESPACE_PLATFORM_CERTS + LOG.info('setting ns for Openldap cert : %s & registering listener' % platcert_ns) + self.namespace = platcert_ns + self.context.kubernete_namespace = platcert_ns + self.register_listener(OpenldapCertRenew(self.context)) + + class CertificateRenew(CertWatcherListener): def __init__(self, context): super(CertificateRenew, self).__init__(context) @@ -680,3 +694,13 @@ class RegistryCertRenew(PlatformCertRenew): LOG.info('RegistryCertRenew: Secret changes detected. Initiating certificate update') self.update_platform_certificate(event_data, constants.CERT_MODE_DOCKER_REGISTRY, force=True) + + +class OpenldapCertRenew(PlatformCertRenew): + def __init__(self, context): + super(OpenldapCertRenew, self).__init__(context, constants.OPENLDAP_CERT_SECRET_NAME) + + def update_certificate(self, event_data): + LOG.info('OpenldapCertRenew: Secret changes detected. Initiating certificate update') + + self.update_platform_certificate(event_data, constants.CERT_MODE_OPENLDAP, force=True) diff --git a/sysinv/sysinv/sysinv/sysinv/common/constants.py b/sysinv/sysinv/sysinv/sysinv/common/constants.py index 0b32ecf186..9ff4c83102 100644 --- a/sysinv/sysinv/sysinv/sysinv/common/constants.py +++ b/sysinv/sysinv/sysinv/sysinv/common/constants.py @@ -1457,14 +1457,17 @@ CERT_MODE_SSL_CA = 'ssl_ca' CERT_MODE_DOCKER_REGISTRY = 'docker_registry' CERT_MODE_OPENSTACK = 'openstack' CERT_MODE_OPENSTACK_CA = 'openstack_ca' +CERT_MODE_OPENLDAP = 'openldap' CERT_MODES_SUPPORTED = [CERT_MODE_SSL, CERT_MODE_SSL_CA, CERT_MODE_DOCKER_REGISTRY, CERT_MODE_OPENSTACK, CERT_MODE_OPENSTACK_CA, + CERT_MODE_OPENLDAP, ] CERT_MODES_SUPPORTED_CERT_MANAGER = [CERT_MODE_SSL, - CERT_MODE_DOCKER_REGISTRY] + CERT_MODE_DOCKER_REGISTRY, + CERT_MODE_OPENLDAP] KUBERNETES_ROOTCA_FILE = '/etc/kubernetes/pki/ca.crt' ETCD_ROOTCA_FILE = '/etc/etcd/ca.crt' @@ -1969,12 +1972,13 @@ ADMIN_EP_CERT_FORMAT = '{tls_key}' # Platform certificates RESTAPI_CERT_SECRET_NAME = "system-restapi-gui-certificate" REGISTRY_CERT_SECRET_NAME = "system-registry-local-certificate" +OPENLDAP_CERT_SECRET_NAME = "system-openldap-local-certificate" CERT_NAMESPACE_PLATFORM_CERTS = 'deployment' CERT_MODE_TO_SECRET_NAME = { CERT_MODE_SSL: RESTAPI_CERT_SECRET_NAME, - CERT_MODE_DOCKER_REGISTRY: REGISTRY_CERT_SECRET_NAME - + CERT_MODE_DOCKER_REGISTRY: REGISTRY_CERT_SECRET_NAME, + CERT_MODE_OPENLDAP: OPENLDAP_CERT_SECRET_NAME } # Storage associated networks