acme: delete ACME RA account on server uninstall

For each CA server, a Dogtag user account is created for the ACME
service to use to authenticate to the CA subsystem.  This commit
cleans up the Dogtag account upon server uninstallation.

The user deletion behaviour is extracted to a common method used for
both ACME RA account deletion (on uninstall) and removal of the
temporary admin account (during replica install).

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

Reviewed-By: Rob Crittenden <rcritten@redhat.com>
This commit is contained in:
Fraser Tweedale 2020-07-01 16:43:08 +10:00 committed by Rob Crittenden
parent 525b946b75
commit 1f72056027
3 changed files with 64 additions and 13 deletions

View File

@ -1517,6 +1517,11 @@ class CAInstance(DogtagInstance):
logger.debug("Successfully updated CRL")
api.Backend.ra.override_port = None
@staticmethod
def acme_uid(fqdn: str) -> str:
"""Compute ACME RA account uid."""
return f'acme-{fqdn}'
def setup_acme(self) -> bool:
"""
Set up ACME service, if needed.
@ -1537,7 +1542,7 @@ class CAInstance(DogtagInstance):
# create ACME agent group (if not exist already) and user
self.ensure_group(ACME_AGENT_GROUP, "ACME RA accounts")
acme_user = f"acme-{self.fqdn}"
acme_user = self.acme_uid(self.fqdn)
result = self.create_user(
uid=acme_user,
cn=acme_user,

View File

@ -621,6 +621,47 @@ class DogtagInstance(service.Service):
return password
@staticmethod
def delete_user(uid: str) -> bool:
"""
Delete the user, removing group memberships along the way.
Return True if user was deleted or False if user entry
did not exist.
"""
dn = _person_dn(uid)
if not api.Backend.ldap2.isconnected():
api.Backend.ldap2.connect()
# remove group memberships
try:
entries = api.Backend.ldap2.get_entries(
OU_GROUPS_DN, filter=f'(uniqueMember={dn})')
except errors.EmptyResult:
entries = []
except errors.NotFound:
# basedn not found; Dogtag is probably not installed.
# Let's ignore this and keep going.
entries = []
for entry in entries:
# remove the uniquemember value
entry['uniquemember'] = [
v for v in entry['uniquemember']
if DN(v) != dn
]
api.Backend.ldap2.update_entry(entry)
# delete user entry
try:
api.Backend.ldap2.delete_entry(dn)
except errors.NotFound:
return False
else:
return True
def setup_admin(self):
self.admin_user = "admin-%s" % self.fqdn
self.admin_password = ipautil.ipa_generate_password()
@ -681,18 +722,8 @@ class DogtagInstance(service.Service):
attrvalue=self.admin_dn
)
def __remove_admin_from_group(self, group):
mod = [(ldap.MOD_DELETE, 'uniqueMember', self.admin_dn)]
try:
api.Backend.ldap2.modify_s(_group_dn(group), mod)
except ldap.NO_SUCH_ATTRIBUTE:
# already removed
pass
def teardown_admin(self):
for group in self.admin_groups:
self.__remove_admin_from_group(group)
api.Backend.ldap2.delete_entry(self.admin_dn)
self.delete_user(self.admin_user)
def backup_config(self):
"""

View File

@ -40,7 +40,7 @@ from ipaserver.install import (
adtrust, bindinstance, ca, dns, dsinstance,
httpinstance, installutils, kra, krbinstance,
otpdinstance, custodiainstance, replication, service,
sysupgrade)
sysupgrade, cainstance)
from ipaserver.install.installutils import (
IPA_MODULES, BadHostError, get_fqdn, get_server_ip_address,
is_ipa_configured, load_pkcs12, read_password, verify_fqdn,
@ -319,6 +319,19 @@ def remove_master_from_managed_topology(api_instance, options):
logger.warning("Failed to delete master: %s", e)
def cleanup_dogtag_server_specific_data():
"""
There are data in Dogtag database related to specific servers.
Some of these data should be left alone, e.g. range assignments.
Some of these data should be cleaned up; that's what this
subroutine does.
"""
# remove ACME user
acme_uid = cainstance.CAInstance.acme_uid(api.env.host)
cainstance.CAInstance.delete_user(acme_uid)
@common_cleanup
def install_check(installer):
options = installer
@ -1103,6 +1116,8 @@ def uninstall_check(installer):
ca.uninstall_check(options)
cleanup_dogtag_server_specific_data()
if domain_level == DOMAIN_LEVEL_0:
rm = replication.ReplicationManager(
realm=api.env.realm,