pgreco / rpms / ipa

Forked from forks/areguera/rpms/ipa 4 years ago
Clone

Blame SOURCES/0130-renew-agent-allow-reusing-existing-certs.patch

483b06
From 854ceb13a72630ba357ca5c1ec8ac5b320a4c9c5 Mon Sep 17 00:00:00 2001
483b06
From: Jan Cholasta <jcholast@redhat.com>
483b06
Date: Wed, 19 Apr 2017 12:55:47 +0000
483b06
Subject: [PATCH] renew agent: allow reusing existing certs
483b06
483b06
Add a switch which makes `dogtag-ipa-ca-renew-agent-submit` reuse the
483b06
existing certificate rather than request a new one from the CA while
483b06
maintaining LDAP replication of the certificate.
483b06
483b06
Make this available as a new `dogtag-ipa-ca-renew-agent-reuse` certmonger
483b06
CA.
483b06
483b06
This allows redoing the LDAP replication and reexecuting pre- and post-save
483b06
commands of a tracking request without reissuing the certificate.
483b06
483b06
https://pagure.io/freeipa/issue/5799
483b06
483b06
Reviewed-By: David Kupka <dkupka@redhat.com>
483b06
Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
483b06
---
483b06
 .../certmonger/dogtag-ipa-ca-renew-agent-submit    | 67 ++++++++++++++++------
483b06
 ipaserver/install/cainstance.py                    |  8 ++-
483b06
 ipaserver/install/dogtaginstance.py                | 15 +++--
483b06
 3 files changed, 63 insertions(+), 27 deletions(-)
483b06
483b06
diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
483b06
index 51b0880c5b57758845e2ffa0c9545bbca7e8c751..7b5489555d069856a6da7a21b5ab2b0f4dd4a41c 100755
483b06
--- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit
483b06
+++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
483b06
@@ -193,10 +193,18 @@ def call_handler(_handler, *args, **kwargs):
483b06
 
483b06
     return result
483b06
 
483b06
-def request_cert():
483b06
+
483b06
+def request_cert(reuse_existing, **kwargs):
483b06
     """
483b06
     Request certificate from IPA CA.
483b06
     """
483b06
+    if reuse_existing:
483b06
+        cert = os.environ.get('CERTMONGER_CERTIFICATE')
483b06
+        if cert:
483b06
+            return (ISSUED, cert)
483b06
+        else:
483b06
+            return (REJECTED, "New certificate requests not supported")
483b06
+
483b06
     syslog.syslog(syslog.LOG_NOTICE,
483b06
                   "Forwarding request to dogtag-ipa-renew-agent")
483b06
 
483b06
@@ -231,7 +239,8 @@ def request_cert():
483b06
     else:
483b06
         return (rc, stdout)
483b06
 
483b06
-def store_cert():
483b06
+
483b06
+def store_cert(**kwargs):
483b06
     """
483b06
     Store certificate in LDAP.
483b06
     """
483b06
@@ -292,7 +301,8 @@ def store_cert():
483b06
 
483b06
     return (ISSUED, cert)
483b06
 
483b06
-def request_and_store_cert():
483b06
+
483b06
+def request_and_store_cert(**kwargs):
483b06
     """
483b06
     Request certificate from IPA CA and store it in LDAP.
483b06
     """
483b06
@@ -318,7 +328,7 @@ def request_and_store_cert():
483b06
         else:
483b06
             os.environ['CERTMONGER_CA_COOKIE'] = cookie
483b06
 
483b06
-        result = call_handler(request_cert)
483b06
+        result = call_handler(request_cert, **kwargs)
483b06
         if result[0] == WAIT:
483b06
             return (result[0], 'request:%s' % result[1])
483b06
         elif result[0] == WAIT_WITH_DELAY:
483b06
@@ -337,7 +347,7 @@ def request_and_store_cert():
483b06
         os.environ['CERTMONGER_CA_COOKIE'] = cookie
483b06
     os.environ['CERTMONGER_CERTIFICATE'] = cert
483b06
 
483b06
-    result = call_handler(store_cert)
483b06
+    result = call_handler(store_cert, **kwargs)
483b06
     if result[0] == WAIT:
483b06
         return (result[0], 'store:%s:%s' % (cert, result[1]))
