Alon Bar-Lev has uploaded a new change for review. Change subject: packaging: setup: pki: renew about to expire certificates ......................................................................
packaging: setup: pki: renew about to expire certificates Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=1210486 Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=1214860 Change-Id: I6383b29e131d65cece96e298bb2c7fe6ae305afe Signed-off-by: Alon Bar-Lev <alo...@redhat.com> --- M packaging/setup/ovirt_engine_setup/engine/constants.py M packaging/setup/plugins/ovirt-engine-setup/ovirt-engine/pki/ca.py 2 files changed, 256 insertions(+), 124 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/08/40508/1 diff --git a/packaging/setup/ovirt_engine_setup/engine/constants.py b/packaging/setup/ovirt_engine_setup/engine/constants.py index da71bdc..a825a92 100644 --- a/packaging/setup/ovirt_engine_setup/engine/constants.py +++ b/packaging/setup/ovirt_engine_setup/engine/constants.py @@ -533,11 +533,16 @@ class PKIEnv(object): STORE_PASS = 'OVESETUP_PKI/storePassword' - COUNTRY = 'OVESETUP_PKI/country' + @osetupattrs( + postinstallfile=True, + ) + def COUNTRY(self): + return 'OVESETUP_PKI/country' @osetupattrs( answerfile=True, summary=True, + postinstallfile=True, description=_('PKI organization'), ) def ORG(self): diff --git a/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine/pki/ca.py b/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine/pki/ca.py index 84641b4..b0086cd 100644 --- a/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine/pki/ca.py +++ b/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine/pki/ca.py @@ -19,6 +19,7 @@ """CA plugin.""" +import datetime import os import re import random @@ -86,6 +87,221 @@ fileList=files, ) + def _extractPKCS12CertificateString(self, pkcs12): + rc, stdout, stderr = self.execute( + args=( + self.command.get('openssl'), + 'pkcs12', + '-in', pkcs12, + '-passin', 'pass:%s' % self.environment[ + oenginecons.PKIEnv.STORE_PASS + ], + '-nokeys', + ), + ) + return '\n'.join(stdout) + + def _extractPKCS12Certificate(self, pkcs12): + return X509.load_cert_string( + str( + self._extractPKCS12CertificateString(pkcs12) + ) + ) + + def _expandPKCS12(self, pkcs12, name, owner, uninstall_files): + rc, key, stderr = self.execute( + args=( + self.command.get('openssl'), + 'pkcs12', + '-in', pkcs12, + '-passin', 'pass:%s' % self.environment[ + oenginecons.PKIEnv.STORE_PASS + ], + '-nodes', + '-nocerts', + ), + logStreams=False, + ) + + self.environment[otopicons.CoreEnv.MAIN_TRANSACTION].append( + filetransaction.FileTransaction( + name=os.path.join( + oenginecons.FileLocations.OVIRT_ENGINE_PKICERTSDIR, + '%s.cer' % name, + ), + content=self._extractPKCS12CertificateString(pkcs12), + mode=0o644, + modifiedList=uninstall_files, + ) + ) + self.environment[otopicons.CoreEnv.MAIN_TRANSACTION].append( + filetransaction.FileTransaction( + name=os.path.join( + oenginecons.FileLocations.OVIRT_ENGINE_PKIKEYSDIR, + '%s.key.nopass' % name, + ), + content=key, + mode=0o600, + owner=owner, + modifiedList=uninstall_files, + ) + ) + + def _enrollCertificate(self, name, uninstall_files, keepKey=False): + self.execute( + ( + oenginecons.FileLocations.OVIRT_ENGINE_PKI_CA_ENROLL, + '--name=%s' % name, + '--password=%s' % ( + self.environment[oenginecons.PKIEnv.STORE_PASS], + ), + '--subject=/C=%s/O=%s/CN=%s' % ( + self._subjectComponentEscape( + self.environment[oenginecons.PKIEnv.COUNTRY], + ), + self._subjectComponentEscape( + self.environment[oenginecons.PKIEnv.ORG], + ), + self._subjectComponentEscape( + self.environment[osetupcons.ConfigEnv.FQDN], + ), + ), + ) + (('--keep-key',) if keepKey else ()) + ) + uninstall_files.extend( + ( + os.path.join( + oenginecons.FileLocations.OVIRT_ENGINE_PKIKEYSDIR, + name, + ), + os.path.join( + oenginecons.FileLocations.OVIRT_ENGINE_PKICERTSDIR, + name, + ), + ) + ) + + def _expired(self, x509): + # + # LEGACY NOTE + # Since 3.0 and maybe before the CA certificate's + # notBefore attribute was set using timezone offset + # instead of Z + # in this case we need to reissue CA certificate. + # + return ( + x509.get_not_before().get_datetime().tzname() is None or + ( + x509.get_not_after().get_datetime().replace(tzinfo=None) - + datetime.datetime.utcnow() < + datetime.timedelta(days=365) + ) + ) + + def _enrollCertificates(self, renew, uninstall_files): + for entry in ( + { + 'name': 'engine', + 'extract': False, + 'user': osetupcons.SystemEnv.USER_ENGINE, + 'keepKey': True, + }, + { + 'name': 'jboss', + 'extract': False, + 'user': osetupcons.SystemEnv.USER_ENGINE, + 'keepKey': False, + }, + { + 'name': 'websocket-proxy', + 'extract': True, + 'user': osetupcons.SystemEnv.USER_ENGINE, + 'keepKey': False, + }, + { + 'name': 'apache', + 'extract': True, + 'user': oengcommcons.SystemEnv.USER_ROOT, + 'keepKey': False, + }, + { + 'name': 'reports', + 'extract': True, + 'user': oengcommcons.SystemEnv.USER_ROOT, + 'keepKey': False, + }, + ): + self.logger.debug( + "processing: '%s'[renew=%s]", + entry['name'], + renew, + ) + + pkcs12 = os.path.join( + oenginecons.FileLocations.OVIRT_ENGINE_PKIKEYSDIR, + '%s.p12' % entry['name'], + ) + + enroll = not renew + + if not enroll: + x509 = self._extractPKCS12Certificate(pkcs12) + if self._expired(x509): + if not entry['extract']: + enroll = True + else: + if x509.verify( + X509.load_cert( + oenginecons.FileLocations. + OVIRT_ENGINE_PKI_ENGINE_CA_CERT + ).get_pubkey() + ): + self.logger.debug( + 'certificate is an internal certificate' + ) + + # sanity check, make sure user did not manually + # change cert + x509x = X509.load_cert( + os.path.join( + ( + oenginecons.FileLocations. + OVIRT_ENGINE_PKICERTSDIR + ), + '%s.cer' % entry['name'], + ) + ) + + if x509x.as_pem() == x509.as_pem(): + self.logger.debug('certificate is sane') + enroll = True + + if enroll: + self.logger.info( + _('Renewing {name} certificate').format( + name=entry['name'], + ) + ) + + if enroll: + self._enrollCertificate( + entry['name'], + uninstall_files, + keepKey=entry['keepKey'] and renew, + ) + os.chown( + pkcs12, + osetuputil.getUid(self.environment[entry['user']]), + -1, + ) + if entry['extract']: + self._expandPKCS12( + pkcs12, + entry['name'], + self.environment[entry['user']], + uninstall_files, + ) + def __init__(self, context): super(Plugin, self).__init__(context=context) self._enabled = False @@ -117,6 +333,12 @@ oenginecons.PKIEnv.ORG, None ) + + @plugin.event( + stage=plugin.Stages.STAGE_SETUP, + ) + def _setup(self): + self.command.detect('openssl') @plugin.event( stage=plugin.Stages.STAGE_CUSTOMIZATION, @@ -166,6 +388,26 @@ ), ) def _miscUpgrade(self): + # + # In <3.6 setup did not store the organization and + # country in post install file. Load it from CA certificate. + # + if self.environment[oenginecons.PKIEnv.ORG] is None: + ca = X509.load_cert( + oenginecons.FileLocations. + OVIRT_ENGINE_PKI_ENGINE_CA_CERT + ) + self.environment[ + oenginecons.PKIEnv.ORG + ] = ca.get_subject().get_entries_by_nid( + X509.X509_Name.nid['O'] + )[0].get_data().as_text() + self.environment[ + oenginecons.PKIEnv.COUNTRY + ] = ca.get_subject().get_entries_by_nid( + X509.X509_Name.nid['C'] + )[0].get_data().as_text() + self.logger.info(_('Upgrading CA')) # @@ -222,17 +464,11 @@ ), ) - # - # LEGACY NOTE - # Since 3.0 and maybe before the CA certificate's - # notBefore attribute was set using timezone offset - # instead of Z - # in this case we need to reissue CA certificate. - # - x509 = X509.load_cert( - oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_CA_CERT - ) - if x509.get_not_before().get_datetime().tzname() is None: + if self._expired( + X509.load_cert( + oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_CA_CERT + ) + ): self._ca_was_renewed = True self.logger.info(_('Renewing CA')) self.execute( @@ -249,6 +485,8 @@ ], }, ) + + self._enrollCertificates(True, uninstall_files) @plugin.event( stage=plugin.Stages.STAGE_MISC, @@ -342,111 +580,14 @@ }, ) - for name in ( - 'engine', - 'apache', - 'jboss', - 'websocket-proxy', - 'reports' - ): - self.execute( - ( - oenginecons.FileLocations.OVIRT_ENGINE_PKI_CA_ENROLL, - '--name=%s' % name, - '--password=%s' % ( - self.environment[oenginecons.PKIEnv.STORE_PASS], - ), - '--subject=/C=%s/O=%s/CN=%s' % ( - self._subjectComponentEscape( - self.environment[oenginecons.PKIEnv.COUNTRY], - ), - self._subjectComponentEscape( - self.environment[oenginecons.PKIEnv.ORG], - ), - self._subjectComponentEscape( - self.environment[osetupcons.ConfigEnv.FQDN], - ), - ), - ), - ) - uninstall_files.extend( ( - oengcommcons.FileLocations.OVIRT_ENGINE_PKI_APACHE_CERT, - oenginecons.FileLocations.OVIRT_ENGINE_PKI_APACHE_STORE, oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_CA_CERT, oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_CA_KEY, - oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_CERT, - oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_STORE, oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_TRUST_STORE, - oenginecons.FileLocations.OVIRT_ENGINE_PKI_JBOSS_STORE, - oenginecons.FileLocations.OVIRT_ENGINE_PKI_JBOSS_CERT, oenginecons.FileLocations.OVIRT_ENGINE_PKI_CA_CERT_CONF, oenginecons.FileLocations.OVIRT_ENGINE_PKI_CERT_CONF, - ( - oenginecons.FileLocations. - OVIRT_ENGINE_PKI_LOCAL_WEBSOCKET_PROXY_CERT - ), - ( - oenginecons.FileLocations. - OVIRT_ENGINE_PKI_LOCAL_WEBSOCKET_PROXY_STORE - ), ) - ) - - self.execute( - args=( - oenginecons.FileLocations.OVIRT_ENGINE_PKI_PKCS12_EXTRACT, - '--name=websocket-proxy', - '--passin=%s' % ( - self.environment[oenginecons.PKIEnv.STORE_PASS], - ), - '--key=%s' % ( - oenginecons.FileLocations. - OVIRT_ENGINE_PKI_LOCAL_WEBSOCKET_PROXY_KEY, - ), - ), - logStreams=False, - ) - uninstall_files.append( - oenginecons.FileLocations. - OVIRT_ENGINE_PKI_LOCAL_WEBSOCKET_PROXY_KEY - ) - - self.execute( - args=( - oenginecons.FileLocations.OVIRT_ENGINE_PKI_PKCS12_EXTRACT, - '--name=reports', - '--passin=%s' % ( - self.environment[oenginecons.PKIEnv.STORE_PASS], - ), - '--key=%s' % ( - oenginecons.FileLocations. - OVIRT_ENGINE_PKI_REPORTS_KEY, - ), - ), - logStreams=False, - ) - uninstall_files.append( - oenginecons.FileLocations. - OVIRT_ENGINE_PKI_REPORTS_KEY - ) - - self.execute( - args=( - oenginecons.FileLocations.OVIRT_ENGINE_PKI_PKCS12_EXTRACT, - '--name=apache', - '--passin=%s' % ( - self.environment[oenginecons.PKIEnv.STORE_PASS], - ), - '--key=%s' % ( - oengcommcons.FileLocations.OVIRT_ENGINE_PKI_APACHE_KEY, - ), - ), - logStreams=False, - ) - uninstall_files.append( - oengcommcons.FileLocations.OVIRT_ENGINE_PKI_APACHE_KEY ) if not os.path.exists( @@ -460,21 +601,7 @@ oengcommcons.FileLocations.OVIRT_ENGINE_PKI_APACHE_CA_CERT ) - for f in ( - oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_STORE, - oenginecons.FileLocations.OVIRT_ENGINE_PKI_JBOSS_STORE, - oenginecons.FileLocations. - OVIRT_ENGINE_PKI_LOCAL_WEBSOCKET_PROXY_KEY, - oenginecons.FileLocations. - OVIRT_ENGINE_PKI_LOCAL_WEBSOCKET_PROXY_STORE, - ): - os.chown( - f, - osetuputil.getUid( - self.environment[osetupcons.SystemEnv.USER_ENGINE] - ), - -1, - ) + self._enrollCertificates(False, uninstall_files) @plugin.event( stage=plugin.Stages.STAGE_MISC, -- To view, visit https://gerrit.ovirt.org/40508 To unsubscribe, visit https://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I6383b29e131d65cece96e298bb2c7fe6ae305afe Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: ovirt-engine-3.5 Gerrit-Owner: Alon Bar-Lev <alo...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches