summaryrefslogtreecommitdiffstats
path: root/ipaserver/install
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2016-07-26 11:19:01 -0400
committerJan Cholasta <jcholast@redhat.com>2016-12-12 13:39:44 +0100
commitca4e6c1fdfac9b545b26f885dc4865f22ca36ae6 (patch)
tree92b2245b68b343440591e47f82e4898d48c07c2e /ipaserver/install
parent32b1743e5fb318b226a602ec8d9a4b6ef2a25c9d (diff)
downloadfreeipa-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.py2
-rw-r--r--ipaserver/install/certs.py10
-rw-r--r--ipaserver/install/dsinstance.py2
-rw-r--r--ipaserver/install/httpinstance.py2
-rw-r--r--ipaserver/install/krbinstance.py62
-rw-r--r--ipaserver/install/server/__init__.py4
-rw-r--r--ipaserver/install/server/install.py21
-rw-r--r--ipaserver/install/server/replicainstall.py4
-rw-r--r--ipaserver/install/server/upgrade.py35
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)