URL: https://github.com/freeipa/freeipa/pull/3508
Author: frasertweedale
 Title: #3508: [Backport][ipa-4-7] Profile-based system cert renewal
Action: opened

PR body:
"""
Manual backport of https://github.com/freeipa/freeipa/pull/3316 to ipa-4-7.  We
may need to backport this change all the way to ipa-4-6 to allow us to change
the IPA RA certificate profile on older releases.  Currently this change is on
master and ipa-4-8, so ipa-4-7 is the next step.

There were some trivial conflicts. The only substantive conflicts were in
`dogtaginstance.py`.  These were resolved by cherry-picking
8686cd3b4b69f725aee05c9cdd3034d7436055d3 ahead of the original patchset.

https://pagure.io/freeipa/issue/7991

Do not rely on CI only; I will have to test this change myself so I'll add WIP
label, and remove it when I'm satisfied.
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/3508/head:pr3508
git checkout pr3508
From c0e1de49560ee8acc1ef13d5b871b187461fe42a Mon Sep 17 00:00:00 2001
From: Christian Heimes <chei...@redhat.com>
Date: Tue, 23 Apr 2019 13:47:38 +0200
Subject: [PATCH 01/15] Pass token_name to certmonger

For HSM support, IPA has to pass the token name for CA and subsystem
certificates to certmonger. For now, only the default 'internal' token is
supported.

Related: https://pagure.io/freeipa/issue/5608
Signed-off-by: Christian Heimes <chei...@redhat.com>
Reviewed-By: Alexander Bokovoy <aboko...@redhat.com>
Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 ipalib/install/certmonger.py        | 11 +++++++++--
 ipaserver/install/dogtaginstance.py | 29 ++++++++++++++++++++++-------
 2 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/ipalib/install/certmonger.py b/ipalib/install/certmonger.py
index 03caff964a..3c1844797b 100644
--- a/ipalib/install/certmonger.py
+++ b/ipalib/install/certmonger.py
@@ -427,7 +427,8 @@ def request_cert(
 
 def start_tracking(
         certpath, ca='IPA', nickname=None, pin=None, pinfile=None,
-        pre_command=None, post_command=None, profile=None, storage="NSSDB"):
+        pre_command=None, post_command=None, profile=None, storage="NSSDB",
+        token_name=None):
     """
     Tell certmonger to track the given certificate in either a file or an NSS
     database. The certificate access can be protected by a password_file.
