URL: https://github.com/freeipa/freeipa/pull/694
Author: martbab
 Title: #694: RFC: implement local PKINIT deployment in server/replica install
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/694/head:pr694
git checkout pr694
From 7dfa337769079d6f4247aa7306abdc0401b38dd6 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Fri, 31 Mar 2017 15:06:46 +0200
Subject: [PATCH 1/8] Allow for configuration of all three PKINIT variants when
 deploying KDC

The PKINIT setup code now can configure PKINIT using IPA CA signed
certificate, 3rd party certificate and local PKINIT with self-signed
keypair. The local PKINIT is also selected as a fallback mechanism if
the CSR is rejected by CA master.

http://www.freeipa.org/page/V4/Kerberos_PKINIT
https://pagure.io/freeipa/issue/6830
---
 ipaserver/install/krbinstance.py | 127 +++++++++++++++++++++++++--------------
 1 file changed, 81 insertions(+), 46 deletions(-)

diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
index 6c105f7..c3d56dc 100644
--- a/ipaserver/install/krbinstance.py
+++ b/ipaserver/install/krbinstance.py
@@ -38,6 +38,7 @@
 from ipalib.install import certmonger
 from ipapython.ipa_log_manager import root_logger
 from ipapython.dn import DN
+from ipapython.dogtag import KDC_PROFILE
 
 from ipaserver.install import replication
 from ipaserver.install import ldapupdate
@@ -354,55 +355,86 @@ def _wait_for_replica_kdc_entry(self):
             remote_ldap.gssapi_bind()
             replication.wait_for_entry(remote_ldap, kdc_dn, timeout=60)
 
+    def _call_certmonger(self, certmonger_ca='IPA'):
+        subject = str(DN(('cn', self.fqdn), self.subject_base))
+        krbtgt = "krbtgt/" + self.realm + "@" + self.realm
+        certpath = (paths.KDC_CERT, paths.KDC_KEY)
+
+        try:
+            prev_helper = None
+            # on the first CA-ful master without '--no-pkinit', we issue the
+            # certificate by contacting Dogtag directly
+            use_dogtag_submit = all(
+                [self.master_fqdn is None,
+                 self.pkcs12_info is None,
+                 self.config_pkinit])
+
+            if use_dogtag_submit:
+                ca_args = [
+                    paths.CERTMONGER_DOGTAG_SUBMIT,
+                    '--ee-url', 'https://%s:8443/ca/ee/ca' % self.fqdn,
+                    '--certfile', paths.RA_AGENT_PEM,
+                    '--keyfile', paths.RA_AGENT_KEY,
+                    '--cafile', paths.IPA_CA_CRT,
+                    '--agent-submit'
+                ]
+                helper = " ".join(ca_args)
+                prev_helper = certmonger.modify_ca_helper(certmonger_ca, helper)
+
+            certmonger.request_and_wait_for_cert(
+                certpath,
+                subject,
+                krbtgt,
+                ca=certmonger_ca,
+                dns=self.fqdn,
+                storage='FILE',
+                profile=KDC_PROFILE)
+        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
+        finally:
+            if prev_helper is not None:
+                certmonger.modify_ca_helper(certmonger_ca, prev_helper)
+
+    def setup_local_pkinit(self):
+        self._call_certmonger(certmonger_ca="SelfSign")
+        # for self-signed certificate, the certificate is its own CA, copy it
+        # as CA cert
+        shutil.copyfile(paths.KDC_CERT, paths.CACERT_PEM)
+
+    def setup_full_pkinit(self):
+        try:
+            self._call_certmonger()
+            shutil.copyfile(paths.IPA_CA_CRT, paths.CACERT_PEM)
+        except RuntimeError as e:
+            root_logger.error("PKINIT certificate request failed: %s", e)
+            root_logger.error("Falling back to local PKINIT with self-signed "
+                              "certificate")
+            self.stop_tracking_certs()
+            self.setup_local_pkinit()
+
+    def setup_external_pkinit(self):
+        certs.install_pem_from_p12(self.pkcs12_info[0],
+                                   self.pkcs12_info[1],
+                                   paths.KDC_CERT)
+        certs.install_key_from_p12(self.pkcs12_info[0],
+                                   self.pkcs12_info[1],
+                                   paths.KDC_KEY)
+        shutil.copyfile(paths.IPA_CA_CRT, paths.CACERT_PEM)
+
     def setup_pkinit(self):
