Skip to content

Commit

Permalink
Do not renew externally-signed CA as self-signed
Browse files Browse the repository at this point in the history
Commit 49cf5ec fixed a bug that
prevented migration from externally-signed to self-signed IPA CA.
But it introduced a subtle new issue: certmonger-initiated renewal
renews an externally-signed IPA CA as a self-signed CA.

To resolve this issue, introduce the `--force-self-signed' flag for
the dogtag-ipa-ca-renew-agent script.  Add another certmonger CA
definition that calls this script with the `--force-self-signed'
flag.  Update dogtag-ipa-ca-renew-agent to only issue a self-signed
CA certificate if the existing certificate is self-signed or if
`--force-self-signed' was given.  Update `ipa-cacert-manage renew'
to supply `--force-self-signed' when appropriate.

As a result of these changes, certmonger-initiated renewal of an
externally-signed IPA CA certificate will not issue a self-signed
certificate.

Fixes: https://pagure.io/freeipa/issue/8176
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
  • Loading branch information
frasertweedale committed Jan 30, 2020
1 parent 78827db commit 4b55136
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 10 deletions.
14 changes: 12 additions & 2 deletions install/certmonger/dogtag-ipa-ca-renew-agent-submit.in
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ def retrieve_cert(**kwargs):
return result


def renew_ca_cert(reuse_existing, **kwargs):
def renew_ca_cert(reuse_existing, force_self_signed, **kwargs):
"""
This is used for automatic CA certificate renewal.
"""
Expand All @@ -420,7 +420,8 @@ def renew_ca_cert(reuse_existing, **kwargs):
if operation == 'SUBMIT':
state = 'retrieve'

if not reuse_existing and is_renewal_master():
if (is_self_signed or force_self_signed) \
and not reuse_existing and is_renewal_master():
state = 'request'

csr_file = paths.IPA_CA_CSR
Expand Down Expand Up @@ -473,14 +474,23 @@ def renew_ca_cert(reuse_existing, **kwargs):
def main():
kwargs = {
'reuse_existing': False,
'force_self_signed': False,
}

try:
sys.argv.remove('--reuse-existing')
except ValueError:
pass
else:
kwargs['reuse_existing'] = True

try:
sys.argv.remove('--force-self-signed')
except ValueError:
pass
else:
kwargs['force_self_signed'] = True

operation = os.environ.get('CERTMONGER_OPERATION')
if operation not in ('SUBMIT', 'POLL'):
return OPERATION_NOT_SUPPORTED_BY_HELPER
Expand Down
1 change: 1 addition & 0 deletions ipalib/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,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'
RENEWAL_SELFSIGNED_CA_NAME = 'dogtag-ipa-ca-renew-agent-selfsigned'
# The RA agent cert is used for client cert authentication. In the past IPA
# used caServerCert profile, which adds clientAuth and serverAuth EKU. The
# serverAuth EKU caused trouble with NamedConstraints, see RHBZ#1670239.
Expand Down
4 changes: 2 additions & 2 deletions ipaserver/install/cainstance.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ def configure_instance(self, host_name, dm_password, admin_password,
if self.external != 1:
if not has_ra_cert:
self.step("configure certmonger for renewals",
self.configure_certmonger_renewal)
self.configure_certmonger_renewal_helpers)
if not self.clone:
self.step("requesting RA certificate from CA", self.__request_ra_certificate)
elif promote:
Expand Down Expand Up @@ -998,7 +998,7 @@ def uninstall(self):
obj = bus.get_object('org.fedorahosted.certmonger',
'/org/fedorahosted/certmonger')
iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
for suffix in ['', '-reuse']:
for suffix in ['', '-reuse', '-selfsigned']:
name = ipalib.constants.RENEWAL_CA_NAME + suffix
path = iface.find_ca_by_nickname(name)
if path:
Expand Down
8 changes: 6 additions & 2 deletions ipaserver/install/dogtaginstance.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ def http_proxy(self):
fd.write(template)
os.fchmod(fd.fileno(), 0o644)

def configure_certmonger_renewal(self):
def configure_certmonger_renewal_helpers(self):
"""
Create a new CA type for certmonger that will retrieve updated
certificates from the dogtag master server.
Expand All @@ -306,7 +306,11 @@ def configure_certmonger_renewal(self):
obj = bus.get_object('org.fedorahosted.certmonger',
'/org/fedorahosted/certmonger')
iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
for suffix, args in [('', ''), ('-reuse', ' --reuse-existing')]:
for suffix, args in [
('', ''),
('-reuse', ' --reuse-existing'),
('-selfsigned', ' --force-self-signed'),
]:
name = RENEWAL_CA_NAME + suffix
path = iface.find_ca_by_nickname(name)
if not path:
Expand Down
6 changes: 4 additions & 2 deletions ipaserver/install/ipa_cacert_manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
from optparse import OptionGroup # pylint: disable=deprecated-module
import gssapi

from ipalib.constants import RENEWAL_CA_NAME, RENEWAL_REUSE_CA_NAME, IPA_CA_CN
from ipalib.constants import (
RENEWAL_CA_NAME, RENEWAL_REUSE_CA_NAME, RENEWAL_SELFSIGNED_CA_NAME,
IPA_CA_CN)
from ipalib.install import certmonger, certstore
from ipapython import admintool, ipautil
from ipapython.certdb import (EMPTY_TRUST_FLAGS,
Expand Down Expand Up @@ -223,7 +225,7 @@ def renew_self_signed(self, ca):
except errors.NotFound:
raise admintool.ScriptError("CA renewal master not found")

self.resubmit_request()
self.resubmit_request(RENEWAL_SELFSIGNED_CA_NAME)

db = certs.CertDB(api.env.realm, nssdir=paths.PKI_TOMCAT_ALIAS_DIR)
cert = db.get_cert_from_db(self.cert_nickname)
Expand Down
2 changes: 1 addition & 1 deletion ipaserver/install/krainstance.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def configure_instance(self, realm_name, host_name, dm_password,
self.step("enabling ephemeral requests", self.enable_ephemeral)
self.step("restarting KRA", self.restart_instance)
self.step("configure certmonger for renewals",
self.configure_certmonger_renewal)
self.configure_certmonger_renewal_helpers)
self.step("configure certificate renewals", self.configure_renewal)
self.step("configure HTTP to proxy connections",
self.http_proxy)
Expand Down
4 changes: 3 additions & 1 deletion ipaserver/install/server/upgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,9 @@ def certificate_renewal_update(ca, kra, ds, http):
Update certmonger certificate renewal configuration.
"""

# First ensure the renewal helpers are defined.
ca.configure_certmonger_renewal_helpers()

template = paths.CERTMONGER_COMMAND_TEMPLATE
serverid = ipaldap.realm_to_serverid(api.env.realm)

Expand Down Expand Up @@ -1148,7 +1151,6 @@ def certificate_renewal_update(ca, kra, ds, http):
logger.info("Removing %s", filename)
ipautil.remove_file(filename)

ca.configure_certmonger_renewal()
ca.configure_renewal()
ca.configure_agent_renewal()
ca.add_lightweight_ca_tracking_requests()
Expand Down

0 comments on commit 4b55136

Please sign in to comment.