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