diff options
author | Simo Sorce <simo@redhat.com> | 2016-07-26 11:19:01 -0400 |
---|---|---|
committer | Jan Cholasta <jcholast@redhat.com> | 2016-12-12 13:39:44 +0100 |
commit | ca4e6c1fdfac9b545b26f885dc4865f22ca36ae6 (patch) | |
tree | 92b2245b68b343440591e47f82e4898d48c07c2e /ipaserver/install | |
parent | 32b1743e5fb318b226a602ec8d9a4b6ef2a25c9d (diff) | |
download | freeipa-ca4e6c1fdfac9b545b26f885dc4865f22ca36ae6.tar.gz freeipa-ca4e6c1fdfac9b545b26f885dc4865f22ca36ae6.tar.xz freeipa-ca4e6c1fdfac9b545b26f885dc4865f22ca36ae6.zip |
Configure Anonymous PKINIT on server install
Allow anonymous pkinit to be used so that unenrolled hosts can perform FAST
authentication (necessary for 2FA for example) using an anonymous krbtgt
obtained via Pkinit.
https://fedorahosted.org/freeipa/ticket/5678
Signed-off-by: Simo Sorce <simo@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
Diffstat (limited to 'ipaserver/install')
-rw-r--r-- | ipaserver/install/cainstance.py | 2 | ||||
-rw-r--r-- | ipaserver/install/certs.py | 10 | ||||
-rw-r--r-- | ipaserver/install/dsinstance.py | 2 | ||||
-rw-r--r-- | ipaserver/install/httpinstance.py | 2 | ||||
-rw-r--r-- | ipaserver/install/krbinstance.py | 62 | ||||
-rw-r--r-- | ipaserver/install/server/__init__.py | 4 | ||||
-rw-r--r-- | ipaserver/install/server/install.py | 21 | ||||
-rw-r--r-- | ipaserver/install/server/replicainstall.py | 4 | ||||
-rw-r--r-- | ipaserver/install/server/upgrade.py | 35 |
9 files changed, 109 insertions, 33 deletions
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py index 29acd7e27..c7e81f085 100644 --- a/ipaserver/install/cainstance.py +++ b/ipaserver/install/cainstance.py @@ -817,7 +817,7 @@ class CAInstance(DogtagInstance): # The certificate must be requested using caServerCert profile # because this profile does not require agent authentication reqId = certmonger.request_and_wait_for_cert( - nssdb=self.ra_agent_db, + certpath=self.ra_agent_db, nickname='ipaCert', principal='host/%s' % self.fqdn, passwd_fname=self.ra_agent_pwd, diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py index 45602baa6..02b03d48b 100644 --- a/ipaserver/install/certs.py +++ b/ipaserver/install/certs.py @@ -633,7 +633,13 @@ class CertDB(object): def install_pem_from_p12(self, p12_fname, p12_passwd, pem_fname): pwd = ipautil.write_tmp_file(p12_passwd) - ipautil.run([paths.OPENSSL, "pkcs12", "-nodes", + ipautil.run([paths.OPENSSL, "pkcs12", "-nokeys", + "-in", p12_fname, "-out", pem_fname, + "-passin", "file:" + pwd.name]) + + def install_key_from_p12(self, p12_fname, p12_passwd, pem_fname): + pwd = ipautil.write_tmp_file(p12_passwd) + ipautil.run([paths.OPENSSL, "pkcs12", "-nodes", "-nocerts", "-in", p12_fname, "-out", pem_fname, "-passin", "file:" + pwd.name]) @@ -647,7 +653,7 @@ class CertDB(object): def request_service_cert(self, nickname, principal, host, pwdconf=False): if pwdconf: self.create_password_conf() - certmonger.request_and_wait_for_cert(nssdb=self.secdir, + certmonger.request_and_wait_for_cert(certpath=self.secdir, nickname=nickname, principal=principal, subject=host, diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index 1be5ac73c..bcfcb0500 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -816,7 +816,7 @@ class DsInstance(service.Service): try: cmd = 'restart_dirsrv %s' % self.serverid certmonger.request_and_wait_for_cert( - nssdb=dirname, + certpath=dirname, nickname=self.nickname, principal=self.principal, passwd_fname=dsdb.passwd_fname, diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py index 15c310780..b7ce857ed 100644 --- a/ipaserver/install/httpinstance.py +++ b/ipaserver/install/httpinstance.py @@ -376,7 +376,7 @@ class HTTPInstance(service.Service): try: certmonger.request_and_wait_for_cert( - nssdb=db.secdir, + certpath=db.secdir, nickname=self.cert_nickname, principal=self.principal, passwd_fname=db.passwd_fname, diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py index 8de92f764..b52b0c3f9 100644 --- a/ipaserver/install/krbinstance.py +++ b/ipaserver/install/krbinstance.py @@ -24,6 +24,7 @@ import shutil import os import pwd import socket +import dbus import dns.name @@ -32,6 +33,7 @@ from ipaserver.install import installutils from ipapython import ipautil from ipapython import kernel_keyring from ipalib import api +from ipalib.install import certmonger from ipapython.ipa_log_manager import root_logger from ipapython.dn import DN @@ -153,12 +155,14 @@ class KrbInstance(service.Service): self.step("creating a keytab for the directory", self.__create_ds_keytab) self.step("creating a keytab for the machine", self.__create_host_keytab) self.step("adding the password extension to the directory", self.__add_pwd_extop_module) - if setup_pkinit: - self.step("creating X509 Certificate for PKINIT", self.__setup_pkinit) - self.step("creating principal for anonymous PKINIT", self.__add_anonymous_pkinit_principal) + self.step("creating anonymous principal", self.add_anonymous_principal) self.__common_post_setup() + if setup_pkinit: + self.step("installing X509 Certificate for PKINIT", + self.setup_pkinit) + self.start_creation(runtime=30) self.kpasswd = KpasswdInstance() @@ -179,7 +183,8 @@ class KrbInstance(service.Service): self.step("configuring KDC", self.__configure_instance) self.step("adding the password extension to the directory", self.__add_pwd_extop_module) if setup_pkinit: - self.step("installing X509 Certificate for PKINIT", self.__setup_pkinit) + self.step("installing X509 Certificate for PKINIT", + self.setup_pkinit) self.__common_post_setup() @@ -214,7 +219,8 @@ class KrbInstance(service.Service): KRB5KDC_KADM5_ACL=paths.KRB5KDC_KADM5_ACL, DICT_WORDS=paths.DICT_WORDS, KRB5KDC_KADM5_KEYTAB=paths.KRB5KDC_KADM5_KEYTAB, - KDC_PEM=paths.KDC_PEM, + KDC_CERT=paths.KDC_CERT, + KDC_KEY=paths.KDC_KEY, CACERT_PEM=paths.CACERT_PEM) # IPA server/KDC is not a subdomain of default domain @@ -338,31 +344,50 @@ class KrbInstance(service.Service): self.move_service_to_host(host_principal) - def __setup_pkinit(self): + def setup_pkinit(self): ca_db = certs.CertDB(self.realm, host_name=self.fqdn, subject_base=self.subject_base) if self.pkcs12_info: ca_db.install_pem_from_p12(self.pkcs12_info[0], self.pkcs12_info[1], - paths.KDC_PEM) + paths.KDC_CERT) + ca_db.install_key_from_p12(self.pkcs12_info[0], + self.pkcs12_info[1], + paths.KDC_KEY) else: - raise RuntimeError("PKI not supported yet\n") + subject = str(DN(('cn', self.fqdn), self.subject_base)) + krbtgt = "krbtgt/" + self.realm + "@" + self.realm + certpath = (paths.KDC_CERT, paths.KDC_KEY) + try: + reqid = certmonger.request_cert(certpath, u'KDC-Cert', + subject, krbtgt, + dns=self.fqdn, storage='FILE', + profile='KDCs_PKINIT_Certs') + except dbus.DBusException as e: + # if the certificate is already tracked, ignore the error + name = e.get_dbus_name() + if name != 'org.fedorahosted.certmonger.duplicate': + root_logger.error("Failed to initiate the request: %s", e) + return + + try: + certmonger.wait_for_request(reqid) + except RuntimeError as e: + root_logger.error("Failed to wait for request: %s", e) # Finally copy the cacert in the krb directory so we don't # have any selinux issues with the file context shutil.copyfile(paths.IPA_CA_CRT, paths.CACERT_PEM) - def __add_anonymous_pkinit_principal(self): + def get_anonymous_principal_name(self): princ = "WELLKNOWN/ANONYMOUS" - princ_realm = "%s@%s" % (princ, self.realm) + return "%s@%s" % (princ, self.realm) + def add_anonymous_principal(self): # Create the special anonymous principal + princ_realm = self.get_anonymous_principal_name() installutils.kadmin_addprinc(princ_realm) - dn = DN(('krbprincipalname', princ_realm), self.get_realm_suffix()) - entry = api.Backend.ldap2.get_entry(dn) - entry['nsAccountlock'] = ['TRUE'] - api.Backend.ldap2.update_entry(entry) def __convert_to_gssapi_replication(self): repl = replication.ReplicationManager(self.realm, @@ -372,6 +397,9 @@ class KrbInstance(service.Service): r_binddn=DN(('cn', 'Directory Manager')), r_bindpw=self.dm_password) + def stop_tracking_certs(self): + certmonger.stop_tracking(certfile=paths.KDC_CERT) + def uninstall(self): if self.is_configured(): self.print_msg("Unconfiguring %s" % self.service_name) @@ -394,6 +422,12 @@ class KrbInstance(service.Service): if enabled: self.enable() + # stop tracking and remove certificates + self.stop_tracking_certs() + installutils.remove_file(paths.CACERT_PEM) + installutils.remove_file(paths.KDC_CERT) + installutils.remove_file(paths.KDC_KEY) + if running: self.restart() diff --git a/ipaserver/install/server/__init__.py b/ipaserver/install/server/__init__.py index 0237702cc..28cdd066a 100644 --- a/ipaserver/install/server/__init__.py +++ b/ipaserver/install/server/__init__.py @@ -501,8 +501,8 @@ class ServerInstallInterface(client.ClientInstallInterface, "You must specify at least one of --forwarder, " "--auto-forwarders, or --no-forwarders options") - # Automatically disable pkinit w/ dogtag until that is supported - self.no_pkinit = True + # Automatically enable pkinit w/ dogtag + self.no_pkinit = not self.setup_ca ServerMasterInstallInterface = installs_master(ServerInstallInterface) diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py index f81c202cc..b5b9cb48a 100644 --- a/ipaserver/install/server/install.py +++ b/ipaserver/install/server/install.py @@ -521,6 +521,11 @@ def install_check(installer): dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin) if options.pkinit_cert_files: + if not options.no_pkinit: + raise ScriptError("Cannot create KDC PKINIT certificate and use " + "provided external PKINIT certificate at the " + "same time. Please choose one of them.") + if options.pkinit_pin is None: options.pkinit_pin = read_password( "Enter Kerberos KDC private key unlock", @@ -792,17 +797,11 @@ def install(installer): ds.enable_ssl() krb = krbinstance.KrbInstance(fstore) - if options.pkinit_cert_files: - krb.create_instance(realm_name, host_name, domain_name, - dm_password, master_password, - setup_pkinit=not options.no_pkinit, - pkcs12_info=pkinit_pkcs12_info, - subject_base=options.subject) - else: - krb.create_instance(realm_name, host_name, domain_name, - dm_password, master_password, - setup_pkinit=not options.no_pkinit, - subject_base=options.subject) + krb.create_instance(realm_name, host_name, domain_name, + dm_password, master_password, + setup_pkinit=not options.no_pkinit, + pkcs12_info=pkinit_pkcs12_info, + subject_base=options.subject) # restart DS to enable ipa-pwd-extop plugin print("Restarting directory server to enable password extension plugin") diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py index 06d209e23..b0cf28f0f 100644 --- a/ipaserver/install/server/replicainstall.py +++ b/ipaserver/install/server/replicainstall.py @@ -124,7 +124,9 @@ def install_krb(config, setup_pkinit=False, promote=False): krb.create_replica(config.realm_name, config.master_host_name, config.host_name, config.domain_name, config.dirman_password, - setup_pkinit, pkcs12_info, promote=promote) + setup_pkinit, pkcs12_info, + subject_base=config.subject_base, + promote=promote) return krb diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py index 245450701..0ebe9af24 100644 --- a/ipaserver/install/server/upgrade.py +++ b/ipaserver/install/server/upgrade.py @@ -47,6 +47,7 @@ from ipaserver.install import sysupgrade from ipaserver.install import dnskeysyncinstance from ipaserver.install import krainstance from ipaserver.install import dogtaginstance +from ipaserver.install import krbinstance from ipaserver.install.upgradeinstance import IPAUpgrade from ipaserver.install.ldapupdate import BadSyntax @@ -1492,6 +1493,20 @@ def add_default_caacl(ca): sysupgrade.set_upgrade_state('caacl', 'add_default_caacl', True) +def enable_anonymous_principal(krb): + princ_realm = krb.get_anonymous_principal_name() + dn = DN(('krbprincipalname', princ_realm), krb.get_realm_suffix()) + try: + _ = api.Backend.ldap2.get_entry(dn) # pylint: disable=unused-variable + except ipalib.errors.NotFound: + krb.add_anonymous_principal() + + try: + api.Backend.ldap2.set_entry_active(dn, True) + except ipalib.errors.AlreadyActive: + pass + + def upgrade_configuration(): """ Execute configuration upgrade of the IPA services @@ -1735,6 +1750,26 @@ def upgrade_configuration(): set_sssd_domain_option('ipa_server_mode', 'True') + krb = krbinstance.KrbInstance(fstore) + krb.fqdn = fqdn + krb.realm = api.env.realm + krb.suffix = ipautil.realm_to_suffix(krb.realm) + krb.subject_base = subject_base + if not os.path.exists(paths.KDC_CERT): + krb.setup_pkinit() + replacevars = dict() + replacevars['pkinit_identity'] = 'FILE:{},{}'.format( + paths.KDC_CERT,paths.KDC_KEY) + appendvars = {} + ipautil.backup_config_and_replace_variables( + fstore, paths.KRB5KDC_KDC_CONF, replacevars=replacevars, + appendvars=appendvars) + tasks.restore_context(paths.KRB5KDC_KDC_CONF) + if krb.is_running(): + krb.stop() + krb.start() + enable_anonymous_principal(krb) + if not ds_running: ds.stop(ds_serverid) |