+        if self.master_fqdn is not None:
+            self._wait_for_replica_kdc_entry()
+
         if self.pkcs12_info:
-            certs.install_pem_from_p12(self.pkcs12_info[0],
-                                       self.pkcs12_info[1],
-                                       paths.KDC_CERT)
-            certs.install_key_from_p12(self.pkcs12_info[0],
-                                       self.pkcs12_info[1],
-                                       paths.KDC_KEY)
+            self.setup_external_pkinit()
+        elif self.config_pkinit:
+            self.setup_full_pkinit()
         else:
-            subject = str(DN(('cn', self.fqdn), self.subject_base))
-            krbtgt = "krbtgt/" + self.realm + "@" + self.realm
-            certpath = (paths.KDC_CERT, paths.KDC_KEY)
-
-            try:
-                prev_helper = None
-                if self.master_fqdn is None:
-                    ca_args = [
-                        paths.CERTMONGER_DOGTAG_SUBMIT,
-                        '--ee-url', 'https://%s:8443/ca/ee/ca' % self.fqdn,
-                        '--certfile', paths.RA_AGENT_PEM,
-                        '--keyfile', paths.RA_AGENT_KEY,
-                        '--cafile', paths.IPA_CA_CRT,
-                        '--agent-submit'
-                    ]
-                    helper = " ".join(ca_args)
-                    prev_helper = certmonger.modify_ca_helper('IPA', helper)
-                else:
-                    self._wait_for_replica_kdc_entry()
-
-                certmonger.request_and_wait_for_cert(
-                    certpath,
-                    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
-            finally:
-                if prev_helper is not None:
-                    certmonger.modify_ca_helper('IPA', prev_helper)
-
-        # 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)
+            self.setup_local_pkinit()
 
         try:
             self.restart()
@@ -425,6 +457,9 @@ def enable_ssl(self):
             self.step("testing anonymous PKINIT", self.test_anonymous_pkinit)
 
             self.start_creation()
+        else:
+            self.setup_pkinit()
+            self.test_anonymous_pkinit()
 
     def get_anonymous_principal_name(self):
         return "%s@%s" % (ANON_USER, self.realm)

From c88a1d111d66cc5a289682319f893e998e22dbc7 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Fri, 31 Mar 2017 14:44:29 +0200
Subject: [PATCH 2/8] API for retrieval of master's PKINIT status and
 publishing it in LDAP

An API was added to retrieve PKINIT status and store it in master's KDC
entry during configuration. The PKINIT feature can have the following
states:
   * full PKINIT: PKINIT certificate was issued by IPA CA and all
     clients with IPA CA configured as PKINIT trust anchor will be able
     to perform PKINIT and request anonymous TGT from this KDC
   * external PKINIT: the PKINIT certificate was provided by a 3rd party
     in a PKCS#12 bundle and all clients that have its root CA as anchor
     can request TGTs by PKINIT
   * local PKINIT: PKINIT certificate was self-signed by KDC's private
     key. This is a fallback mechanism usable only locally on the master
     hosting the KDC. Its intended use is to provide FAST armoring for
     password authenticated requests (e.g. WebUI logins)

See http://www.freeipa.org/page/V4/Kerberos_PKINIT#Configuration for
more details.

https://pagure.io/freeipa/issue/6830
---
 ipaserver/install/krbinstance.py | 81 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
index c3d56dc..f98b0a9 100644
--- a/ipaserver/install/krbinstance.py
+++ b/ipaserver/install/krbinstance.py
@@ -48,6 +48,85 @@
 from ipaplatform.tasks import tasks
 from ipaplatform.paths import paths
 
+PKINIT_STATUS = 'pkinitStatus'
+PKINIT_LOCAL = 'local'
+PKINIT_EXTERNAL = 'external'
+PKINIT_FULL = 'full'
+
+
+def get_pkinit_request_ca():
+    """
+    Return the certmonger CA name which is serving the PKINIT certificate
+    request. If the certificate is not tracked by Certmonger, return None
+    """
+    pkinit_request_id = certmonger.get_request_id(
+        {'cert-file': paths.KDC_CERT})
+
+    if pkinit_request_id is None:
+        return
+
+    return certmonger.get_request_value(pkinit_request_id, 'ca-name')
+
+
+def get_local_pkinit_state():
+    """
+    Get the PKINIT feature status locally from the presence of KDC certificate
+    and certmonger tracking status
+    :returns: PKINIT status (local, external, full) or None if the feature is
+        not configured
+    """
+
+    if not os.path.exists(paths.KDC_CERT):
+        return
+
+    pkinit_request_ca = get_pkinit_request_ca()
+
+    if pkinit_request_ca is None:
+        return PKINIT_EXTERNAL
+
+    if pkinit_request_ca == "IPA":
+        return PKINIT_FULL
+    elif pkinit_request_ca == "SelfSign":
+        return PKINIT_LOCAL
+    else:
+        raise ValueError(
+            "Unrecognized certmonger CA: {}".format(pkinit_request_ca))
+
+
+def record_pkinit_state_ldap(_api):
+    """
+    record PKINIT state in the master's KDC entry in LDAP. The state is
+    recorded in ipaConfigString attribute as a 'pkinit_status:STATUS' where
+    STATUS is one of (local, external, full).
+
+    Previous value of the pkinit_status will be overwritten
+
+    :param _api: IPA API instance with established LDAP connection
+    """
+    local_state = get_local_pkinit_state()
+
+    if local_state is None:
+        raise RuntimeError("PKINIT is not configured on this master")
+
+    hostname = _api.env.host
+    ldap2 = _api.Backend.ldap2
+
+    master_dn = _api.Object.server.get_dn_if_exists(hostname)
+    master_kdc_dn = DN(('cn', 'KDC'), master_dn)
+    kdc_entry = ldap2.get_entry(master_kdc_dn)
+
+    ipa_config_string = {
+        v for v in kdc_entry.get('ipaConfigString', [])
+        if not v.lower().startswith(PKINIT_STATUS.lower())
+    }
+
+    ipa_config_string.add('{} {}'.format(PKINIT_STATUS, local_state))
+
+    kdc_entry['ipaConfigString'] = list(ipa_config_string)
+
+    ldap2.update_entry(kdc_entry)
+
+
 class KpasswdInstance(service.SimpleServiceInstance):
     def __init__(self):
         service.SimpleServiceInstance.__init__(self, "kadmin")
@@ -442,6 +521,8 @@ def setup_pkinit(self):
             root_logger.critical("krb5kdc service failed to restart")
             raise
 
+        record_pkinit_state_ldap(self.api)
+
     def test_anonymous_pkinit(self):
         with ipautil.private_ccache() as anon_ccache:
             try:

From 069f49737c60f3a30961fc530573d8808576b508 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Fri, 31 Mar 2017 14:14:11 +0200
Subject: [PATCH 3/8] Use only anonymous PKINIT to fetch armor ccache

Since the anonymous principal can only use PKINIT to fetch credential
cache it makes no sense to try and use its kerberos key to establish
FAST channel.

We should also be able to use custom PKINIT anchor for the armoring.

https://pagure.io/freeipa/issue/6830
---
 ipalib/install/kinit.py | 30 +++++++++++++-----------------
 1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/ipalib/install/kinit.py b/ipalib/install/kinit.py
index 1e4d1a8..fb6caee 100644
--- a/ipalib/install/kinit.py
+++ b/ipalib/install/kinit.py
@@ -7,7 +7,6 @@
 
 import gssapi
 
-from ipalib.constants import ANON_USER
 from ipaplatform.paths import paths
 from ipapython.ipa_log_manager import root_logger
 from ipapython.ipautil import run
@@ -97,29 +96,26 @@ def kinit_password(principal, password, ccache_name, config=None,
         raise RuntimeError(result.error_output)
 
 
-def kinit_armor(ccache_name):
+def kinit_armor(ccache_name, pkinit_anchor=None):
     """
-    perform kinit to obtain anonymous ticket to be used as armor for FAST.
+    perform anonymous pkinit to obtain anonymous ticket to be used as armor
+    for FAST.
+
+    :param ccache_name: location of the armor ccache
+    :param pkinit_anchor: if not None, the location of PKINIT anchor file to
+        use. Otherwise the value from Kerberos client library configuration is
+        used
+
+    :raises: CalledProcessError if the anonymous PKINIT fails
     """
     root_logger.debug("Initializing anonymous ccache")
 
     env = {'LC_ALL': 'C'}
-    # try with the keytab first and then again fallback to try with pkinit in
-    # case someone decided it is fun to remove Anonymous keys from the entry
-    # or in future pkinit enabled principal enforce the use of pkinit
-    try:
-        # Gssapi does not understand anonymous cred use kinit command instead
-        args = [paths.KINIT, '-k', '-t', paths.ANON_KEYTAB,
-                ANON_USER, '-c', ccache_name]
-        run(args, env=env, raiseonerr=True, capture_error=True)
-        return
-    except Exception as e:
-        root_logger.debug("Failed to init Anonymous keytab: %s", e,
-                          exc_info=True)
-
-    root_logger.debug("Fallback to slower Anonymous PKINIT")
     args = [paths.KINIT, '-n', '-c', ccache_name]
 
+    if pkinit_anchor is not None:
+        args.extend(['-X', 'X509_anchors=FILE:{}'.format(pkinit_anchor)])
+
     # this workaround enables us to capture stderr and put it
     # into the raised exception in case of unsuccessful authentication
     run(args, env=env, raiseonerr=True, capture_error=True)

From fa81aacbe0e48e0f53e550a6f1be4e44dc9da21b Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Wed, 5 Apr 2017 17:29:26 +0200
Subject: [PATCH 4/8] Stop requesting anonymous keytab and purge all references
 of it

anonymous kinit using keytab never worked so we may safely remove all
code that requests/uses it.

https://pagure.io/freeipa/issue/6830
---
 ipaplatform/base/paths.py           |  1 -
 ipaserver/install/httpinstance.py   | 17 -----------------
 ipaserver/install/ipa_backup.py     |  1 -
 ipaserver/install/server/upgrade.py |  1 -
 4 files changed, 20 deletions(-)

diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
index 9cf160f..1908dda 100644
--- a/ipaplatform/base/paths.py
+++ b/ipaplatform/base/paths.py
@@ -50,7 +50,6 @@ class BasePathNamespace(object):
     HTTPD_SSL_CONF = "/etc/httpd/conf.d/ssl.conf"
     OLD_IPA_KEYTAB = "/etc/httpd/conf/ipa.keytab"
     HTTP_KEYTAB = "/var/lib/ipa/gssproxy/http.keytab"
-    ANON_KEYTAB = "/var/lib/ipa/api/anon.keytab"
     HTTPD_PASSWORD_CONF = "/etc/httpd/conf/password.conf"
     IDMAPD_CONF = "/etc/idmapd.conf"
     ETC_IPA = "/etc/ipa"
diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
index 079ea92..445b809 100644
--- a/ipaserver/install/httpinstance.py
+++ b/ipaserver/install/httpinstance.py
@@ -30,7 +30,6 @@
 
 import six
 
-from ipalib.constants import IPAAPI_USER
 from ipalib.install import certmonger
 from ipaserver.install import service
 from ipaserver.install import certs
@@ -43,7 +42,6 @@
 from ipaserver.install import sysupgrade
 from ipalib import api
 from ipalib import errors
-from ipalib.constants import ANON_USER
 from ipaplatform.constants import constants
 from ipaplatform.tasks import tasks
 from ipaplatform.paths import paths
@@ -170,7 +168,6 @@ def create_instance(self, realm, fqdn, domain_name, pkcs12_info=None,
         self.step("adding URL rewriting rules", self.__add_include)
         self.step("configuring httpd", self.__configure_http)
         self.step("setting up httpd keytab", self.request_service_keytab)
-        self.step("retrieving anonymous keytab", self.request_anon_keytab)
         self.step("configuring Gssproxy", self.configure_gssproxy)
         self.step("setting up ssl", self.__setup_ssl)
         if self.ca_is_configured:
@@ -317,20 +314,6 @@ def configure_certmonger_renewal_guard(self):
             if certmonger_stopped:
                 certmonger.stop()
 
-    def request_anon_keytab(self):
-        parent = os.path.dirname(paths.ANON_KEYTAB)
-        if not os.path.exists(parent):
-            os.makedirs(parent, 0o755)
-
-        self.clean_previous_keytab(keytab=paths.ANON_KEYTAB)
-        self.run_getkeytab(self.api.env.ldap_uri, paths.ANON_KEYTAB, ANON_USER)
-
-        pent = pwd.getpwnam(IPAAPI_USER)
-        os.chmod(parent, 0o700)
-        os.chown(parent, pent.pw_uid, pent.pw_gid)
-
-        self.set_keytab_owner(keytab=paths.ANON_KEYTAB, owner=IPAAPI_USER)
-
     def create_password_conf(self):
         """
         This is the format of mod_nss pin files.
diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py
index f71a40b..40f08d7 100644
--- a/ipaserver/install/ipa_backup.py
+++ b/ipaserver/install/ipa_backup.py
@@ -120,7 +120,6 @@ class Backup(admintool.AdminTool):
     )
 
     files = (
-        paths.ANON_KEYTAB,
         paths.NAMED_CONF,
         paths.NAMED_KEYTAB,
         paths.RESOLV_CONF,
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index 25b8629..e736d78 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -1796,7 +1796,6 @@ def upgrade_configuration():
                         KDC_KEY=paths.KDC_KEY,
                         CACERT_PEM=paths.CACERT_PEM)
     krb.add_anonymous_principal()
-    http.request_anon_keytab()
     setup_pkinit(krb)
 
     if not ds_running:

From 888866949c913e866026d2c2a2ec8f0fe9f35009 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Wed, 5 Apr 2017 15:59:24 +0200
Subject: [PATCH 5/8] test out anonymous PKINIT only when the master is fully
 configured

this is to ensure that we are talking only to our own KDC and not to KDC
on remote master that may not support (local) PKINIT functionality and
cause errors.

https://pagure.io/freeipa/issue/6817
---
 ipaserver/install/krbinstance.py           | 3 ---
 ipaserver/install/server/install.py        | 4 ++++
 ipaserver/install/server/replicainstall.py | 4 ++++
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
index f98b0a9..f0ed85b 100644
--- a/ipaserver/install/krbinstance.py
+++ b/ipaserver/install/krbinstance.py
@@ -535,12 +535,9 @@ def enable_ssl(self):
             self.steps = []
             self.step("installing X509 Certificate for PKINIT",
                       self.setup_pkinit)
-            self.step("testing anonymous PKINIT", self.test_anonymous_pkinit)
-
             self.start_creation()
         else:
             self.setup_pkinit()
-            self.test_anonymous_pkinit()
 
     def get_anonymous_principal_name(self):
         return "%s@%s" % (ANON_USER, self.realm)
diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py
index d7eb0bf..2228d4d 100644
--- a/ipaserver/install/server/install.py
+++ b/ipaserver/install/server/install.py
@@ -892,6 +892,10 @@ def install(installer):
     # Make sure the files we crated in /var/run are recreated at startup
     tasks.configure_tmpfiles()
 
+    if not options.no_pkinit:
+        print("Testing anonymous PKINIT")
+    krb.test_anonymous_pkinit()
+
     # Everything installed properly, activate ipa service.
     services.knownservices.ipa.enable()
 
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
index f489e69..03c2b58 100644
--- a/ipaserver/install/server/replicainstall.py
+++ b/ipaserver/install/server/replicainstall.py
@@ -1525,6 +1525,10 @@ def install(installer):
         # remove the extracted replica file
         remove_replica_info_dir(installer)
 
+    if not options.no_pkinit:
+        print("Testing anonymous PKINIT")
+    krb.test_anonymous_pkinit()
+
     # Everything installed properly, activate ipa service.
     services.knownservices.ipa.enable()
 

From 0a1dae54f0d2d07c4a70e1b403ea0ecdf87e88a2 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Fri, 31 Mar 2017 15:15:28 +0200
Subject: [PATCH 6/8] Use local anchor when testing out PKINIT configuration

The PKINIT configuration can use a different anchor than the one
specified in the Kerberos config file. We should always use KDC's anchor
on master to avoid false positive errors.

https://pagure.io/freeipa/issue/6830
---
 ipaserver/install/krbinstance.py | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
index f0ed85b..2ea77e8 100644
--- a/ipaserver/install/krbinstance.py
+++ b/ipaserver/install/krbinstance.py
@@ -36,6 +36,7 @@
 from ipalib import api, errors
 from ipalib.constants import ANON_USER
 from ipalib.install import certmonger
+from ipalib.install.kinit import kinit_armor
 from ipapython.ipa_log_manager import root_logger
 from ipapython.dn import DN
 from ipapython.dogtag import KDC_PROFILE
@@ -526,9 +527,10 @@ def setup_pkinit(self):
     def test_anonymous_pkinit(self):
         with ipautil.private_ccache() as anon_ccache:
             try:
-                ipautil.run([paths.KINIT, '-n', '-c', anon_ccache])
-            except ipautil.CalledProcessError:
-                raise RuntimeError("Failed to configure anonymous PKINIT")
+                kinit_armor(anon_ccache, pkinit_anchor=paths.CACERT_PEM)
+            except ipautil.CalledProcessError as e:
+                raise RuntimeError(
+                    "Failed to configure anonymous PKINIT: {}".format(e))
 
     def enable_ssl(self):
         if self.config_pkinit:

From 57f2aaf6bcc7e0e09a4f60151cacaffcedf9b454 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Fri, 31 Mar 2017 15:15:50 +0200
Subject: [PATCH 7/8] Use local anchor when armoring password requests

https://pagure.io/freeipa/issue/6830
---
 ipaserver/rpcserver.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py
index 77ed7e1..1618724 100644
--- a/ipaserver/rpcserver.py
+++ b/ipaserver/rpcserver.py
@@ -944,7 +944,7 @@ def kinit(self, principal, password, ccache_name):
         self.debug('Obtaining armor in ccache %s', armor_path)
 
         try:
-            kinit_armor(armor_path)
+            kinit_armor(armor_path, pkinit_anchor=paths.CACERT_PEM)
         except RuntimeError as e:
             self.error("Failed to obtain armor cache")
             # We try to continue w/o armor, 2FA will be impacted

From 199f97b8eb3fcec01c0d4cb76746a76aa54f0989 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Thu, 6 Apr 2017 18:52:05 +0200
Subject: [PATCH 8/8] Uograde: configure local/full PKINIT depending on the
 master status

The upgrader has been modified to configure either local or full PKINIT
depending on the CA status. Additionally, the new PKINIT configuration
will be written to the master's KDC entry.

https://pagure.io/freeipa/issue/6830
http://www.freeipa.org/page/V4/Kerberos_PKINIT
---
 ipaserver/install/server/upgrade.py | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index e736d78..8974bec 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -1485,14 +1485,20 @@ def add_default_caacl(ca):
 def setup_pkinit(krb):
     root_logger.info("[Setup PKINIT]")
 
-    if not api.Command.ca_is_enabled()['result']:
-        root_logger.info("CA is not enabled")
-        return
+    pkinit_state = krbinstance.get_local_pkinit_state()
+
+    if pkinit_state not in (krbinstance.PKINIT_FULL,
+                            krbinstance.PKINIT_EXTERNAL):
 
-    if not os.path.exists(paths.KDC_CERT):
-        root_logger.info("Requesting PKINIT certificate")
-        krb.setup_pkinit()
+        pkinit_setup_handler = krb.setup_local_pkinit
 
+        if api.Command.ca_is_enabled()['result']:
+            pkinit_setup_handler = krb.setup_full_pkinit
+
+        pkinit_setup_handler()
+
+    # reconfigure KDC just in case in order to handle potentially broken
+    # 4.5.0 -> 4.5.1 upgrade path
     replacevars = dict()
     replacevars['pkinit_identity'] = 'FILE:{},{}'.format(
         paths.KDC_CERT,paths.KDC_KEY)
@@ -1506,6 +1512,9 @@ def setup_pkinit(krb):
     krb.start()
     krb.test_anonymous_pkinit()
 
+    # finally publish the resulting PKINIT status in LDAP
+    krbinstance.record_pkinit_state_ldap(api)
+
 
 def disable_httpd_system_trust(http):
     ca_certs = []
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to