keep and reuse ssl certificate

Currently when https is disabled, the installed ssl certificate
is removed from the system. The default self signed certificate
is installed again once https is enabled.

This change enhanced ssl certificate handling in that:
- The very first time https is enabled, the default self signed
  certificate is installed not only in fs but also in sysinv.
- When https is disabled, installed ssl/tpm certificate is no longer
  deleted.
- When https is enabled, the existing ssl/tpm certificate will be
  used if there is one installed. Otherwise the default self signed
  certificate will be installed (this is the case that https is
  enabled for the very first time).

Change-Id: Iaef7b4acc4badaab617c05dcbd6654ea3d1e126a
Closes-Bug: 1908437
Signed-off-by: Andy Ning <andy.ning@windriver.com>
This commit is contained in:
Andy Ning 2020-12-15 13:31:39 -05:00
parent 9331c8fcb5
commit 41b5fa0b50
2 changed files with 39 additions and 31 deletions

View File

@ -152,6 +152,20 @@ def do_modify(cc, args):
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 in ['ssl', 'tpm_mode']:
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:
@ -159,5 +173,4 @@ def do_modify(cc, args):
_print_isystem_show(isystem)
if print_https_warning:
print("HTTPS enabled with a self-signed certificate.\nThis should be "
"changed to a CA-signed certificate with 'system certificate-install'. ")
print(warning)

View File

@ -6080,7 +6080,13 @@ class ConductorManager(service.PeriodicService):
system = self.dbapi.isystem_get_one()
if system.capabilities.get('https_enabled', False):
self._config_selfsigned_certificate(context)
certificates = self.dbapi.certificate_get_list()
for certificate in certificates:
if certificate.certtype in [constants.CERT_MODE_SSL,
constants.CERT_MODE_TPM]:
break
else:
self._config_selfsigned_certificate(context)
config_dict = {
"personalities": personalities,
@ -6093,10 +6099,6 @@ class ConductorManager(service.PeriodicService):
config_uuid = self._config_update_hosts(context, personalities)
self._config_apply_runtime_manifest(context, config_uuid, config_dict)
if not system.capabilities.get('https_enabled', False):
self._destroy_tpm_config(context)
self._destroy_certificates(context)
cutils.touch(constants.HTTPS_CONFIG_REQUIRED)
@staticmethod
@ -10362,29 +10364,6 @@ class ConductorManager(service.PeriodicService):
self._config_apply_runtime_manifest(context, config_uuid, config_dict)
def _destroy_certificates(self, context):
"""Delete certificates."""
LOG.info("_destroy_certificates clear ssl/tpm certificates")
certificates = self.dbapi.certificate_get_list()
for certificate in certificates:
if certificate.certtype in [constants.CERT_MODE_SSL,
constants.CERT_MODE_TPM,
constants.CERT_MODE_OPENSTACK]:
self.dbapi.certificate_destroy(certificate.uuid)
personalities = [constants.CONTROLLER]
config_uuid = self._config_update_hosts(context, personalities)
config_dict = {
'personalities': personalities,
'file_names': [constants.SSL_PEM_FILE],
'file_content': None,
'permissions': constants.CONFIG_FILE_PERMISSION_ROOT_READ_ONLY,
'nobackup': True,
}
self._config_update_file(context, config_uuid, config_dict)
def _destroy_tpm_config(self, context, tpm_obj=None):
"""Delete a tpmconfig."""
@ -10921,7 +10900,23 @@ class ConductorManager(service.PeriodicService):
'wb') as f:
f.write(file_content)
return cert_list[0].get('signature')
# Inventory the self signed certificate.
# In case the self signed cert is ICA signed,
# skip these intermediate CA certs.
for cert in cert_list:
if not cert.get('is_ca', False):
values = {
'certtype': mode,
'signature': cert.get('signature'),
'start_date': cert.get('cert').not_valid_before,
'expiry_date': cert.get('cert').not_valid_after,
}
self.dbapi.certificate_create(values)
break
else:
msg = "Fail to inventory the self signed certificate, \
no leaf cert found."
raise exception.SysinvException(_(msg))
def delete_certificate(self, context, mode, signature):
"""Delete a certificate by its mode and signature.