483b06
     elif result[0] == WAIT_WITH_DELAY:
483b06
@@ -345,7 +355,8 @@ def request_and_store_cert():
483b06
     else:
483b06
         return result
483b06
 
483b06
-def retrieve_or_reuse_cert():
483b06
+
483b06
+def retrieve_or_reuse_cert(**kwargs):
483b06
     """
483b06
     Retrieve certificate from LDAP. If the certificate is not available, reuse
483b06
     the old certificate.
483b06
@@ -373,7 +384,8 @@ def retrieve_or_reuse_cert():
483b06
 
483b06
     return (ISSUED, cert)
483b06
 
483b06
-def retrieve_cert_continuous():
483b06
+
483b06
+def retrieve_cert_continuous(reuse_existing, **kwargs):
483b06
     """
483b06
     Retrieve new certificate from LDAP. Repeat every eight hours until the
483b06
     certificate is available.
483b06
@@ -382,8 +394,10 @@ def retrieve_cert_continuous():
483b06
     if old_cert:
483b06
         old_cert = x509.normalize_certificate(old_cert)
483b06
 
483b06
-    result = call_handler(retrieve_or_reuse_cert)
483b06
-    if result[0] != ISSUED:
483b06
+    result = call_handler(retrieve_or_reuse_cert,
483b06
+                          reuse_existing=reuse_existing,
483b06
+                          **kwargs)
483b06
+    if result[0] != ISSUED or reuse_existing:
483b06
         return result
483b06
 
483b06
     new_cert = x509.normalize_certificate(result[1])
483b06
@@ -394,17 +408,19 @@ def retrieve_cert_continuous():
483b06
 
483b06
     return result
483b06
 
483b06
-def retrieve_cert():
483b06
+
483b06
+def retrieve_cert(**kwargs):
483b06
     """
483b06
     Retrieve new certificate from LDAP.
483b06
     """
483b06
-    result = call_handler(retrieve_cert_continuous)
483b06
+    result = call_handler(retrieve_cert_continuous, **kwargs)
483b06
     if result[0] == WAIT_WITH_DELAY:
483b06
         return (REJECTED, "Updated certificate not available")
483b06
 
483b06
     return result
483b06
 
483b06
-def export_csr():
483b06
+
483b06
+def export_csr(**kwargs):
483b06
     """
483b06
     This does not actually renew the cert, it just writes the CSR provided
483b06
     by certmonger to /var/lib/ipa/ca.csr and returns the existing cert.
483b06
@@ -430,7 +446,8 @@ def export_csr():
483b06
 
483b06
     return (ISSUED, cert)
483b06
 
483b06
-def renew_ca_cert():
483b06
+
483b06
+def renew_ca_cert(reuse_existing, **kwargs):
483b06
     """
483b06
     This is used for automatic CA certificate renewal.