@@ -460,6 +461,8 @@ def start_tracking(
         NSS or OpenSSL backend to track the certificate in ``certpath``
     :param profile:
         Which certificate profile should be used.
+    :param token_name:
+        Hardware token name for HSM support
     :returns: certificate tracking nickname.
     """
     if storage == 'FILE':
@@ -500,6 +503,10 @@ def start_tracking(
         params['cert-postsave-command'] = post_command
     if profile:
         params['ca-profile'] = profile
+    if token_name not in {None, "internal"}:
+        # only pass token names for external tokens (e.g. HSM)
+        params['key-token'] = token_name
+        params['cert-token'] = token_name
 
     result = cm.obj_if.add_request(params)
     try:
@@ -663,7 +670,7 @@ def modify_ca_helper(ca_name, helper):
         return old_helper
 
 
-def get_pin(token):
+def get_pin(token="internal"):
     """
     Dogtag stores its NSS pin in a file formatted as token:PIN.
 
diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py
index d70651728b..91e352559a 100644
--- a/ipaserver/install/dogtaginstance.py
+++ b/ipaserver/install/dogtaginstance.py
@@ -92,6 +92,10 @@ class DogtagInstance(service.Service):
     tracking_reqs = None
     server_cert_name = None
 
+    # token for CA and subsystem certificates. For now, only internal token
+    # is supported.
+    token_name = "internal"
+
     ipaca_groups = DN(('ou', 'groups'), ('o', 'ipaca'))
     ipaca_people = DN(('ou', 'people'), ('o', 'ipaca'))
     groups_aci = (
@@ -195,6 +199,12 @@ def enable_client_auth_to_db(self):
         """
         Enable client auth connection to the internal db.
         """
+        sub_system_nickname = "subsystemCert cert-pki-ca"
+        if self.token_name != "internal":
+            # TODO: Dogtag 10.6.9 does not like "internal" prefix.
+            sub_system_nickname = '{}:{}'.format(
+                self.token_name, sub_system_nickname
+            )
 
         with stopped_service('pki-tomcatd', 'pki-tomcat'):
             directivesetter.set_directive(
@@ -204,7 +214,7 @@ def enable_client_auth_to_db(self):
             directivesetter.set_directive(
                 self.config,
                 'authz.instance.DirAclAuthz.ldap.ldapauth.clientCertNickname',
-                'subsystemCert cert-pki-ca', quotes=False, separator='=')
+                sub_system_nickname, quotes=False, separator='=')
             directivesetter.set_directive(
                 self.config,
                 'authz.instance.DirAclAuthz.ldap.ldapconn.port', '636',
@@ -222,7 +232,7 @@ def enable_client_auth_to_db(self):
             directivesetter.set_directive(
                 self.config,
                 'internaldb.ldapauth.clientCertNickname',
-                'subsystemCert cert-pki-ca', quotes=False, separator='=')
+                sub_system_nickname, quotes=False, separator='=')
             directivesetter.set_directive(
                 self.config,
                 'internaldb.ldapconn.port', '636', quotes=False, separator='=')
@@ -289,9 +299,9 @@ def configure_certmonger_renewal(self):
                     # Give dogtag extra time to generate cert
                     timeout=CA_DBUS_TIMEOUT)
 
-    def __get_pin(self):
+    def __get_pin(self, token_name="internal"):
         try:
-            return certmonger.get_pin('internal')
+            return certmonger.get_pin(token_name)
         except IOError as e:
             logger.debug(
                 'Unable to determine PIN for the Dogtag instance: %s', e)
@@ -299,7 +309,7 @@ def __get_pin(self):
 
     def configure_renewal(self):
         """ Configure certmonger to renew system certs """
-        pin = self.__get_pin()
+        pin = self.__get_pin(self.token_name)
 
         for nickname in self.tracking_reqs:
             try:
@@ -307,6 +317,7 @@ def configure_renewal(self):
                     certpath=self.nss_db,
                     ca='dogtag-ipa-ca-renew-agent',
                     nickname=nickname,
+                    token_name=self.token_name,
                     pin=pin,
                     pre_command='stop_pkicad',
                     post_command='renew_ca_cert "%s"' % nickname,
@@ -321,15 +332,19 @@ def track_servercert(self):
         done by the renewal script, renew_ca_cert once all the subsystem
         certificates are renewed.
         """
-        pin = self.__get_pin()
+        # server cert is always stored in internal token
+        token_name = "internal"
+        pin = self.__get_pin(token_name)
         try:
             certmonger.start_tracking(
                 certpath=self.nss_db,
                 ca='dogtag-ipa-ca-renew-agent',
                 nickname=self.server_cert_name,
+                token_name=token_name,
                 pin=pin,
                 pre_command='stop_pkicad',
-                post_command='renew_ca_cert "%s"' % self.server_cert_name)
+                post_command='renew_ca_cert "%s"' % self.server_cert_name
+            )
         except RuntimeError as e:
             logger.error(
                 "certmonger failed to start tracking certificate: %s", e)

From 0e2d088735ad5cf726411aec3688c2eb3f1af407 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftwee...@redhat.com>
Date: Fri, 17 May 2019 16:04:14 +1000
Subject: [PATCH 02/15] dogtaginstance: add profile to tracking requests

Enabling "fresh" renewals (c.f. "renewal"-based renewals that
reference the expired certificate and its associated request object)
will improve renewal robustness.

To use fresh renewals the tracking request must record the profile
to be used.  Make dogtaginstance record the profile when creating
tracking requests for both CA and KRA.

Note that 'Server-Cert cert-pki-ca' and the 'IPA RA' both use
profile 'caServerCert', which is the default (according to
dogtag-ipa-renew-agent which is part of Certmonger).  So we do not
need any special handling for those certificates.

This commit does not handle upgrade.  It will be handled in a
subsequent commit.

Part of: https://pagure.io/freeipa/issue/7991

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 ipaserver/install/cainstance.py     | 10 ++++++----
 ipaserver/install/dogtaginstance.py |  8 +++++++-
 ipaserver/install/krainstance.py    |  8 +++++---
 3 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 7033f13bce..1efea008b6 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -298,10 +298,12 @@ class CAInstance(DogtagInstance):
        2 = have signed cert, continue installation
     """
 
-    tracking_reqs = ('auditSigningCert cert-pki-ca',
-                     'ocspSigningCert cert-pki-ca',
-                     'subsystemCert cert-pki-ca',
-                     'caSigningCert cert-pki-ca')
+    tracking_reqs = {
+        'auditSigningCert cert-pki-ca': 'caSignedLogCert',
+        'ocspSigningCert cert-pki-ca': 'caOCSPCert',
+        'subsystemCert cert-pki-ca': 'caSubsystemCert',
+        'caSigningCert cert-pki-ca': 'caCACert',
+    }
     server_cert_name = 'Server-Cert cert-pki-ca'
     # The following must be aligned with the RewriteRule defined in
     # install/share/ipa-pki-proxy.conf.template
diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py
index 91e352559a..27d123fe09 100644
--- a/ipaserver/install/dogtaginstance.py
+++ b/ipaserver/install/dogtaginstance.py
@@ -89,7 +89,12 @@ class DogtagInstance(service.Service):
     CA, KRA, and eventually TKS and TPS.
     """
 
-    tracking_reqs = None
+    # Mapping of nicknames for tracking requests, and the profile to use for
+    # that certificate.  'configure_renewal()' reads this dict and adds the
+    # profile if configured.  Certificates that use the default profile
+    # ("caServerCert", as defined by dogtag-ipa-renew-agent which is part of
+    # Certmonger) are omitted.
+    tracking_reqs = dict()
     server_cert_name = None
 
     # token for CA and subsystem certificates. For now, only internal token
@@ -321,6 +326,7 @@ def configure_renewal(self):
                     pin=pin,
                     pre_command='stop_pkicad',
                     post_command='renew_ca_cert "%s"' % nickname,
+                    profile=self.tracking_reqs[nickname],
                 )
             except RuntimeError as e:
                 logger.error(
diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py
index 3b44651819..02f48bed69 100644
--- a/ipaserver/install/krainstance.py
+++ b/ipaserver/install/krainstance.py
@@ -65,9 +65,11 @@ class KRAInstance(DogtagInstance):
     be the same for both the CA and KRA.
     """
 
-    tracking_reqs = ('auditSigningCert cert-pki-kra',
-                     'transportCert cert-pki-kra',
-                     'storageCert cert-pki-kra')
+    tracking_reqs = {
+        'auditSigningCert cert-pki-kra': 'caInternalAuthAuditSigningCert',
+        'transportCert cert-pki-kra': 'caInternalAuthTransportCert',
+        'storageCert cert-pki-kra': 'caInternalAuthDRMstorageCert',
+    }
 
     def __init__(self, realm):
         super(KRAInstance, self).__init__(

From d7e6c9d797bc01b2e30744c3d040967c159434e2 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftwee...@redhat.com>
Date: Fri, 17 May 2019 16:30:47 +1000
Subject: [PATCH 03/15] upgrade: add profile to Dogtag tracking requests

To use profile-based renewal (rather than "renewal existing cert"
renewal which is brittle against database corruption or deleted
certificate / request objects), Certmonger tracking requests for
Dogtag system certs must record the profile to be used.

Update the upgrade method that checks tracking requests to look for
the profile.  Tracking requests will be recreated if the expected
data are not found.  The code that actually adds the tracking
requests was updated in a previous commit.

Part of: https://pagure.io/freeipa/issue/7991

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 ipaserver/install/cainstance.py     |  3 ++
 ipaserver/install/krainstance.py    |  3 ++
 ipaserver/install/server/upgrade.py | 57 +++++++++--------------------
 3 files changed, 24 insertions(+), 39 deletions(-)

diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 1efea008b6..45ba2fb626 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -298,6 +298,9 @@ class CAInstance(DogtagInstance):
        2 = have signed cert, continue installation
     """
 
+    # Mapping of nicknames for tracking requests, and the profile to
+    # use for that certificate.  'configure_renewal()' reads this
+    # dict.  The profile MUST be specified.
     tracking_reqs = {
         'auditSigningCert cert-pki-ca': 'caSignedLogCert',
         'ocspSigningCert cert-pki-ca': 'caOCSPCert',
diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py
index 02f48bed69..a2b3961d61 100644
--- a/ipaserver/install/krainstance.py
+++ b/ipaserver/install/krainstance.py
@@ -65,6 +65,9 @@ class KRAInstance(DogtagInstance):
     be the same for both the CA and KRA.
     """
 
+    # Mapping of nicknames for tracking requests, and the profile to
+    # use for that certificate.  'configure_renewal()' reads this
+    # dict.  The profile MUST be specified.
     tracking_reqs = {
         'auditSigningCert cert-pki-kra': 'caInternalAuthAuditSigningCert',
         'transportCert cert-pki-kra': 'caInternalAuthTransportCert',
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index fbb62d7c9a..d1149f15bd 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -970,48 +970,27 @@ def certificate_renewal_update(ca, ds, http):
     template = paths.CERTMONGER_COMMAND_TEMPLATE
     serverid = installutils.realm_to_serverid(api.env.realm)
 
-    requests = [
-        {
-            'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
-            'cert-nickname': 'auditSigningCert cert-pki-ca',
-            'ca-name': 'dogtag-ipa-ca-renew-agent',
-            'cert-presave-command': template % 'stop_pkicad',
-            'cert-postsave-command':
-                (template % 'renew_ca_cert "auditSigningCert cert-pki-ca"'),
-        },
-        {
-            'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
-            'cert-nickname': 'ocspSigningCert cert-pki-ca',
-            'ca-name': 'dogtag-ipa-ca-renew-agent',
-            'cert-presave-command': template % 'stop_pkicad',
-            'cert-postsave-command':
-                (template % 'renew_ca_cert "ocspSigningCert cert-pki-ca"'),
-        },
-        {
-            'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
-            'cert-nickname': 'subsystemCert cert-pki-ca',
-            'ca-name': 'dogtag-ipa-ca-renew-agent',
-            'cert-presave-command': template % 'stop_pkicad',
-            'cert-postsave-command':
-                (template % 'renew_ca_cert "subsystemCert cert-pki-ca"'),
-        },
-        {
-            'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
-            'cert-nickname': 'caSigningCert cert-pki-ca',
-            'ca-name': 'dogtag-ipa-ca-renew-agent',
-            'cert-presave-command': template % 'stop_pkicad',
-            'cert-postsave-command':
-                (template % 'renew_ca_cert "caSigningCert cert-pki-ca"'),
-            'template-profile': None,
-        },
-        {
+    requests = []
+
+    dogtag_system_nicks = (
+        list(cainstance.CAInstance.tracking_reqs) +
+        [cainstance.CAInstance.server_cert_name]
+    )
+    for nick in dogtag_system_nicks:
+        req = {
             'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
-            'cert-nickname': 'Server-Cert cert-pki-ca',
+            'cert-nickname': nick,
             'ca-name': 'dogtag-ipa-ca-renew-agent',
             'cert-presave-command': template % 'stop_pkicad',
             'cert-postsave-command':
-                (template % 'renew_ca_cert "Server-Cert cert-pki-ca"'),
-        },
+                (template % 'renew_ca_cert "{}"'.format(nick)),
+        }
+        profile = cainstance.CAInstance.tracking_reqs.get(nick)
+        if profile:
+            req['template-profile'] = profile
+        requests.append(req)
+
+    requests.append(
         {
             'cert-file': paths.RA_AGENT_PEM,
             'key-file': paths.RA_AGENT_KEY,
@@ -1019,7 +998,7 @@ def certificate_renewal_update(ca, ds, http):
             'cert-presave-command': template % 'renew_ra_cert_pre',
             'cert-postsave-command': template % 'renew_ra_cert',
         },
-    ]
+    )
 
     logger.info("[Update certmonger certificate renewal configuration]")
     if not ca.is_configured():

From f09614bd614caea6af40d31d3efd29892640dcbc Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftwee...@redhat.com>
Date: Fri, 17 May 2019 11:43:18 +1000
Subject: [PATCH 04/15] certmonger: use long options when invoking
 dogtag-ipa-renew-agent

To aid reader comprehension, use long options instead of short
options when invoking dogtag-ipa-renew-agent.

  -N -> --force-new
  -O -> --approval-option

Part of: https://pagure.io/freeipa/issue/7991

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 install/certmonger/dogtag-ipa-ca-renew-agent-submit.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit.in b/install/certmonger/dogtag-ipa-ca-renew-agent-submit.in
index d4d4c255ac..cd3a1bd69a 100644
--- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit.in
+++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit.in
@@ -205,7 +205,7 @@ def request_cert(reuse_existing, **kwargs):
             sys.argv[1:] +
             ['--submit-option', "requestor_name=IPA"])
     if os.environ.get('CERTMONGER_CA_PROFILE') == 'caCACert':
-        args += ['-N', '-O', 'bypassCAnotafter=true']
+        args += ['--force-new', '--approval-option', 'bypassCAnotafter=true']
     result = ipautil.run(args, raiseonerr=False, env=os.environ,
                          capture_output=True)
     if six.PY2:

From cbbb0dc1d813df3c57e22d1ddb3cbb494a6b9f28 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftwee...@redhat.com>
Date: Fri, 17 May 2019 16:38:01 +1000
Subject: [PATCH 05/15] dogtag-ipa-ca-renew-agent: always use profile-based
 renewal

Update the renewal helper to always request a new certificate
("enrollment request") instead of using "renewal request".  The
latter is brittle in the face of:

- missing certificate record in database

- missing original request record in database (pointed to by
  certificate record)

- "mismatched" certificate or request records (there have been many
  cases of this; it is suspected that request/serial range conflicts,
  or something similar, may be the cause)

The Dogtag tracking request must know what profile to use, except
where the certificate uses the default profile ("caServerCert" per
'dogtag-ipa-renew-agent' implementation in Certmonger itself).
This part of the puzzle was dealt with in previous commits.

Part of: https://pagure.io/freeipa/issue/7991

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 install/certmonger/dogtag-ipa-ca-renew-agent-submit.in | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit.in b/install/certmonger/dogtag-ipa-ca-renew-agent-submit.in
index cd3a1bd69a..19e50da4d6 100644
--- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit.in
+++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit.in
@@ -203,9 +203,9 @@ def request_cert(reuse_existing, **kwargs):
              "--certfile", paths.RA_AGENT_PEM,
              "--keyfile", paths.RA_AGENT_KEY] +
             sys.argv[1:] +
-            ['--submit-option', "requestor_name=IPA"])
-    if os.environ.get('CERTMONGER_CA_PROFILE') == 'caCACert':
-        args += ['--force-new', '--approval-option', 'bypassCAnotafter=true']
+            ['--submit-option', "requestor_name=IPA"] +
+            ['--force-new', '--approval-option', 'bypassCAnotafter=true']
+    )
     result = ipautil.run(args, raiseonerr=False, env=os.environ,
                          capture_output=True)
     if six.PY2:

