From 732437f3cd9d8ed7170e4870314cbd2e8a569fa4 Mon Sep 17 00:00:00 2001 From: amantri Date: Wed, 26 Jul 2023 12:23:08 -0400 Subject: [PATCH] Deprecate,add new system certificate commands Deprecate the existing system certificate commands and add new commands Testcases: PASS: Bootstrap the system with changes and verify that system is installed successfully PASS: Run update_platform_certificates and verify it is successful PASS: Verify the following commands are not working anymore system modify --https_enabled=True system modify --https_enabled=False PASS: Verify new following ca commands system ca-certificate-install system ca-certificate-list system ca-certificate-show system ca-certificate-uninstall PASS: Verify new openstack commands are working system os-certificate-install --mode < server | ca > system os-certificate-list system os-certificate-show PASS: Verify the following are not working anymore system certificate-install -m ssl system certificate-install -m openstack system certificate-install -m openstack_ca system certificate-install -m ssl_ca system certificate-install -m docker_registry system certificate-uninstall -m ssl_ca Story: 2010848 Task: 48474 Change-Id: Ic5d4f3c60b196f5be0602502dcd8a3af50cc8e62 Signed-off-by: amantri --- .../cgtsclient/v1/certificate_shell.py | 196 +++++++++++++----- .../cgtsclient/v1/isystem_shell.py | 28 +-- .../sysinv/sysinv/sysinv/common/exception.py | 2 +- 3 files changed, 141 insertions(+), 85 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 13c79bffab..2da16c2f20 100644 --- a/sysinv/cgts-client/cgts-client/cgtsclient/v1/certificate_shell.py +++ b/sysinv/cgts-client/cgts-client/cgtsclient/v1/certificate_shell.py @@ -34,58 +34,12 @@ def _print_certificate_show(certificate): utils.print_tuple_list(data) -@utils.arg('certificate_uuid', metavar='', - help="UUID of certificate") -def do_certificate_show(cc, args): - """Show Certificate details.""" - certificate = cc.certificate.get(args.certificate_uuid) - if certificate: - _print_certificate_show(certificate) - else: - print("No Certificates installed") - - -def do_certificate_list(cc, args): - """List certificates.""" - certificates = cc.certificate.list() - fields = ['uuid', 'certtype', 'expiry_date', 'subject'] - field_labels = fields - for certificate in certificates: - if certificate.subject and len(certificate.subject) > 20: - certificate.subject = certificate.subject[:20] + "..." - utils.print_list(certificates, fields, field_labels, sortby=0) - - -@utils.arg('certificate_file', - metavar='', - help='Path to Certificate file (PEM format) to install. ' - 'WARNING: For security reasons, the original certificate_file ' - 'will be removed. Installing an invalid certificate ' - 'could cause service interruption.') -@utils.arg('-p', '--passphrase', - metavar='', - help='The passphrase for the PEM file') -@utils.arg('-m', '--mode', - metavar='', - help="optional mode: 'docker_registry', " - "'openstack', 'openstack_ca', 'ssl_ca'. " - "Default is 'ssl'.") -def do_certificate_install(cc, args): - """Install certificate.""" - - certificate_file = args.certificate_file +def _install_cert(cc, certificate_file, data): try: sec_file = open(certificate_file, 'rb') except Exception: raise exc.CommandError("Error: Could not open file %s." % certificate_file) - - data = {'passphrase': args.passphrase, - 'mode': args.mode} - - if data['mode'] in ['openldap', 'openldap_ca']: - raise exc.CommandError('Warning: Invalid mode: %s' % data['mode']) - has_private_key = False try: with open(certificate_file, 'r') as reader: @@ -128,18 +82,146 @@ def do_certificate_install(cc, args): @utils.arg('certificate_uuid', metavar='', - help="UUID of certificate to uninstall") + help="UUID of certificate") +def do_certificate_show(cc, args): + """Show Certificate details.""" + certificate = cc.certificate.get(args.certificate_uuid) + if certificate: + _print_certificate_show(certificate) + else: + print("No Certificates installed") + + +def do_certificate_list(cc, args): + """List certificates.""" + certificates = cc.certificate.list() + fields = ['uuid', 'certtype', 'expiry_date', 'subject'] + field_labels = fields + for certificate in certificates: + if certificate.subject and len(certificate.subject) > 20: + certificate.subject = certificate.subject[:20] + "..." + utils.print_list(certificates, fields, field_labels, sortby=0) + + +@utils.arg('certificate_file', + metavar='', + help='Path to Certificate file (PEM format) to install. ' + 'WARNING: For security reasons, the original certificate_file ' + 'will be removed. Installing an invalid certificate ' + 'could cause service interruption.') +@utils.arg('-p', '--passphrase', + metavar='', + help='The passphrase for the PEM file') @utils.arg('-m', '--mode', metavar='', - help="Supported mode: 'ssl_ca'.") -def do_certificate_uninstall(cc, args): - """Uninstall certificate.""" + help="optional mode: 'server', 'ca'. ") +def do_os_certificate_install(cc, args): + """Install certificate.""" + certificate_file = args.certificate_file - supported_modes = ['ssl_ca'] - if args.mode not in supported_modes: - msg = ("Unsupported mode: {}\nPlease use certificate-install" - " instead to update the existing certificate").format(args.mode) + data = {'passphrase': args.passphrase, + 'mode': args.mode} + + if not data['mode']: + raise exc.CommandError('Warning: Need to specify a valid mode: server or ca') + + if data['mode'] == 'server': + data['mode'] = 'openstack' + elif data['mode'] == 'ca': + data['mode'] = 'openstack_ca' + else: + raise exc.CommandError('Warning: Invalid mode: %s' % data['mode']) + + _install_cert(cc, certificate_file, data) + + +def do_os_certificate_list(cc, args): + """List openstack certificates.""" + os_cert_types = ['openstack', 'openstack_ca'] + certificates = [] + for certificate in cc.certificate.list(): + if certificate.certtype in os_cert_types: + if certificate.certtype == "openstack": + certificate.certtype = "server" + elif certificate.certtype == "openstack_ca": + certificate.certtype = "ca" + certificates.append(certificate) + + fields = ['uuid', 'certtype', 'expiry_date', 'subject'] + field_labels = fields + for certificate in certificates: + if certificate.subject and len(certificate.subject) > 20: + certificate.subject = certificate.subject[:20] + "..." + utils.print_list(certificates, fields, field_labels, sortby=0) + + +@utils.arg('certificate_uuid', metavar='', + help="UUID of certificate") +def do_os_certificate_show(cc, args): + """Show Openstack Certificate details.""" + certificate = cc.certificate.get(args.certificate_uuid) + if certificate.certtype in ['openstack', 'openstack_ca']: + if certificate.certtype == "openstack": + certificate.certtype = "server" + elif certificate.certtype == "openstack_ca": + certificate.certtype = "ca" + _print_certificate_show(certificate) + else: + print('No certificate of type "openstack" is installed ' + 'with this uuid: %s' % (args.certificate_uuid)) + + +@utils.arg('certificate_file', + metavar='', + help='Path to Certificate file (PEM format) to install. ' + 'WARNING: For security reasons, the original certificate_file ' + 'will be removed. Installing an invalid certificate ' + 'could cause service interruption.') +@utils.arg('-p', '--passphrase', + metavar='', + help='The passphrase for the PEM file') +def do_ca_certificate_install(cc, args): + """Install certificate.""" + certificate_file = args.certificate_file + + data = {'passphrase': args.passphrase, + 'mode': 'ssl_ca'} + + _install_cert(cc, certificate_file, data) + + +@utils.arg('certificate_uuid', metavar='', + help="UUID of certificate to uninstall") +def do_ca_certificate_uninstall(cc, args): + """Uninstall ca certificate.""" + certificate = cc.certificate.get(args.certificate_uuid) + if certificate.certtype == 'ssl_ca': + cc.certificate.certificate_uninstall(args.certificate_uuid) + print('Uninstalled certificate: %s' % (args.certificate_uuid)) + else: + msg = "Only ssl_ca type certs can be uninstalled using this command" raise exc.CommandError(msg) - cc.certificate.certificate_uninstall(args.certificate_uuid) - print('Uninstalled certificate: %s' % (args.certificate_uuid)) + +def do_ca_certificate_list(cc, args): + """List certificates.""" + certificates = [certificate for certificate in cc.certificate.list() + if certificate.certtype == 'ssl_ca'] + fields = ['uuid', 'expiry_date', 'subject'] + field_labels = fields + for certificate in certificates: + if certificate.subject and len(certificate.subject) > 20: + certificate.subject = certificate.subject[:20] + "..." + utils.print_list(certificates, fields, field_labels, sortby=0) + + +@utils.arg('certificate_uuid', metavar='', + help="UUID of certificate") +def do_ca_certificate_show(cc, args): + """Show Certificate details.""" + certificate = cc.certificate.get(args.certificate_uuid) + if certificate.certtype == 'ssl_ca': + _print_certificate_show(certificate) + else: + print('No certificate of type "ssl_ca" is installed with ' + 'this uuid: %s' % (args.certificate_uuid)) diff --git a/sysinv/cgts-client/cgts-client/cgtsclient/v1/isystem_shell.py b/sysinv/cgts-client/cgts-client/cgtsclient/v1/isystem_shell.py index 6bf33dcdbc..b96c2af3b3 100644 --- a/sysinv/cgts-client/cgts-client/cgtsclient/v1/isystem_shell.py +++ b/sysinv/cgts-client/cgts-client/cgtsclient/v1/isystem_shell.py @@ -82,10 +82,6 @@ def do_show(cc, args): @utils.arg('-lo', '--longitude', metavar='', help='The longitude GEO location coordinate of the system') -@utils.arg('-p', '--https_enabled', - metavar='', - choices=['true', 'false', 'True', 'False'], - help='The HTTPS enabled or disabled flag') @utils.arg('-v', '--vswitch_type', metavar='', help='The vswitch type for the system') @@ -138,7 +134,7 @@ def do_modify(cc, args): field_list = ['name', 'system_mode', 'description', 'location', 'latitude', 'longitude', 'contact', 'timezone', 'sdn_enabled', - 'https_enabled', 'vswitch_type', 'security_feature'] + 'vswitch_type', 'security_feature'] # use field list as filter user_fields = dict((k, v) for (k, v) in vars(args).items() @@ -146,34 +142,12 @@ def do_modify(cc, args): configured_fields = isystem.__dict__ configured_fields.update(user_fields) - print_https_warning = False - patch = [] for (k, v) in user_fields.items(): patch.append({'op': 'replace', 'path': '/' + k, 'value': v}) - if k == "https_enabled" and v == "true": - print_https_warning = True - - # If there is an existing ssl or tpm certificate in system, it will - # be used instead of installing the default self signed certificate. - if print_https_warning: - certificates = cc.certificate.list() - for certificate in certificates: - if certificate.certtype == 'ssl': - warning = ("Existing certificate %s is used for https." - % certificate.uuid) - break - else: - warning = "HTTPS enabled with a self-signed certificate.\nThis " \ - "should be changed to a CA-signed certificate with " \ - "'system certificate-install'. " - try: isystem = cc.isystem.update(isystem.uuid, patch) except exc.HTTPNotFound: raise exc.CommandError('system not found: %s' % isystem.uuid) _print_isystem_show(isystem) - - if print_https_warning: - print(warning) diff --git a/sysinv/sysinv/sysinv/sysinv/common/exception.py b/sysinv/sysinv/sysinv/sysinv/common/exception.py index 937e0907a4..f073b73d27 100644 --- a/sysinv/sysinv/sysinv/sysinv/common/exception.py +++ b/sysinv/sysinv/sysinv/sysinv/common/exception.py @@ -969,7 +969,7 @@ class DockerRegistryCredentialNotFound(NotFound): class DockerRegistrySSLException(SysinvException): message = _("Registry certificate signed by an unknown CA. " - "Install a trusted CA with 'system certificate-install -m ssl_ca'") + "Install a trusted CA with 'system ca-certificate-install'") class DockerRegistryAPIException(SysinvException):