483b06
     """
483b06
@@ -443,7 +460,7 @@ def renew_ca_cert():
483b06
     if operation == 'SUBMIT':
483b06
         state = 'retrieve'
483b06
 
483b06
-        if is_self_signed and is_renewal_master():
483b06
+        if is_self_signed and not reuse_existing and is_renewal_master():
483b06
             state = 'request'
483b06
     elif operation == 'POLL':
483b06
         cookie = os.environ.get('CERTMONGER_CA_COOKIE')
483b06
@@ -460,8 +477,10 @@ def renew_ca_cert():
483b06
         return (OPERATION_NOT_SUPPORTED_BY_HELPER,)
483b06
 
483b06
     if state == 'retrieve':
483b06
-        result = call_handler(retrieve_cert)
483b06
-        if result[0] == REJECTED and not is_self_signed:
483b06
+        result = call_handler(retrieve_cert,
483b06
+                              reuse_existing=reuse_existing,
483b06
+                              **kwargs)
483b06
+        if result[0] == REJECTED and not is_self_signed and not reuse_existing:
483b06
             syslog.syslog(syslog.LOG_ALERT,
483b06
                           "Certificate with subject '%s' is about to expire, "
483b06
                           "use ipa-cacert-manage to renew it"
483b06
@@ -469,7 +488,9 @@ def renew_ca_cert():
483b06
     elif state == 'request':
483b06
         profile = os.environ['CERTMONGER_CA_PROFILE']
483b06
         os.environ['CERTMONGER_CA_PROFILE'] = 'caCACert'
483b06
-        result = call_handler(request_and_store_cert)
483b06
+        result = call_handler(request_and_store_cert,
483b06
+                              reuse_existing=reuse_existing,
483b06
+                              **kwargs)
483b06
         os.environ['CERTMONGER_CA_PROFILE'] = profile
483b06
 
483b06
     if result[0] == WAIT:
483b06
@@ -480,6 +501,16 @@ def renew_ca_cert():
483b06
         return result
483b06
 
483b06
 def main():
483b06
+    kwargs = {
483b06
+        'reuse_existing': False,
483b06
+    }
483b06
+    try:
483b06
+        sys.argv.remove('--reuse-existing')
483b06
+    except ValueError:
483b06
+        pass
483b06
+    else:
483b06
+        kwargs['reuse_existing'] = True
483b06
+
483b06
     handlers = {
483b06
         'ipaStorage':           store_cert,
483b06
         'ipaRetrievalOrReuse':  retrieve_or_reuse_cert,
483b06
@@ -515,7 +546,7 @@ def main():
483b06
             handler = request_cert
483b06
         handler = handlers.get(profile, handler)
483b06
 
483b06
-        res = call_handler(handler)
483b06
+        res = call_handler(handler, **kwargs)
483b06
         for item in res[1:]:
483b06
             print(item)
483b06
         return res[0]
483b06
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
483b06
index 546e1b7b39b323bbaeae3fb57d31ea4152d5e418..ff5432d1a7460f1b853c7cf7490b3604c82cd1f7 100644
483b06
--- a/ipaserver/install/cainstance.py
483b06
+++ b/ipaserver/install/cainstance.py
483b06
@@ -964,9 +964,11 @@ class CAInstance(DogtagInstance):
483b06
         obj = bus.get_object('org.fedorahosted.certmonger',
483b06
                              '/org/fedorahosted/certmonger')
483b06
         iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
483b06
-        path = iface.find_ca_by_nickname('dogtag-ipa-ca-renew-agent')
483b06
-        if path:
483b06
-            iface.remove_known_ca(path)
483b06
+        for suffix in ['', '-reuse']:
483b06
+            name = 'dogtag-ipa-ca-renew-agent' + suffix
483b06
+            path = iface.find_ca_by_nickname(name)
483b06
+            if path:
483b06
+                iface.remove_known_ca(path)
483b06
 
483b06
         cmonger.stop()
483b06
 
483b06
diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py
483b06
index 356358adf1b60e236ce821fb44a77ca5f8c1942f..e0515973f7a598b30c6f12675b9ebdbfd0cf3423 100644
483b06
--- a/ipaserver/install/dogtaginstance.py
483b06
+++ b/ipaserver/install/dogtaginstance.py
483b06
@@ -265,12 +265,15 @@ class DogtagInstance(service.Service):
483b06
         obj = bus.get_object('org.fedorahosted.certmonger',
483b06
                              '/org/fedorahosted/certmonger')
483b06
         iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
483b06
-        path = iface.find_ca_by_nickname('dogtag-ipa-ca-renew-agent')
483b06
-        if not path:
483b06
-            iface.add_known_ca(
483b06
-                'dogtag-ipa-ca-renew-agent',
483b06
-                paths.DOGTAG_IPA_CA_RENEW_AGENT_SUBMIT,
483b06
-                dbus.Array([], dbus.Signature('s')))
483b06
+        for suffix, args in [('', ''), ('-reuse', ' --reuse-existing')]:
483b06
+            name = 'dogtag-ipa-ca-renew-agent' + suffix
483b06
+            path = iface.find_ca_by_nickname(name)
483b06
+            if not path:
483b06
+                command = paths.DOGTAG_IPA_CA_RENEW_AGENT_SUBMIT + args
483b06
+                iface.add_known_ca(
483b06
+                    name,
483b06
+                    command,
483b06
+                    dbus.Array([], dbus.Signature('s')))
483b06
 
483b06
     def __get_pin(self):
483b06
         try:
483b06
-- 
483b06
2.9.3
483b06