From 3d2f77ef805487e46ed953d2044c71df28cf4348 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftwee...@redhat.com>
Date: Wed, 26 Jun 2019 11:54:59 +1000
Subject: [PATCH 06/15] dogtaginstance: avoid special cases for Server-Cert

The Dogtag "Server-Cert cert-pki-ca" certificate is treated
specially, with its own track_servercert() method and other special
casing.  But there is no real need for this - the only (potential)
difference is the token name.  Account for the token name difference
with a lookup method and treat all Dogtag system certs equally
w.r.t. tracking request creation and removal.

Part of: https://pagure.io/freeipa/issue/7991

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 ipaserver/install/cainstance.py     |  9 ++++--
 ipaserver/install/dogtaginstance.py | 50 ++++++++---------------------
 ipaserver/install/server/upgrade.py |  7 +---
 3 files changed, 22 insertions(+), 44 deletions(-)

diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 45ba2fb626..0e3ba2170b 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -298,6 +298,8 @@ class CAInstance(DogtagInstance):
        2 = have signed cert, continue installation
     """
 
+    server_cert_name = 'Server-Cert cert-pki-ca'
+
     # Mapping of nicknames for tracking requests, and the profile to
     # use for that certificate.  'configure_renewal()' reads this
     # dict.  The profile MUST be specified.
@@ -306,8 +308,12 @@ class CAInstance(DogtagInstance):
         'ocspSigningCert cert-pki-ca': 'caOCSPCert',
         'subsystemCert cert-pki-ca': 'caSubsystemCert',
         'caSigningCert cert-pki-ca': 'caCACert',
+        server_cert_name: 'caServerCert',
     }
-    server_cert_name = 'Server-Cert cert-pki-ca'
+    token_names = {
+        server_cert_name: 'internal',  # Server-Cert always on internal token
+    }
+
     # The following must be aligned with the RewriteRule defined in
     # install/share/ipa-pki-proxy.conf.template
     crl_rewrite_pattern = r"^\s*(RewriteRule\s+\^/ipa/crl/MasterCRL.bin\s.*)$"
@@ -474,7 +480,6 @@ def configure_instance(self, host_name, dm_password, admin_password,
                         "Ensuring backward compatibility",
                         self.__dogtag10_migration)
                 self.step("configure certificate renewals", self.configure_renewal)
-                self.step("configure Server-Cert certificate renewal", self.track_servercert)
                 self.step("Configure HTTP to proxy connections",
                           self.http_proxy)
                 self.step("restarting certificate server", self.restart_instance)
diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py
index 27d123fe09..aba94c438a 100644
--- a/ipaserver/install/dogtaginstance.py
+++ b/ipaserver/install/dogtaginstance.py
@@ -89,18 +89,22 @@ class DogtagInstance(service.Service):
     CA, KRA, and eventually TKS and TPS.
     """
 
