mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-01-26 16:16:31 -06:00
renew agent: allow reusing existing certs
Add a switch which makes `dogtag-ipa-ca-renew-agent-submit` reuse the existing certificate rather than request a new one from the CA while maintaining LDAP replication of the certificate. Make this available as a new `dogtag-ipa-ca-renew-agent-reuse` certmonger CA. This allows redoing the LDAP replication and reexecuting pre- and post-save commands of a tracking request without reissuing the certificate. https://pagure.io/freeipa/issue/5799 Reviewed-By: David Kupka <dkupka@redhat.com> Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
This commit is contained in:
parent
09a49ad458
commit
25aeeaf46d
@ -193,10 +193,18 @@ def call_handler(_handler, *args, **kwargs):
|
||||
|
||||
return result
|
||||
|
||||
def request_cert():
|
||||
|
||||
def request_cert(reuse_existing, **kwargs):
|
||||
"""
|
||||
Request certificate from IPA CA.
|
||||
"""
|
||||
if reuse_existing:
|
||||
cert = os.environ.get('CERTMONGER_CERTIFICATE')
|
||||
if cert:
|
||||
return (ISSUED, cert)
|
||||
else:
|
||||
return (REJECTED, "New certificate requests not supported")
|
||||
|
||||
syslog.syslog(syslog.LOG_NOTICE,
|
||||
"Forwarding request to dogtag-ipa-renew-agent")
|
||||
|
||||
@ -231,7 +239,8 @@ def request_cert():
|
||||
else:
|
||||
return (rc, stdout)
|
||||
|
||||
def store_cert():
|
||||
|
||||
def store_cert(**kwargs):
|
||||
"""
|
||||
Store certificate in LDAP.
|
||||
"""
|
||||
@ -292,7 +301,8 @@ def store_cert():
|
||||
|
||||
return (ISSUED, cert)
|
||||
|
||||
def request_and_store_cert():
|
||||
|
||||
def request_and_store_cert(**kwargs):
|
||||
"""
|
||||
Request certificate from IPA CA and store it in LDAP.
|
||||
"""
|
||||
@ -318,7 +328,7 @@ def request_and_store_cert():
|
||||
else:
|
||||
os.environ['CERTMONGER_CA_COOKIE'] = cookie
|
||||
|
||||
result = call_handler(request_cert)
|
||||
result = call_handler(request_cert, **kwargs)
|
||||
if result[0] == WAIT:
|
||||
return (result[0], 'request:%s' % result[1])
|
||||
elif result[0] == WAIT_WITH_DELAY:
|
||||
@ -337,7 +347,7 @@ def request_and_store_cert():
|
||||
os.environ['CERTMONGER_CA_COOKIE'] = cookie
|
||||
os.environ['CERTMONGER_CERTIFICATE'] = cert
|
||||
|
||||
result = call_handler(store_cert)
|
||||
result = call_handler(store_cert, **kwargs)
|
||||
if result[0] == WAIT:
|
||||
return (result[0], 'store:%s:%s' % (cert, result[1]))
|
||||
elif result[0] == WAIT_WITH_DELAY:
|
||||
@ -345,7 +355,8 @@ def request_and_store_cert():
|
||||
else:
|
||||
return result
|
||||
|
||||
def retrieve_or_reuse_cert():
|
||||
|
||||
def retrieve_or_reuse_cert(**kwargs):
|
||||
"""
|
||||
Retrieve certificate from LDAP. If the certificate is not available, reuse
|
||||
the old certificate.
|
||||
@ -373,7 +384,8 @@ def retrieve_or_reuse_cert():
|
||||
|
||||
return (ISSUED, cert)
|
||||
|
||||
def retrieve_cert_continuous():
|
||||
|
||||
def retrieve_cert_continuous(reuse_existing, **kwargs):
|
||||
"""
|
||||
Retrieve new certificate from LDAP. Repeat every eight hours until the
|
||||
certificate is available.
|
||||
@ -382,8 +394,10 @@ def retrieve_cert_continuous():
|
||||
if old_cert:
|
||||
old_cert = x509.normalize_certificate(old_cert)
|
||||
|
||||
result = call_handler(retrieve_or_reuse_cert)
|
||||
if result[0] != ISSUED:
|
||||
result = call_handler(retrieve_or_reuse_cert,
|
||||
reuse_existing=reuse_existing,
|
||||
**kwargs)
|
||||
if result[0] != ISSUED or reuse_existing:
|
||||
return result
|
||||
|
||||
new_cert = x509.normalize_certificate(result[1])
|
||||
@ -394,17 +408,19 @@ def retrieve_cert_continuous():
|
||||
|
||||
return result
|
||||
|
||||
def retrieve_cert():
|
||||
|
||||
def retrieve_cert(**kwargs):
|
||||
"""
|
||||
Retrieve new certificate from LDAP.
|
||||
"""
|
||||
result = call_handler(retrieve_cert_continuous)
|
||||
result = call_handler(retrieve_cert_continuous, **kwargs)
|
||||
if result[0] == WAIT_WITH_DELAY:
|
||||
return (REJECTED, "Updated certificate not available")
|
||||
|
||||
return result
|
||||
|
||||
def export_csr():
|
||||
|
||||
def export_csr(**kwargs):
|
||||
"""
|
||||
This does not actually renew the cert, it just writes the CSR provided
|
||||
by certmonger to /var/lib/ipa/ca.csr and returns the existing cert.
|
||||
@ -430,7 +446,8 @@ def export_csr():
|
||||
|
||||
return (ISSUED, cert)
|
||||
|
||||
def renew_ca_cert():
|
||||
|
||||
def renew_ca_cert(reuse_existing, **kwargs):
|
||||
"""
|
||||
This is used for automatic CA certificate renewal.
|
||||
"""
|
||||
@ -443,7 +460,7 @@ def renew_ca_cert():
|
||||
if operation == 'SUBMIT':
|
||||
state = 'retrieve'
|
||||
|
||||
if is_self_signed and is_renewal_master():
|
||||
if is_self_signed and not reuse_existing and is_renewal_master():
|
||||
state = 'request'
|
||||
elif operation == 'POLL':
|
||||
cookie = os.environ.get('CERTMONGER_CA_COOKIE')
|
||||
@ -460,8 +477,10 @@ def renew_ca_cert():
|
||||
return (OPERATION_NOT_SUPPORTED_BY_HELPER,)
|
||||
|
||||
if state == 'retrieve':
|
||||
result = call_handler(retrieve_cert)
|
||||
if result[0] == REJECTED and not is_self_signed:
|
||||
result = call_handler(retrieve_cert,
|
||||
reuse_existing=reuse_existing,
|
||||
**kwargs)
|
||||
if result[0] == REJECTED and not is_self_signed and not reuse_existing:
|
||||
syslog.syslog(syslog.LOG_ALERT,
|
||||
"Certificate with subject '%s' is about to expire, "
|
||||
"use ipa-cacert-manage to renew it"
|
||||
@ -469,7 +488,9 @@ def renew_ca_cert():
|
||||
elif state == 'request':
|
||||
profile = os.environ['CERTMONGER_CA_PROFILE']
|
||||
os.environ['CERTMONGER_CA_PROFILE'] = 'caCACert'
|
||||
result = call_handler(request_and_store_cert)
|
||||
result = call_handler(request_and_store_cert,
|
||||
reuse_existing=reuse_existing,
|
||||
**kwargs)
|
||||
os.environ['CERTMONGER_CA_PROFILE'] = profile
|
||||
|
||||
if result[0] == WAIT:
|
||||
@ -480,6 +501,16 @@ def renew_ca_cert():
|
||||
return result
|
||||
|
||||
def main():
|
||||
kwargs = {
|
||||
'reuse_existing': False,
|
||||
}
|
||||
try:
|
||||
sys.argv.remove('--reuse-existing')
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
kwargs['reuse_existing'] = True
|
||||
|
||||
handlers = {
|
||||
'ipaStorage': store_cert,
|
||||
'ipaRetrievalOrReuse': retrieve_or_reuse_cert,
|
||||
@ -515,7 +546,7 @@ def main():
|
||||
handler = request_cert
|
||||
handler = handlers.get(profile, handler)
|
||||
|
||||
res = call_handler(handler)
|
||||
res = call_handler(handler, **kwargs)
|
||||
for item in res[1:]:
|
||||
print(item)
|
||||
return res[0]
|
||||
|
@ -964,9 +964,11 @@ class CAInstance(DogtagInstance):
|
||||
obj = bus.get_object('org.fedorahosted.certmonger',
|
||||
'/org/fedorahosted/certmonger')
|
||||
iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
|
||||
path = iface.find_ca_by_nickname('dogtag-ipa-ca-renew-agent')
|
||||
if path:
|
||||
iface.remove_known_ca(path)
|
||||
for suffix in ['', '-reuse']:
|
||||
name = 'dogtag-ipa-ca-renew-agent' + suffix
|
||||
path = iface.find_ca_by_nickname(name)
|
||||
if path:
|
||||
iface.remove_known_ca(path)
|
||||
|
||||
cmonger.stop()
|
||||
|
||||
|
@ -253,12 +253,15 @@ class DogtagInstance(service.Service):
|
||||
obj = bus.get_object('org.fedorahosted.certmonger',
|
||||
'/org/fedorahosted/certmonger')
|
||||
iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
|
||||
path = iface.find_ca_by_nickname('dogtag-ipa-ca-renew-agent')
|
||||
if not path:
|
||||
iface.add_known_ca(
|
||||
'dogtag-ipa-ca-renew-agent',
|
||||
paths.DOGTAG_IPA_CA_RENEW_AGENT_SUBMIT,
|
||||
dbus.Array([], dbus.Signature('s')))
|
||||
for suffix, args in [('', ''), ('-reuse', ' --reuse-existing')]:
|
||||
name = 'dogtag-ipa-ca-renew-agent' + suffix
|
||||
path = iface.find_ca_by_nickname(name)
|
||||
if not path:
|
||||
command = paths.DOGTAG_IPA_CA_RENEW_AGENT_SUBMIT + args
|
||||
iface.add_known_ca(
|
||||
name,
|
||||
command,
|
||||
dbus.Array([], dbus.Signature('s')))
|
||||
|
||||
def __get_pin(self):
|
||||
try:
|
||||
|
Loading…
Reference in New Issue
Block a user