mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Enable upgrades from a mod_nss-installed master to mod_ssl
The existing private/public keys are migrated to PEM files via a PKCS#12 temporary file. This should work for both IPA-generated and user-provided server certificates. Related: https://pagure.io/freeipa/issue/3757 Reviewed-By: Christian Heimes <cheimes@redhat.com> Reviewed-By: Stanislav Laznicka <slaznick@redhat.com> Reviewed-By: Rob Crittenden <rcritten@redhat.com>
This commit is contained in:
parent
5c64e28512
commit
4596674481
@ -116,6 +116,8 @@ class HTTPInstance(service.Service):
|
|||||||
self.step("stopping httpd", self.__stop)
|
self.step("stopping httpd", self.__stop)
|
||||||
self.step("backing up ssl.conf", self.backup_ssl_conf)
|
self.step("backing up ssl.conf", self.backup_ssl_conf)
|
||||||
self.step("disabling nss.conf", self.disable_nss_conf)
|
self.step("disabling nss.conf", self.disable_nss_conf)
|
||||||
|
self.step("configuring mod_ssl certificate paths",
|
||||||
|
self.configure_mod_ssl_certs)
|
||||||
self.step("setting mod_ssl protocol list to TLSv1.0 - TLSv1.2",
|
self.step("setting mod_ssl protocol list to TLSv1.0 - TLSv1.2",
|
||||||
self.set_mod_ssl_protocol)
|
self.set_mod_ssl_protocol)
|
||||||
self.step("configuring mod_ssl log directory",
|
self.step("configuring mod_ssl log directory",
|
||||||
@ -198,6 +200,11 @@ class HTTPInstance(service.Service):
|
|||||||
tasks.configure_http_gssproxy_conf(IPAAPI_USER)
|
tasks.configure_http_gssproxy_conf(IPAAPI_USER)
|
||||||
services.knownservices.gssproxy.restart()
|
services.knownservices.gssproxy.restart()
|
||||||
|
|
||||||
|
def get_mod_nss_nickname(self):
|
||||||
|
cert = installutils.get_directive(paths.HTTPD_NSS_CONF, 'NSSNickname')
|
||||||
|
nickname = installutils.unquote_directive_value(cert, quote_char="'")
|
||||||
|
return nickname
|
||||||
|
|
||||||
def backup_ssl_conf(self):
|
def backup_ssl_conf(self):
|
||||||
self.fstore.backup_file(paths.HTTPD_SSL_CONF)
|
self.fstore.backup_file(paths.HTTPD_SSL_CONF)
|
||||||
|
|
||||||
@ -225,7 +232,6 @@ class HTTPInstance(service.Service):
|
|||||||
if sysupgrade.get_upgrade_state('http', OCSP_ENABLED) is None:
|
if sysupgrade.get_upgrade_state('http', OCSP_ENABLED) is None:
|
||||||
self.__disable_mod_ssl_ocsp()
|
self.__disable_mod_ssl_ocsp()
|
||||||
sysupgrade.set_upgrade_state('http', OCSP_ENABLED, False)
|
sysupgrade.set_upgrade_state('http', OCSP_ENABLED, False)
|
||||||
>>>>>>> 754c26ef6... Revisions for ocsp
|
|
||||||
|
|
||||||
def __disable_mod_ssl_ocsp(self):
|
def __disable_mod_ssl_ocsp(self):
|
||||||
aug = Augeas(flags=Augeas.NO_LOAD | Augeas.NO_MODL_AUTOLOAD)
|
aug = Augeas(flags=Augeas.NO_LOAD | Augeas.NO_MODL_AUTOLOAD)
|
||||||
@ -250,6 +256,35 @@ class HTTPInstance(service.Service):
|
|||||||
aug.set(ocsp_comment, '{} {}'.format(OCSP_DIRECTIVE, ocsp_state))
|
aug.set(ocsp_comment, '{} {}'.format(OCSP_DIRECTIVE, ocsp_state))
|
||||||
aug.save()
|
aug.save()
|
||||||
|
|
||||||
|
# def disable_mod_nss_ocsp(self):
|
||||||
|
# if sysupgrade.get_upgrade_state('http', NSS_OCSP_ENABLED) is None:
|
||||||
|
# self.__disable_mod_nss_ocsp()
|
||||||
|
# sysupgrade.set_upgrade_state('http', NSS_OCSP_ENABLED, False)
|
||||||
|
|
||||||
|
# def __disable_mod_nss_ocsp(self):
|
||||||
|
# aug = Augeas(flags=Augeas.NO_LOAD | Augeas.NO_MODL_AUTOLOAD)
|
||||||
|
#
|
||||||
|
# aug.set('/augeas/load/Httpd/lens', 'Httpd.lns')
|
||||||
|
# aug.set('/augeas/load/Httpd/incl', paths.HTTPD_NSS_CONF)
|
||||||
|
# aug.load()
|
||||||
|
#
|
||||||
|
# path = '/files{}/VirtualHost'.format(paths.HTTPD_NSS_CONF)
|
||||||
|
# ocsp_path = '{}/directive[.="{}"]'.format(path, OCSP_DIRECTIVE)
|
||||||
|
# ocsp_arg = '{}/arg'.format(ocsp_path)
|
||||||
|
# ocsp_comment = '{}/#comment[.="{}"]'.format(path, OCSP_DIRECTIVE)
|
||||||
|
#
|
||||||
|
# ocsp_dir = aug.get(ocsp_path)
|
||||||
|
#
|
||||||
|
# # there is NSSOCSP directive in nss.conf file, comment it
|
||||||
|
# # otherwise just do nothing
|
||||||
|
# if ocsp_dir is not None:
|
||||||
|
# ocsp_state = aug.get(ocsp_arg)
|
||||||
|
# aug.remove(ocsp_arg)
|
||||||
|
# aug.rename(ocsp_path, '#comment')
|
||||||
|
# aug.set(ocsp_comment, '{} {}'.format(OCSP_DIRECTIVE, ocsp_state))
|
||||||
|
# aug.save()
|
||||||
|
|
||||||
|
|
||||||
def __add_include(self):
|
def __add_include(self):
|
||||||
"""This should run after __set_mod_nss_port so is already backed up"""
|
"""This should run after __set_mod_nss_port so is already backed up"""
|
||||||
if installutils.update_file(paths.HTTPD_SSL_CONF,
|
if installutils.update_file(paths.HTTPD_SSL_CONF,
|
||||||
@ -347,9 +382,9 @@ class HTTPInstance(service.Service):
|
|||||||
finally:
|
finally:
|
||||||
if prev_helper is not None:
|
if prev_helper is not None:
|
||||||
certmonger.modify_ca_helper('IPA', prev_helper)
|
certmonger.modify_ca_helper('IPA', prev_helper)
|
||||||
self.cert = x509.load_der_x509_certificate(
|
self.cert = x509.load_certificate_from_file(
|
||||||
paths.HTTPD_CERT_FILE
|
paths.HTTPD_CERT_FILE
|
||||||
)
|
)
|
||||||
|
|
||||||
if prev_helper is not None:
|
if prev_helper is not None:
|
||||||
self.add_cert_to_service()
|
self.add_cert_to_service()
|
||||||
@ -363,7 +398,10 @@ class HTTPInstance(service.Service):
|
|||||||
# store the CA cert nickname so that we can publish it later on
|
# store the CA cert nickname so that we can publish it later on
|
||||||
# self.cacert_nickname = db.cacert_name
|
# self.cacert_nickname = db.cacert_name
|
||||||
# FIXME: figure this out too
|
# FIXME: figure this out too
|
||||||
|
sysupgrade.set_upgrade_state('ssl.conf', 'migrated_to_mod_ssl', True)
|
||||||
|
|
||||||
|
def configure_mod_ssl_certs(self):
|
||||||
|
"""Configure the mod_ssl certificate directives"""
|
||||||
installutils.set_directive(paths.HTTPD_SSL_CONF,
|
installutils.set_directive(paths.HTTPD_SSL_CONF,
|
||||||
'SSLCertificateFile',
|
'SSLCertificateFile',
|
||||||
paths.HTTPD_CERT_FILE, False)
|
paths.HTTPD_CERT_FILE, False)
|
||||||
@ -499,14 +537,14 @@ class HTTPInstance(service.Service):
|
|||||||
str(e))
|
str(e))
|
||||||
|
|
||||||
def start_tracking_certificates(self):
|
def start_tracking_certificates(self):
|
||||||
cert = x509.load_pem_x509_certificate(paths.HTTPD_CERT_FILE)
|
cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE)
|
||||||
if certs.is_ipa_issued_cert(api, cert):
|
if certs.is_ipa_issued_cert(api, cert):
|
||||||
request_id = certmonger.start_tracking(
|
request_id = certmonger.start_tracking(
|
||||||
certpath=(paths.HTTPD_CERT_FILE, paths.HTTPD_CERT_KEY),
|
certpath=(paths.HTTPD_CERT_FILE, paths.HTTPD_KEY_FILE),
|
||||||
post_command='restart_httpd'
|
post_command='restart_httpd', storage='FILE'
|
||||||
)
|
)
|
||||||
subject = str(DN(cert.subject))
|
subject = str(DN(cert.subject))
|
||||||
certmonger.add_principal(request_id, principal)
|
certmonger.add_principal(request_id, self.principal)
|
||||||
certmonger.add_subject(request_id, subject)
|
certmonger.add_subject(request_id, subject)
|
||||||
else:
|
else:
|
||||||
logger.debug("Will not track HTTP server cert %s as it is not "
|
logger.debug("Will not track HTTP server cert %s as it is not "
|
||||||
@ -530,3 +568,32 @@ class HTTPInstance(service.Service):
|
|||||||
remote_ldap.simple_bind(ipaldap.DIRMAN_DN,
|
remote_ldap.simple_bind(ipaldap.DIRMAN_DN,
|
||||||
self.dm_password)
|
self.dm_password)
|
||||||
replication.wait_for_entry(remote_ldap, service_dn, timeout=60)
|
replication.wait_for_entry(remote_ldap, service_dn, timeout=60)
|
||||||
|
|
||||||
|
def migrate_to_mod_ssl(self):
|
||||||
|
"""For upgrades only, migrate from mod_nss to mod_ssl"""
|
||||||
|
db = certs.CertDB(api.env.realm, nssdir=paths.HTTPD_ALIAS_DIR)
|
||||||
|
nickname = self.get_mod_nss_nickname()
|
||||||
|
with tempfile.NamedTemporaryFile() as temp:
|
||||||
|
pk12_password = ipautil.ipa_generate_password()
|
||||||
|
pk12_pwdfile = ipautil.write_tmp_file(pk12_password)
|
||||||
|
db.export_pkcs12(temp.name, pk12_pwdfile.name, nickname)
|
||||||
|
certs.install_pem_from_p12(temp.name,
|
||||||
|
pk12_password,
|
||||||
|
paths.HTTPD_CERT_FILE)
|
||||||
|
certs.install_key_from_p12(temp.name,
|
||||||
|
pk12_password,
|
||||||
|
paths.HTTPD_KEY_FILE)
|
||||||
|
|
||||||
|
self.configure_mod_ssl_certs()
|
||||||
|
self.set_mod_ssl_protocol()
|
||||||
|
self.set_mod_ssl_logdir()
|
||||||
|
|
||||||
|
self.cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE)
|
||||||
|
|
||||||
|
if self.ca_is_configured:
|
||||||
|
db.untrack_server_cert(nickname)
|
||||||
|
self.start_tracking_certificates()
|
||||||
|
|
||||||
|
# remove nickname and CA certs from NSS db
|
||||||
|
|
||||||
|
self.disable_nss_conf()
|
||||||
|
@ -13,7 +13,7 @@ import fileinput
|
|||||||
import sys
|
import sys
|
||||||
from augeas import Augeas
|
from augeas import Augeas
|
||||||
import dns.exception
|
import dns.exception
|
||||||
from ipalib import api
|
from ipalib import api, x509
|
||||||
from ipalib.install import certmonger, sysrestore
|
from ipalib.install import certmonger, sysrestore
|
||||||
import SSSDConfig
|
import SSSDConfig
|
||||||
import ipalib.util
|
import ipalib.util
|
||||||
@ -58,6 +58,7 @@ else:
|
|||||||
if six.PY3:
|
if six.PY3:
|
||||||
unicode = str
|
unicode = str
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -987,13 +988,12 @@ def certificate_renewal_update(ca, ds, http):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# Check the http server cert if issued by IPA
|
# Check the http server cert if issued by IPA
|
||||||
http_nickname = http.get_mod_nss_nickname()
|
cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE)
|
||||||
http_db = certs.CertDB(api.env.realm, nssdir=paths.HTTPD_ALIAS_DIR)
|
if certs.is_ipa_issued_cert(api, cert):
|
||||||
if http_db.is_ipa_issued_cert(api, http_nickname):
|
|
||||||
requests.append(
|
requests.append(
|
||||||
{
|
{
|
||||||
'cert-database': paths.HTTPD_ALIAS_DIR,
|
'cert-file': paths.HTTPD_CERT_FILE,
|
||||||
'cert-nickname': http_nickname,
|
'key-storage': paths.HTTPD_KEY_FILE,
|
||||||
'ca-name': 'IPA',
|
'ca-name': 'IPA',
|
||||||
'cert-postsave-command': template % 'restart_httpd',
|
'cert-postsave-command': template % 'restart_httpd',
|
||||||
}
|
}
|
||||||
@ -1436,38 +1436,18 @@ def fix_trust_flags():
|
|||||||
sysupgrade.set_upgrade_state('http', 'fix_trust_flags', True)
|
sysupgrade.set_upgrade_state('http', 'fix_trust_flags', True)
|
||||||
|
|
||||||
|
|
||||||
def update_mod_nss_protocol(http):
|
def migrate_to_mod_ssl(http):
|
||||||
logger.info('[Updating mod_nss protocol versions]')
|
logger.info('[Migrating from mod_nss to mod_ssl]')
|
||||||
|
|
||||||
if sysupgrade.get_upgrade_state('nss.conf', 'protocol_updated_tls12'):
|
if sysupgrade.get_upgrade_state('ssl.conf', 'migrated_to_mod_ssl'):
|
||||||
logger.info("Protocol versions already updated")
|
logger.info("Already migrated to mod_ssl")
|
||||||
return
|
return
|
||||||
|
|
||||||
http.set_mod_nss_protocol()
|
http.migrate_to_mod_ssl()
|
||||||
|
|
||||||
sysupgrade.set_upgrade_state('nss.conf', 'protocol_updated_tls12', True)
|
sysupgrade.set_upgrade_state('ssl.conf', 'migrated_to_mod_ssl', True)
|
||||||
|
|
||||||
|
|
||||||
def disable_mod_nss_ocsp(http):
|
|
||||||
logger.info('[Updating mod_nss enabling OCSP]')
|
|
||||||
http.disable_mod_nss_ocsp()
|
|
||||||
|
|
||||||
|
|
||||||
def update_mod_nss_cipher_suite(http):
|
|
||||||
logger.info('[Updating mod_nss cipher suite]')
|
|
||||||
|
|
||||||
revision = sysupgrade.get_upgrade_state('nss.conf', 'cipher_suite_updated')
|
|
||||||
if revision and revision >= httpinstance.NSS_CIPHER_REVISION:
|
|
||||||
logger.debug("Cipher suite already updated")
|
|
||||||
return
|
|
||||||
|
|
||||||
http.set_mod_nss_cipher_suite()
|
|
||||||
|
|
||||||
sysupgrade.set_upgrade_state(
|
|
||||||
'nss.conf',
|
|
||||||
'cipher_suite_updated',
|
|
||||||
httpinstance.NSS_CIPHER_REVISION)
|
|
||||||
|
|
||||||
|
|
||||||
def update_ipa_httpd_service_conf(http):
|
def update_ipa_httpd_service_conf(http):
|
||||||
logger.info('[Updating HTTPD service IPA configuration]')
|
logger.info('[Updating HTTPD service IPA configuration]')
|
||||||
@ -1628,21 +1608,6 @@ def enable_certauth(krb):
|
|||||||
aug.close()
|
aug.close()
|
||||||
|
|
||||||
|
|
||||||
def disable_httpd_system_trust(http):
|
|
||||||
ca_certs = []
|
|
||||||
|
|
||||||
db = certs.CertDB(api.env.realm, nssdir=paths.HTTPD_ALIAS_DIR)
|
|
||||||
for nickname, trust_flags in db.list_certs():
|
|
||||||
if not trust_flags.has_key:
|
|
||||||
cert = db.get_cert_from_db(nickname)
|
|
||||||
if cert:
|
|
||||||
ca_certs.append((cert, nickname, trust_flags))
|
|
||||||
|
|
||||||
if http.disable_system_trust():
|
|
||||||
for cert, nickname, trust_flags in ca_certs:
|
|
||||||
db.add_cert(cert, nickname, trust_flags)
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade_configuration():
|
def upgrade_configuration():
|
||||||
"""
|
"""
|
||||||
Execute configuration upgrade of the IPA services
|
Execute configuration upgrade of the IPA services
|
||||||
@ -1797,12 +1762,9 @@ def upgrade_configuration():
|
|||||||
http.enable_kdcproxy()
|
http.enable_kdcproxy()
|
||||||
|
|
||||||
http.stop()
|
http.stop()
|
||||||
disable_httpd_system_trust(http)
|
|
||||||
update_ipa_httpd_service_conf(http)
|
update_ipa_httpd_service_conf(http)
|
||||||
update_ipa_http_wsgi_conf(http)
|
update_ipa_http_wsgi_conf(http)
|
||||||
update_mod_nss_protocol(http)
|
migrate_to_mod_ssl(http)
|
||||||
update_mod_nss_cipher_suite(http)
|
|
||||||
disable_mod_nss_ocsp(http)
|
|
||||||
fix_trust_flags()
|
fix_trust_flags()
|
||||||
update_http_keytab(http)
|
update_http_keytab(http)
|
||||||
http.configure_gssproxy()
|
http.configure_gssproxy()
|
||||||
|
Loading…
Reference in New Issue
Block a user