-    # Mapping of nicknames for tracking requests, and the profile to use for
-    # that certificate.  'configure_renewal()' reads this dict and adds the
-    # profile if configured.  Certificates that use the default profile
-    # ("caServerCert", as defined by dogtag-ipa-renew-agent which is part of
-    # Certmonger) are omitted.
+    # Mapping of nicknames for tracking requests, and the profile to
+    # use for that certificate.  'configure_renewal()' reads this
+    # dict and adds the profile if configured.
     tracking_reqs = dict()
-    server_cert_name = None
 
     # token for CA and subsystem certificates. For now, only internal token
     # is supported.
     token_name = "internal"
 
+    # override token for specific nicknames
+    token_names = dict()
+
+    def get_token_name(self, nickname):
+        """Look up token name for nickname."""
+        return self.token_names.get(nickname, self.token_name)
+
     ipaca_groups = DN(('ou', 'groups'), ('o', 'ipaca'))
     ipaca_people = DN(('ou', 'people'), ('o', 'ipaca'))
     groups_aci = (
@@ -314,15 +318,16 @@ def __get_pin(self, token_name="internal"):
 
     def configure_renewal(self):
         """ Configure certmonger to renew system certs """
-        pin = self.__get_pin(self.token_name)
 
         for nickname in self.tracking_reqs:
+            token_name = self.get_token_name(nickname)
+            pin = self.__get_pin(token_name)
             try:
                 certmonger.start_tracking(
                     certpath=self.nss_db,
                     ca='dogtag-ipa-ca-renew-agent',
                     nickname=nickname,
-                    token_name=self.token_name,
+                    token_name=token_name,
                     pin=pin,
                     pre_command='stop_pkicad',
                     post_command='renew_ca_cert "%s"' % nickname,
@@ -332,29 +337,6 @@ def configure_renewal(self):
                 logger.error(
                     "certmonger failed to start tracking certificate: %s", e)
 
-    def track_servercert(self):
-        """
-        Specifically do not tell certmonger to restart the CA. This will be
-        done by the renewal script, renew_ca_cert once all the subsystem
-        certificates are renewed.
-        """
-        # server cert is always stored in internal token
-        token_name = "internal"
-        pin = self.__get_pin(token_name)
-        try:
-            certmonger.start_tracking(
-                certpath=self.nss_db,
-                ca='dogtag-ipa-ca-renew-agent',
-                nickname=self.server_cert_name,
-                token_name=token_name,
-                pin=pin,
-                pre_command='stop_pkicad',
-                post_command='renew_ca_cert "%s"' % self.server_cert_name
-            )
-        except RuntimeError as e:
-            logger.error(
-                "certmonger failed to start tracking certificate: %s", e)
-
     def stop_tracking_certificates(self, stop_certmonger=True):
         """Stop tracking our certificates. Called on uninstall.
         """
@@ -368,11 +350,7 @@ def stop_tracking_certificates(self, stop_certmonger=True):
             services.knownservices.dbus.start()
         cmonger.start()
 
-        nicknames = list(self.tracking_reqs)
-        if self.server_cert_name is not None:
-            nicknames.append(self.server_cert_name)
-
-        for nickname in nicknames:
+        for nickname in self.tracking_reqs:
             try:
                 certmonger.stop_tracking(
                     self.nss_db, nickname=nickname)
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index d1149f15bd..12f6aeefd2 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -972,11 +972,7 @@ def certificate_renewal_update(ca, ds, http):
 
     requests = []
 
-    dogtag_system_nicks = (
-        list(cainstance.CAInstance.tracking_reqs) +
-        [cainstance.CAInstance.server_cert_name]
-    )
-    for nick in dogtag_system_nicks:
+    for nick in cainstance.CAInstance.tracking_reqs:
         req = {
             'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
             'cert-nickname': nick,
@@ -1072,7 +1068,6 @@ def certificate_renewal_update(ca, ds, http):
     ca.configure_certmonger_renewal()
     ca.configure_renewal()
     ca.configure_agent_renewal()
-    ca.track_servercert()
     ca.add_lightweight_ca_tracking_requests()
     ds.start_tracking_certificates(serverid)
     http.start_tracking_certificates()

From ec44f0a4dd158f6f07abe71cba2e0e1a4e5ba79f Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftwee...@redhat.com>
Date: Wed, 26 Jun 2019 13:52:20 +1000
Subject: [PATCH 07/15] upgrade: always add profile to tracking requests

The profile for every Dogtag system cert tracking request is now
explicitly specified.  So remove the code that handled unspecified
profiles.

Part of: https://pagure.io/freeipa/issue/7991

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 ipaserver/install/dogtaginstance.py | 2 +-
 ipaserver/install/server/upgrade.py | 6 ++----
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py
index aba94c438a..8a3839cd03 100644
--- a/ipaserver/install/dogtaginstance.py
+++ b/ipaserver/install/dogtaginstance.py
@@ -91,7 +91,7 @@ class DogtagInstance(service.Service):
 
     # Mapping of nicknames for tracking requests, and the profile to
     # use for that certificate.  'configure_renewal()' reads this
-    # dict and adds the profile if configured.
+    # dict.  The profile MUST be specified.
     tracking_reqs = dict()
 
     # token for CA and subsystem certificates. For now, only internal token
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index 12f6aeefd2..b660b7b739 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -972,7 +972,7 @@ def certificate_renewal_update(ca, ds, http):
 
     requests = []
 
-    for nick in cainstance.CAInstance.tracking_reqs:
+    for nick, profile in cainstance.CAInstance.tracking_reqs.items():
         req = {
             'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
             'cert-nickname': nick,
@@ -980,10 +980,8 @@ def certificate_renewal_update(ca, ds, http):
             'cert-presave-command': template % 'stop_pkicad',
             'cert-postsave-command':
                 (template % 'renew_ca_cert "{}"'.format(nick)),
+            'template-profile': profile,
         }
-        profile = cainstance.CAInstance.tracking_reqs.get(nick)
-        if profile:
-            req['template-profile'] = profile
         requests.append(req)
 
     requests.append(

From 243c3644556b598487e400aa945360fc51164946 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftwee...@redhat.com>
Date: Wed, 26 Jun 2019 14:08:48 +1000
Subject: [PATCH 08/15] upgrade: update KRA tracking requests

The upgrade routine checks tracking requests for CA system
certificates, IPA RA and HTTP/LDAP/KDC service certificates.  If a
tracking request matching our expectations is not found, we stop
tracking all certificates, then create new tracking requests with
the correct configuration.

But the KRA was left out.  Add checks for KRA certificates, and
remove/recreate KRA tracking requests when appropriate.

Part of: https://pagure.io/freeipa/issue/7991

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 ipaserver/install/server/upgrade.py | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index b660b7b739..ba48701edf 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -5,6 +5,7 @@
 from __future__ import print_function, absolute_import
 
 import errno
+import itertools
 import logging
 import re
 import os
@@ -962,7 +963,7 @@ def named_add_crypto_policy():
     return True
 
 
-def certificate_renewal_update(ca, ds, http):
+def certificate_renewal_update(ca, kra, ds, http):
     """
     Update certmonger certificate renewal configuration.
     """
@@ -972,7 +973,11 @@ def certificate_renewal_update(ca, ds, http):
 
     requests = []
 
-    for nick, profile in cainstance.CAInstance.tracking_reqs.items():
+    dogtag_reqs = ca.tracking_reqs.items()
+    if kra.is_installed():
+        dogtag_reqs = itertools.chain(dogtag_reqs, kra.tracking_reqs.items())
+
+    for nick, profile in dogtag_reqs:
         req = {
             'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
             'cert-nickname': nick,
@@ -1054,6 +1059,8 @@ def certificate_renewal_update(ca, ds, http):
     # Ok, now we need to stop tracking, then we can start tracking them
     # again with new configuration:
     ca.stop_tracking_certificates()
+    if kra.is_installed():
+        kra.stop_tracking_certificates()
     ds.stop_tracking_certificates(serverid)
     http.stop_tracking_certificates()
 
@@ -1067,6 +1074,8 @@ def certificate_renewal_update(ca, ds, http):
     ca.configure_renewal()
     ca.configure_agent_renewal()
     ca.add_lightweight_ca_tracking_requests()
+    if kra.is_installed():
+        kra.configure_renewal()
     ds.start_tracking_certificates(serverid)
     http.start_tracking_certificates()
 
@@ -2048,7 +2057,7 @@ def upgrade_configuration():
         ca_restart,
         ca_upgrade_schema(ca),
         upgrade_ca_audit_cert_validity(ca),
-        certificate_renewal_update(ca, ds, http),
+        certificate_renewal_update(ca, kra, ds, http),
         ca_enable_pkix(ca),
         ca_configure_profiles_acl(ca),
         ca_configure_lightweight_ca_acls(ca),

From 78c85a32ccacdaacbb0a52aa8a90c7b0ae4cb104 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftwee...@redhat.com>
Date: Thu, 27 Jun 2019 09:46:59 +1000
Subject: [PATCH 09/15] upgrade: log missing/misconfigured tracking requests

For better diagnostics during upgrade, log the Certmonger tracking
requests that were not found (either because they do not exist, or
do not have the expected configuration).

Part of: https://pagure.io/freeipa/issue/7991

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 ipaserver/install/server/upgrade.py | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index ba48701edf..2ce9d86aad 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -1047,15 +1047,28 @@ def certificate_renewal_update(ca, kra, ds, http):
             )
 
     # State not set, lets see if we are already configured
+    missing_or_misconfigured_requests = []
     for request in requests:
         request_id = certmonger.get_request_id(request)
         if request_id is None:
-            break
-    else:
+            missing_or_misconfigured_requests.append(request)
+
+    if len(missing_or_misconfigured_requests) == 0:
         logger.info("Certmonger certificate renewal configuration already "
                     "up-to-date")
         return False
 
+    # Print info about missing requests
+    logger.info("Missing or incorrect tracking request for certificates:")
+    for request in missing_or_misconfigured_requests:
+        cert = None
+        if 'cert-file' in request:
+            cert = request['cert-file']
+        elif 'cert-database' in request and 'cert-nickname' in request:
+            cert = '{cert-database}:{cert-nickname}'.format(**request)
+        if cert is not None:
+            logger.info("  %s", cert)
+
     # Ok, now we need to stop tracking, then we can start tracking them
     # again with new configuration:
     ca.stop_tracking_certificates()

From 980428f7d17b127699d47b9ed53d025f1988b336 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftwee...@redhat.com>
Date: Thu, 27 Jun 2019 11:08:58 +1000
Subject: [PATCH 10/15] upgrade: fix spurious certmonger re-tracking

The search for the HTTP Certmonger tracking request uses an
incorrect parameter ('key-storage'), triggering removal and
recreation of tracking requests on every upgrade.  Replace
'key-storage' with the correct parameter, 'key-file'.

Part of: https://pagure.io/freeipa/issue/7991

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 ipaserver/install/server/upgrade.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index 2ce9d86aad..4cbbb9f316 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -1010,7 +1010,7 @@ def certificate_renewal_update(ca, kra, ds, http):
         requests.append(
             {
                 'cert-file': paths.HTTPD_CERT_FILE,
-                'key-storage': paths.HTTPD_KEY_FILE,
+                'key-file': paths.HTTPD_KEY_FILE,
                 'ca-name': 'IPA',
                 'cert-postsave-command': template % 'restart_httpd',
             }

From 45d6fe856cbef8be50aae56352264843e47331bd Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftwee...@redhat.com>
Date: Thu, 27 Jun 2019 11:27:02 +1000
Subject: [PATCH 11/15] cainstance: add profile to IPA RA tracking request

Profile-based renewal means we should always explicitly specify the
profile in tracking requests that use the dogtag-ipa-ca-renew-agent
renewal helper.  This includes the IPA RA agent certificate.  Update
CAInstance.configure_agent_renewal() to add the profile to the
tracking request.  This also covers the upgrade scenario (because
the same method gets invoked).

Part of: https://pagure.io/freeipa/issue/7991

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 ipalib/constants.py                 | 1 +
 ipaserver/install/cainstance.py     | 1 +
 ipaserver/install/server/upgrade.py | 2 ++
 3 files changed, 4 insertions(+)

diff --git a/ipalib/constants.py b/ipalib/constants.py
index d4577d668f..3bc042edee 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -306,6 +306,7 @@
 IPA_CA_NICKNAME = 'caSigningCert cert-pki-ca'
 RENEWAL_CA_NAME = 'dogtag-ipa-ca-renew-agent'
 RENEWAL_REUSE_CA_NAME = 'dogtag-ipa-ca-renew-agent-reuse'
+RA_AGENT_PROFILE = 'caServerCert'
 # How long dbus clients should wait for CA certificate RPCs [seconds]
 CA_DBUS_TIMEOUT = 120
 
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 0e3ba2170b..a12452cdf9 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -1162,6 +1162,7 @@ def configure_agent_renewal(self):
             certmonger.start_tracking(
                 certpath=(paths.RA_AGENT_PEM, paths.RA_AGENT_KEY),
                 ca='dogtag-ipa-ca-renew-agent',
+                profile=ipalib.constants.RA_AGENT_PROFILE,
                 pre_command='renew_ra_cert_pre',
                 post_command='renew_ra_cert',
                 storage='FILE')
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index 4cbbb9f316..6d6287c7f7 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -20,6 +20,7 @@
 from augeas import Augeas
 import dns.exception
 from ipalib import api, x509
+from ipalib.constants import RA_AGENT_PROFILE
 from ipalib.install import certmonger, sysrestore
 import SSSDConfig
 import ipalib.util
@@ -994,6 +995,7 @@ def certificate_renewal_update(ca, kra, ds, http):
             'cert-file': paths.RA_AGENT_PEM,
             'key-file': paths.RA_AGENT_KEY,
             'ca-name': 'dogtag-ipa-ca-renew-agent',
+            'template-profile': RA_AGENT_PROFILE,
             'cert-presave-command': template % 'renew_ra_cert_pre',
             'cert-postsave-command': template % 'renew_ra_cert',
         },

From 0db7b7e18aa95fbbdf1b7d6b6387716ddd10c410 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftwee...@redhat.com>
Date: Thu, 27 Jun 2019 11:48:53 +1000
Subject: [PATCH 12/15] Use RENEWAL_CA_NAME and RA_AGENT_PROFILE constants

Replace renewal CA and profile name literals with corresponding
symbols from ipalib.constants.

Part of: https://pagure.io/freeipa/issue/7991

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 ipaserver/install/cainstance.py     | 6 +++---
 ipaserver/install/dogtaginstance.py | 6 +++---
 ipaserver/install/server/upgrade.py | 8 ++++----
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index a12452cdf9..195d17d4bb 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -979,7 +979,7 @@ def __request_ra_certificate(self):
                 principal='host/%s' % self.fqdn,
                 subject=str(DN(('CN', 'IPA RA'), self.subject_base)),
                 ca=ipalib.constants.RENEWAL_CA_NAME,
-                profile='caServerCert',
+                profile=ipalib.constants.RA_AGENT_PROFILE,
                 pre_command='renew_ra_cert_pre',
                 post_command='renew_ra_cert',
                 storage="FILE",
@@ -1106,7 +1106,7 @@ def uninstall(self):
                              '/org/fedorahosted/certmonger')
         iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
         for suffix in ['', '-reuse']:
-            name = 'dogtag-ipa-ca-renew-agent' + suffix
+            name = ipalib.constants.RENEWAL_CA_NAME + suffix
             path = iface.find_ca_by_nickname(name)
             if path:
                 iface.remove_known_ca(path)
@@ -1161,7 +1161,7 @@ def configure_agent_renewal(self):
         try:
             certmonger.start_tracking(
                 certpath=(paths.RA_AGENT_PEM, paths.RA_AGENT_KEY),
-                ca='dogtag-ipa-ca-renew-agent',
+                ca=ipalib.constants.RENEWAL_CA_NAME,
                 profile=ipalib.constants.RA_AGENT_PROFILE,
                 pre_command='renew_ra_cert_pre',
                 post_command='renew_ra_cert',
diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py
index 8a3839cd03..4354a7c976 100644
--- a/ipaserver/install/dogtaginstance.py
+++ b/ipaserver/install/dogtaginstance.py
@@ -34,7 +34,7 @@
 
 from ipalib import api, errors, x509
 from ipalib.install import certmonger
-from ipalib.constants import CA_DBUS_TIMEOUT
+from ipalib.constants import CA_DBUS_TIMEOUT, RENEWAL_CA_NAME
 from ipaplatform import services
 from ipaplatform.constants import constants
 from ipaplatform.paths import paths
@@ -297,7 +297,7 @@ def configure_certmonger_renewal(self):
                              '/org/fedorahosted/certmonger')
         iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
         for suffix, args in [('', ''), ('-reuse', ' --reuse-existing')]:
-            name = 'dogtag-ipa-ca-renew-agent' + suffix
+            name = RENEWAL_CA_NAME + suffix
             path = iface.find_ca_by_nickname(name)
             if not path:
                 command = paths.DOGTAG_IPA_CA_RENEW_AGENT_SUBMIT + args
@@ -325,7 +325,7 @@ def configure_renewal(self):
             try:
                 certmonger.start_tracking(
                     certpath=self.nss_db,
-                    ca='dogtag-ipa-ca-renew-agent',
+                    ca=RENEWAL_CA_NAME,
                     nickname=nickname,
                     token_name=token_name,
                     pin=pin,
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index 6d6287c7f7..5f8f75fd75 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -20,7 +20,7 @@
 from augeas import Augeas
 import dns.exception
 from ipalib import api, x509
-from ipalib.constants import RA_AGENT_PROFILE
+from ipalib.constants import RENEWAL_CA_NAME, RA_AGENT_PROFILE
 from ipalib.install import certmonger, sysrestore
 import SSSDConfig
 import ipalib.util
@@ -982,7 +982,7 @@ def certificate_renewal_update(ca, kra, ds, http):
         req = {
             'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
             'cert-nickname': nick,
-            'ca-name': 'dogtag-ipa-ca-renew-agent',
+            'ca-name': RENEWAL_CA_NAME,
             'cert-presave-command': template % 'stop_pkicad',
             'cert-postsave-command':
                 (template % 'renew_ca_cert "{}"'.format(nick)),
@@ -994,7 +994,7 @@ def certificate_renewal_update(ca, kra, ds, http):
         {
             'cert-file': paths.RA_AGENT_PEM,
             'key-file': paths.RA_AGENT_KEY,
-            'ca-name': 'dogtag-ipa-ca-renew-agent',
+            'ca-name': RENEWAL_CA_NAME,
             'template-profile': RA_AGENT_PROFILE,
             'cert-presave-command': template % 'renew_ra_cert_pre',
             'cert-postsave-command': template % 'renew_ra_cert',
@@ -1040,7 +1040,7 @@ def certificate_renewal_update(ca, kra, ds, http):
                 {
                     'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
                     'cert-nickname': nickname,
-                    'ca-name': 'dogtag-ipa-ca-renew-agent',
+                    'ca-name': RENEWAL_CA_NAME,
                     'cert-presave-command': template % 'stop_pkicad',
                     'cert-postsave-command':
                         (template % ('renew_ca_cert "%s"' % nickname)),

From 6b260c6a8649d4e6411cb6ba138c4d7ad1b3569d Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftwee...@redhat.com>
Date: Thu, 27 Jun 2019 18:57:02 +1000
Subject: [PATCH 13/15] ipatests: test ipa-server-upgrade in CA-less deployment

Part of: https://pagure.io/freeipa/issue/7991

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 ipatests/test_integration/test_caless.py  | 4 ++++
 ipatests/test_integration/test_upgrade.py | 7 +++++++
 2 files changed, 11 insertions(+)

diff --git a/ipatests/test_integration/test_caless.py b/ipatests/test_integration/test_caless.py
index 77e1d2c09d..9a853e00fa 100644
--- a/ipatests/test_integration/test_caless.py
+++ b/ipatests/test_integration/test_caless.py
@@ -1249,6 +1249,10 @@ def test_host_del_doesnt_revoke(self):
         with self.host():
             self.master.run_command(['ipa', 'host-del', self.test_hostname])
 
+    def test_invoke_upgrader(self):
+        """Test that ipa-server-upgrade runs without error."""
+        self.master.run_command(['ipa-server-upgrade'], raiseonerr=True)
+
 
 class TestCertInstall(CALessBase):
     @classmethod
diff --git a/ipatests/test_integration/test_upgrade.py b/ipatests/test_integration/test_upgrade.py
index 5cc890e2e9..84f2dca0db 100644
--- a/ipatests/test_integration/test_upgrade.py
+++ b/ipatests/test_integration/test_upgrade.py
@@ -14,6 +14,13 @@
 
 
 class TestUpgrade(IntegrationTest):
+    """
+    Test ipa-server-upgrade.
+
+    Note that ipa-server-upgrade on a CA-less installation is tested
+    in ``test_caless.TestIPACommands.test_invoke_upgrader``.
+
+    """
     @classmethod
     def install(cls, mh):
         tasks.install_master(cls.master, setup_dns=False)

From 0d7ed5d23a1f4cb12ef2c689ff0ed4cc71fa2c57 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcrit...@redhat.com>
Date: Wed, 17 Jul 2019 16:51:16 +1000
Subject: [PATCH 14/15] httpinstance: add pinfile when tracking certificate

When the HTTP certificate gets untracked then tracked again, it
loses its pin file.  Ensure we add the pin file when (re-)tracking
the HTTP certificate.

Part of: https://pagure.io/freeipa/issue/7991

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 ipaserver/install/httpinstance.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
index 1ddbaa1427..0f74eadbd6 100644
--- a/ipaserver/install/httpinstance.py
+++ b/ipaserver/install/httpinstance.py
@@ -585,11 +585,14 @@ def stop_tracking_certificates(self):
                          str(e))
 
     def start_tracking_certificates(self):
+        key_passwd_file = paths.HTTPD_PASSWD_FILE_FMT.format(host=api.env.host)
         cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE)
         if certs.is_ipa_issued_cert(api, cert):
             request_id = certmonger.start_tracking(
                 certpath=(paths.HTTPD_CERT_FILE, paths.HTTPD_KEY_FILE),
-                post_command='restart_httpd', storage='FILE'
+                post_command='restart_httpd', storage='FILE',
+                profile=dogtag.DEFAULT_PROFILE,
+                pinfile=key_passwd_file,
             )
             subject = str(DN(cert.subject))
             certmonger.add_principal(request_id, self.principal)

From 5fb488ac8ea42d7b56ec395b7d1a10460360e95d Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftwee...@redhat.com>
Date: Fri, 19 Jul 2019 14:38:58 +1000
Subject: [PATCH 15/15] dsinstance: add profile when tracking certificate

When the DS certificate gets untracked then tracked again (via
dsinstance.start_tracking_certificate()), it loses its profile
configuration.  Although it is the default profile, we want to
retain the explicit reference.  Ensure we add the profile when
re-tracking the DS certificate.

Part of: https://pagure.io/freeipa/issue/7991

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 ipaserver/install/certs.py      | 6 ++++--
 ipaserver/install/dsinstance.py | 9 ++++++---
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
index 1466570fa5..d1d90da4c2 100644
--- a/ipaserver/install/certs.py
+++ b/ipaserver/install/certs.py
@@ -377,14 +377,16 @@ def get_cert_from_db(self, nickname):
         except ipautil.CalledProcessError:
             return None
 
-    def track_server_cert(self, nickname, principal, password_file=None, command=None):
+    def track_server_cert(
+            self, nickname, principal,
+            password_file=None, command=None, profile=None):
         """
         Tell certmonger to track the given certificate nickname.
         """
         try:
             request_id = certmonger.start_tracking(
                 self.secdir, nickname=nickname, pinfile=password_file,
-                post_command=command)
+                post_command=command, profile=profile)
         except RuntimeError as e:
             logger.error("certmonger failed starting to track certificate: %s",
                          str(e))
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index 741a7cbc75..2e36b63705 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -1178,9 +1178,12 @@ def start_tracking_certificates(self, serverid):
         dirname = config_dirname(serverid)[:-1]
         dsdb = certs.CertDB(self.realm, nssdir=dirname)
         if dsdb.is_ipa_issued_cert(api, nickname):
-            dsdb.track_server_cert(nickname, self.principal,
-                                   dsdb.passwd_fname,
-                                   'restart_dirsrv %s' % serverid)
+            dsdb.track_server_cert(
+                nickname,
+                self.principal,
+                password_file=dsdb.passwd_fname,
+                command='restart_dirsrv %s' % serverid,
+                profile=dogtag.DEFAULT_PROFILE)
         else:
             logger.debug("Will not track DS server certificate %s as it is "
                          "not issued by IPA", nickname)
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/freeipa-devel@lists.fedorahosted.org

Reply via email to