From 01a7416d305ddb11d5b83c99afbacf8ba854c148 Mon Sep 17 00:00:00 2001 From: Jan Cholasta Date: May 19 2017 10:31:24 +0000 Subject: install: trust IPA CA for PKINIT Trust IPA CA to issue PKINIT KDC and client authentication certificates in the IPA certificate store. https://pagure.io/freeipa/issue/6831 Reviewed-By: Stanislav Laznicka Reviewed-By: Martin Babinsky --- diff --git a/ipalib/x509.py b/ipalib/x509.py index dbcbb59..4d866a6 100644 --- a/ipalib/x509.py +++ b/ipalib/x509.py @@ -66,6 +66,8 @@ EKU_SERVER_AUTH = '1.3.6.1.5.5.7.3.1' EKU_CLIENT_AUTH = '1.3.6.1.5.5.7.3.2' EKU_CODE_SIGNING = '1.3.6.1.5.5.7.3.3' EKU_EMAIL_PROTECTION = '1.3.6.1.5.5.7.3.4' +EKU_PKINIT_CLIENT_AUTH = '1.3.6.1.5.2.3.4' +EKU_PKINIT_KDC = '1.3.6.1.5.2.3.5' EKU_ANY = '2.5.29.37.0' EKU_PLACEHOLDER = '1.3.6.1.4.1.3319.6.10.16' diff --git a/ipapython/certdb.py b/ipapython/certdb.py index 0e42483..f5043af 100644 --- a/ipapython/certdb.py +++ b/ipapython/certdb.py @@ -65,6 +65,8 @@ IPA_CA_TRUST_FLAGS = TrustFlags( x509.EKU_CLIENT_AUTH, x509.EKU_CODE_SIGNING, x509.EKU_EMAIL_PROTECTION, + x509.EKU_PKINIT_CLIENT_AUTH, + x509.EKU_PKINIT_KDC, }), ) diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index 0e4ae4b..39248ed 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -31,8 +31,11 @@ import fnmatch import ldap +from ipalib import x509 from ipalib.install import certmonger, certstore -from ipapython.certdb import IPA_CA_TRUST_FLAGS, EXTERNAL_CA_TRUST_FLAGS +from ipapython.certdb import (IPA_CA_TRUST_FLAGS, + EXTERNAL_CA_TRUST_FLAGS, + TrustFlags) from ipapython.ipa_log_manager import root_logger from ipapython import ipautil, ipaldap from ipapython import dogtag @@ -289,7 +292,8 @@ class DsInstance(service.Service): def init_info(self, realm_name, fqdn, domain_name, dm_password, subject_base, ca_subject, - idstart, idmax, pkcs12_info, ca_file=None): + idstart, idmax, pkcs12_info, ca_file=None, + setup_pkinit=False): self.realm = realm_name.upper() self.serverid = installutils.realm_to_serverid(self.realm) self.suffix = ipautil.realm_to_suffix(self.realm) @@ -303,6 +307,7 @@ class DsInstance(service.Service): self.pkcs12_info = pkcs12_info if pkcs12_info: self.ca_is_configured = False + self.setup_pkinit = setup_pkinit self.ca_file = ca_file self.__setup_sub_dict() @@ -311,11 +316,12 @@ class DsInstance(service.Service): dm_password, pkcs12_info=None, idstart=1100, idmax=999999, subject_base=None, ca_subject=None, - hbac_allow=True, ca_file=None): + hbac_allow=True, ca_file=None, setup_pkinit=False): self.init_info( realm_name, fqdn, domain_name, dm_password, subject_base, ca_subject, - idstart, idmax, pkcs12_info, ca_file=ca_file) + idstart, idmax, pkcs12_info, ca_file=ca_file, + setup_pkinit=setup_pkinit) self.__common_setup() self.step("restarting directory server", self.__restart_instance) @@ -354,7 +360,8 @@ class DsInstance(service.Service): domain_name, dm_password, subject_base, ca_subject, api, pkcs12_info=None, ca_file=None, - ca_is_configured=None, promote=False): + ca_is_configured=None, promote=False, + setup_pkinit=False): # idstart and idmax are configured so that the range is seen as # depleted by the DNA plugin and the replica will go and get a # new range from the master. @@ -372,7 +379,8 @@ class DsInstance(service.Service): idstart=idstart, idmax=idmax, pkcs12_info=pkcs12_info, - ca_file=ca_file + ca_file=ca_file, + setup_pkinit=setup_pkinit, ) self.master_fqdn = master_fqdn if ca_is_configured is not None: @@ -882,8 +890,17 @@ class DsInstance(service.Service): nickname = self.cacert_name cert = dsdb.get_cert_from_db(nickname, pem=False) + cacert_flags = trust_flags[nickname] + if self.setup_pkinit: + cacert_flags = TrustFlags( + cacert_flags.has_key, + cacert_flags.trusted, + cacert_flags.ca, + (cacert_flags.usages | + {x509.EKU_PKINIT_CLIENT_AUTH, x509.EKU_PKINIT_KDC}), + ) certstore.put_ca_cert_nss(conn, self.suffix, cert, nickname, - trust_flags[nickname], + cacert_flags, config_ipa=self.ca_is_configured, config_compat=self.master_fqdn is None) diff --git a/ipaserver/install/plugins/upload_cacrt.py b/ipaserver/install/plugins/upload_cacrt.py index 73cc91d..a1957ca 100644 --- a/ipaserver/install/plugins/upload_cacrt.py +++ b/ipaserver/install/plugins/upload_cacrt.py @@ -79,7 +79,11 @@ class update_upload_cacrt(Updater): try: ldap.add_entry(entry) except errors.DuplicateEntry: - pass + if nickname == ca_nickname and ca_enabled: + try: + ldap.update_entry(entry) + except errors.EmptyModlist: + pass if ca_cert: dn = DN(('cn', 'CACert'), ('cn', 'ipa'), ('cn','etc'), diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py index 0ce60e9..25c21db 100644 --- a/ipaserver/install/server/install.py +++ b/ipaserver/install/server/install.py @@ -737,7 +737,8 @@ def install(installer): idstart=options.idstart, idmax=options.idmax, subject_base=options.subject_base, ca_subject=options.ca_subject, - hbac_allow=not options.no_hbac_allow) + hbac_allow=not options.no_hbac_allow, + setup_pkinit=not options.no_pkinit) else: ds = dsinstance.DsInstance(fstore=fstore, domainlevel=options.domainlevel, @@ -748,7 +749,8 @@ def install(installer): idstart=options.idstart, idmax=options.idmax, subject_base=options.subject_base, ca_subject=options.ca_subject, - hbac_allow=not options.no_hbac_allow) + hbac_allow=not options.no_hbac_allow, + setup_pkinit=not options.no_pkinit) ntpinstance.ntp_ldap_enable(host_name, ds.suffix, realm_name) @@ -759,7 +761,8 @@ def install(installer): installer._ds = ds ds.init_info( realm_name, host_name, domain_name, dm_password, - options.subject_base, options.ca_subject, 1101, 1100, None) + options.subject_base, options.ca_subject, 1101, 1100, None, + setup_pkinit=not options.no_pkinit) krb = krbinstance.KrbInstance(fstore) if not options.external_cert_files: diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py index fb738cb..c19edce 100644 --- a/ipaserver/install/server/replicainstall.py +++ b/ipaserver/install/server/replicainstall.py @@ -107,6 +107,7 @@ def install_replica_ds(config, options, ca_is_configured, remote_api, ca_file=ca_file, promote=promote, # we need promote because of replication setup api=remote_api, + setup_pkinit=not options.no_pkinit, ) return ds