mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Clean up more files and directories created by the installer(s)
Ideally all files created during an IPA server installation are removed by the uninstaller. Some files are purposefully left, like token passwords, private keys, logs and more. Add an allow list for those files. Include a test to catch any additional files that may be created and left behind. Fixes: https://pagure.io/freeipa/issue/8080 Signed-off-by: Rob Crittenden <rcritten@redhat.com> Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
This commit is contained in:
committed by
Florence Blanc-Renaud
parent
60c127d197
commit
9e364910f5
@@ -3455,7 +3455,7 @@ def uninstall(options):
|
||||
# - sssd was removed after install and before uninstall
|
||||
# - there are no active domains
|
||||
# in both cases we cannot continue with SSSD
|
||||
pass
|
||||
all_domains = []
|
||||
|
||||
if hostname is None:
|
||||
hostname = FQDN
|
||||
@@ -3514,7 +3514,9 @@ def uninstall(options):
|
||||
if result.returncode != 0:
|
||||
logger.error("Unenrolling host failed: %s", result.error_log)
|
||||
|
||||
if os.path.exists(paths.IPA_DEFAULT_CONF):
|
||||
if os.path.exists(paths.IPA_DEFAULT_CONF) and os.path.exists(
|
||||
paths.KRB5_KEYTAB
|
||||
):
|
||||
logger.info(
|
||||
"Removing Kerberos service principals from /etc/krb5.keytab")
|
||||
try:
|
||||
@@ -3566,6 +3568,18 @@ def uninstall(options):
|
||||
# Clean up the SSSD cache before SSSD service is stopped or restarted
|
||||
remove_file(paths.SSSD_MC_GROUP)
|
||||
remove_file(paths.SSSD_MC_PASSWD)
|
||||
remove_file(paths.SSSD_MC_INITGROUPS)
|
||||
remove_file(paths.SSSD_MC_SID)
|
||||
|
||||
for root, _dirs, files in os.walk(paths.SSSD_PIPES):
|
||||
for file in files:
|
||||
remove_file(os.path.join(root, file))
|
||||
|
||||
for domain in all_domains:
|
||||
name = f"domain_realm_{domain.replace('.', '_')}"
|
||||
filename = os.path.join(paths.SSSD_PUBCONF_KRB5_INCLUDE_D_DIR, name)
|
||||
if os.path.exists(filename):
|
||||
remove_file(filename)
|
||||
|
||||
if was_sssd_installed:
|
||||
try:
|
||||
@@ -3585,6 +3599,14 @@ def uninstall(options):
|
||||
sssd_ccache_file = os.path.join(paths.SSSD_DB, sssd_domain_ccache)
|
||||
remove_file(sssd_ccache_file)
|
||||
|
||||
remove_file(paths.SSSD_LDB)
|
||||
remove_file(paths.SSSD_CONFIG_LDB)
|
||||
remove_file(paths.SSSD_SECRETS)
|
||||
|
||||
sssd_timestamps = "timestamps_" + ipa_domain + ".ldb"
|
||||
sssd_timestamps_file = os.path.join(paths.SSSD_DB, sssd_timestamps)
|
||||
remove_file(sssd_timestamps_file)
|
||||
|
||||
# Next if-elif-elif construction deals with sssd.conf file.
|
||||
# Old pre-IPA domains are preserved due merging the old sssd.conf
|
||||
# during the installation of ipa-client but any new domains are
|
||||
@@ -3745,6 +3767,7 @@ def uninstall(options):
|
||||
|
||||
# Remove the IPA configuration file
|
||||
remove_file(paths.IPA_DEFAULT_CONF)
|
||||
remove_file(paths.IPA_DEFAULT_CONF + '.ipabkp')
|
||||
|
||||
# Remove misc backups
|
||||
remove_file(paths.OPENLDAP_LDAP_CONF + '.ipabkp')
|
||||
|
||||
@@ -251,6 +251,7 @@ class BasePathNamespace:
|
||||
CERTMONGER_DOGTAG_SUBMIT = "/usr/libexec/certmonger/dogtag-submit"
|
||||
IPA_SERVER_GUARD = "/usr/libexec/certmonger/ipa-server-guard"
|
||||
GENERATE_RNDC_KEY = "/usr/libexec/generate-rndc-key.sh"
|
||||
RNDC_KEY = "/etc/rndc.key"
|
||||
LIBEXEC_IPA_DIR = "/usr/libexec/ipa"
|
||||
IPA_DNSKEYSYNCD_REPLICA = "/usr/libexec/ipa/ipa-dnskeysync-replica"
|
||||
IPA_DNSKEYSYNCD = "/usr/libexec/ipa/ipa-dnskeysyncd"
|
||||
@@ -325,6 +326,7 @@ class BasePathNamespace:
|
||||
IPA_KASP_DB_BACKUP = "/var/lib/ipa/ipa-kasp.db.backup"
|
||||
DNSSEC_TOKENS_DIR = "/var/lib/ipa/dnssec/tokens"
|
||||
DNSSEC_SOFTHSM_PIN = "/var/lib/ipa/dnssec/softhsm_pin"
|
||||
DNSSEC_ENGINE_SOCK = "/run/opendnssec/engine.sock"
|
||||
IPA_CA_CSR = "/var/lib/ipa/ca.csr"
|
||||
IPA_CACERT_MANAGE = "/usr/sbin/ipa-cacert-manage"
|
||||
IPA_CERTUPDATE = "/usr/sbin/ipa-certupdate"
|
||||
@@ -349,6 +351,11 @@ class BasePathNamespace:
|
||||
SSSD_MC_GROUP = "/var/lib/sss/mc/group"
|
||||
SSSD_MC_PASSWD = "/var/lib/sss/mc/passwd"
|
||||
SSSD_MC_INITGROUPS = "/var/lib/sss/mc/initgroups"
|
||||
SSSD_MC_SID = "/var/lib/sss/mc/sid"
|
||||
SSSD_PIPES = "/var/lib/sss/pipes"
|
||||
SSSD_LDB = "/var/lib/sss/db/sssd.ldb"
|
||||
SSSD_CONFIG_LDB = "/var/lib/sss/db/config.ldb"
|
||||
SSSD_SECRETS = "/var/lib/sss/secrets/secrets.ldb"
|
||||
SSSD_PUBCONF_DIR = "/var/lib/sss/pubconf"
|
||||
SSSD_PUBCONF_KNOWN_HOSTS = "/var/lib/sss/pubconf/known_hosts"
|
||||
SSSD_PUBCONF_KRB5_INCLUDE_D_DIR = "/var/lib/sss/pubconf/krb5.include.d/"
|
||||
|
||||
@@ -369,6 +369,7 @@ class BaseTaskNamespace:
|
||||
|
||||
os.unlink(paths.SYSTEMD_RESOLVED_IPA_CONF)
|
||||
knownservices["systemd-resolved"].reload_or_restart()
|
||||
ipautil.remove_directory(paths.SYSTEMD_RESOLVED_CONF_DIR)
|
||||
|
||||
def configure_pkcs11_modules(self, fstore):
|
||||
"""Disable p11-kit modules
|
||||
|
||||
@@ -1658,9 +1658,16 @@ def remove_ccache(ccache_path=None, run_as=None):
|
||||
"Failed to clear Kerberos credentials cache: %s", e)
|
||||
|
||||
|
||||
def remove_file(filename):
|
||||
def remove_file(filename, only_if_empty=False):
|
||||
"""Remove a file and log any exceptions raised.
|
||||
|
||||
:only_if_empty: only remove the file if empty. Default False.
|
||||
"""
|
||||
if only_if_empty and os.path.exists(filename):
|
||||
file_stat = os.stat(filename)
|
||||
if file_stat.st_size > 0:
|
||||
logger.debug('%s is not empty.', filename)
|
||||
return
|
||||
try:
|
||||
os.unlink(filename)
|
||||
except Exception as e:
|
||||
@@ -1669,6 +1676,15 @@ def remove_file(filename):
|
||||
logger.error('Error removing %s: %s', filename, str(e))
|
||||
|
||||
|
||||
def remove_directory(dir):
|
||||
"""Remove an empty directory."""
|
||||
try:
|
||||
os.rmdir(dir)
|
||||
except OSError as e:
|
||||
if e.errno not in {errno.ENOENT, errno.ENOTEMPTY}:
|
||||
logger.error("Failed to remove directory %s", dir)
|
||||
|
||||
|
||||
def rmtree(path):
|
||||
"""
|
||||
Remove a directory structure and log any exceptions raised.
|
||||
|
||||
@@ -1347,5 +1347,16 @@ class BindInstance(service.Service):
|
||||
ipautil.remove_file(paths.NAMED_CONF_BAK)
|
||||
ipautil.remove_file(paths.NAMED_CUSTOM_CONF)
|
||||
ipautil.remove_file(paths.NAMED_CUSTOM_OPTIONS_CONF)
|
||||
ipautil.remove_file(paths.NAMED_LOGGING_OPTIONS_CONF)
|
||||
ipautil.remove_file(paths.RNDC_KEY)
|
||||
ipautil.remove_file(
|
||||
os.path.join(paths.NAMED_VAR_DIR, "_default.tsigkeys")
|
||||
)
|
||||
try:
|
||||
while self.fstore.restore_file(self.keytab):
|
||||
pass
|
||||
except ValueError:
|
||||
pass
|
||||
ipautil.remove_keytab(self.keytab)
|
||||
|
||||
ipautil.remove_ccache(run_as=self.service_user)
|
||||
|
||||
@@ -1112,6 +1112,9 @@ class CAInstance(DogtagInstance):
|
||||
logger.warning("Error while removing CRL publish "
|
||||
"directory: %s", e)
|
||||
|
||||
ipautil.remove_file(paths.DOGTAG_ADMIN_P12)
|
||||
ipautil.remove_file(paths.CACERT_P12)
|
||||
|
||||
def unconfigure_certmonger_renewal_guard(self):
|
||||
if not self.is_configured():
|
||||
return
|
||||
|
||||
@@ -147,6 +147,7 @@ class CustodiaInstance(SimpleServiceInstance):
|
||||
})
|
||||
keystore.remove_server_keys_file()
|
||||
ipautil.remove_file(self.config_file)
|
||||
ipautil.remove_file(paths.IPA_CUSTODIA_SOCKET)
|
||||
sysupgrade.set_upgrade_state('custodia', 'installed', False)
|
||||
|
||||
def __gen_keys(self):
|
||||
|
||||
@@ -511,6 +511,9 @@ class DNSKeySyncInstance(service.Service):
|
||||
# do not delete *so pin*, user can need it to get token data
|
||||
ipautil.remove_file(paths.DNSSEC_SOFTHSM_PIN)
|
||||
ipautil.remove_file(paths.DNSSEC_SOFTHSM2_CONF)
|
||||
ipautil.remove_file(paths.DNSSEC_OPENSSL_CONF)
|
||||
|
||||
ipautil.rmtree(paths.IPA_DNSSEC_DIR)
|
||||
|
||||
try:
|
||||
shutil.rmtree(paths.DNSSEC_TOKENS_DIR)
|
||||
|
||||
@@ -1103,6 +1103,11 @@ class DsInstance(service.Service):
|
||||
except ipautil.CalledProcessError:
|
||||
logger.error("Failed to remove DS instance. You may "
|
||||
"need to remove instance data manually")
|
||||
destfile = paths.SLAPD_INSTANCE_SYSTEMD_IPA_ENV_TEMPLATE % (
|
||||
serverid
|
||||
)
|
||||
ipautil.remove_file(destfile)
|
||||
ipautil.remove_directory(os.path.dirname(destfile))
|
||||
|
||||
else:
|
||||
logger.error("Failed to remove DS instance. No serverid present "
|
||||
|
||||
@@ -23,7 +23,6 @@ from __future__ import absolute_import
|
||||
import logging
|
||||
import os
|
||||
import glob
|
||||
import errno
|
||||
import shlex
|
||||
import shutil
|
||||
import tempfile
|
||||
@@ -571,14 +570,13 @@ class HTTPInstance(service.Service):
|
||||
for filename in remove_files:
|
||||
ipautil.remove_file(filename)
|
||||
|
||||
try:
|
||||
os.rmdir(paths.SYSTEMD_SYSTEM_HTTPD_D_DIR)
|
||||
except OSError as e:
|
||||
if e.errno not in {errno.ENOENT, errno.ENOTEMPTY}:
|
||||
logger.error(
|
||||
"Failed to remove directory %s",
|
||||
paths.SYSTEMD_SYSTEM_HTTPD_D_DIR
|
||||
)
|
||||
ipautil.remove_file(paths.HTTPD_NSS_CONF, only_if_empty=True)
|
||||
|
||||
for d in (
|
||||
paths.SYSTEMD_SYSTEM_HTTPD_D_DIR,
|
||||
paths.HTTPD_ALIAS_DIR
|
||||
):
|
||||
ipautil.remove_directory(d)
|
||||
|
||||
# Restore SELinux boolean states
|
||||
boolean_states = {name: self.restore_state(name)
|
||||
@@ -595,6 +593,14 @@ class HTTPInstance(service.Service):
|
||||
if enabled:
|
||||
self.enable()
|
||||
|
||||
ipautil.run(
|
||||
[paths.SYSTEMCTL, 'disable', 'ipa-ccache-sweep.timer']
|
||||
)
|
||||
ipautil.remove_file(paths.IPA_CCACHE_SWEEPER_GSSPROXY_SOCK)
|
||||
|
||||
for filename in os.listdir(paths.IPA_CCACHES):
|
||||
ipautil.remove_file(os.path.join(paths.IPA_CCACHES, filename))
|
||||
|
||||
def stop_tracking_certificates(self):
|
||||
try:
|
||||
certmonger.stop_tracking(certfile=paths.HTTPD_CERT_FILE)
|
||||
|
||||
@@ -79,6 +79,11 @@ class KRAInstance(DogtagInstance):
|
||||
config=paths.KRA_CS_CFG_PATH,
|
||||
)
|
||||
|
||||
def uninstall(self):
|
||||
DogtagInstance.uninstall(self)
|
||||
|
||||
ipautil.remove_file(paths.KRACERT_P12)
|
||||
|
||||
def configure_instance(self, realm_name, host_name, dm_password,
|
||||
admin_password, pkcs12_info=None, master_host=None,
|
||||
subject_base=None, ca_subject=None,
|
||||
|
||||
@@ -663,3 +663,7 @@ class KrbInstance(service.Service):
|
||||
|
||||
self.kpasswd = KpasswdInstance()
|
||||
self.kpasswd.uninstall()
|
||||
|
||||
ipautil.remove_file(paths.KRB5_KEYTAB)
|
||||
ipautil.remove_file(paths.KRB5_FREEIPA)
|
||||
ipautil.remove_file(paths.KRB5_FREEIPA_SERVER)
|
||||
|
||||
@@ -365,3 +365,5 @@ class OpenDNSSECInstance(service.Service):
|
||||
|
||||
if running:
|
||||
self.restart()
|
||||
|
||||
ipautil.remove_file(paths.DNSSEC_ENGINE_SOCK)
|
||||
|
||||
@@ -1326,6 +1326,9 @@ def uninstall(installer):
|
||||
logger.warning("Failed to remove file %s: %s",
|
||||
paths.IPA_RENEWAL_LOCK, e)
|
||||
|
||||
ipautil.remove_file(paths.SVC_LIST_FILE)
|
||||
ipautil.rmtree('/root/.cache/ipa')
|
||||
|
||||
print("Removing IPA client configuration")
|
||||
try:
|
||||
result = run([paths.IPA_CLIENT_INSTALL, "--on-master",
|
||||
|
||||
@@ -12,6 +12,7 @@ pieces if possible.
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from difflib import unified_diff
|
||||
import os
|
||||
|
||||
from ipatests.test_integration.base import IntegrationTest
|
||||
@@ -137,3 +138,82 @@ class TestUninstallWithoutDNS(IntegrationTest):
|
||||
related: https://pagure.io/freeipa/issue/8630
|
||||
"""
|
||||
tasks.uninstall_master(self.master)
|
||||
|
||||
|
||||
class TestUninstallCleanup(IntegrationTest):
|
||||
"""Test installer hostname validator."""
|
||||
|
||||
num_replicas = 0
|
||||
before = None
|
||||
after = None
|
||||
|
||||
@classmethod
|
||||
def install(cls, mh):
|
||||
# These create files on first start
|
||||
for svc in ('certmonger', 'sssd',):
|
||||
cls.master.run_command(['systemctl', 'start', svc])
|
||||
cls.before = cls.master.run_command(
|
||||
"find /etc/ /run/ /var/ /root/ -mount | sort"
|
||||
).stdout_text.split('\n')
|
||||
tasks.install_master(cls.master, setup_dns=True,
|
||||
setup_kra=True)
|
||||
tasks.install_dns(
|
||||
cls.master,
|
||||
extra_args=['--dnssec-master', '--no-dnssec-validation']
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def uninstall(cls, mh):
|
||||
pass
|
||||
|
||||
def test_clean_uninstall(self):
|
||||
tasks.uninstall_master(self.master)
|
||||
self.after = self.master.run_command(
|
||||
"find /etc/ /run/ /var/ /root/ -mount | sort"
|
||||
).stdout_text.split('\n')
|
||||
|
||||
diff = unified_diff(self.before, self.after,
|
||||
fromfile='before', tofile='after')
|
||||
ALLOW_LIST = [
|
||||
'/var/log',
|
||||
'/var/tmp/systemd-private',
|
||||
'/run/systemd',
|
||||
'/var/lib/authselect/backups/pre_ipaclient',
|
||||
'/var/named/data/named.run',
|
||||
paths.DNSSEC_SOFTHSM_PIN_SO, # See commit eb54814741
|
||||
'/etc/selinux/targeted/contexts/files/file_contexts.local.bin',
|
||||
paths.SSSD_CONF_DELETED, # See commit dd72ed6212
|
||||
'/root/.cache',
|
||||
'/root/.dogtag',
|
||||
'/root/.local',
|
||||
'/run/dirsrv',
|
||||
'/run/lock/dirsrv',
|
||||
'/var/lib/authselect/backups',
|
||||
'/var/lib/gssproxy/rcache/krb5_0.rcache2',
|
||||
'/var/lib/ipa/ipa-kasp.db.backup',
|
||||
'/var/lib/selinux/targeted/active/booleans.local',
|
||||
'/var/lib/selinux/targeted/active/file_contexts.local',
|
||||
'/var/lib/sss/pubconf/krb5.include.d/krb5_libdefaults',
|
||||
'/var/lib/sss/pubconf/krb5.include.d/localauth_plugin',
|
||||
'/var/named/dynamic/managed-keys.bind',
|
||||
'/var/named/dynamic/managed-keys.bind.jnl',
|
||||
]
|
||||
|
||||
leftovers = []
|
||||
for line in diff:
|
||||
line = line.strip()
|
||||
if line.startswith('+'):
|
||||
if line.endswith('log'):
|
||||
continue
|
||||
if line.startswith('+++ after'):
|
||||
continue
|
||||
found = False
|
||||
for s in ALLOW_LIST:
|
||||
if s in line:
|
||||
found = True
|
||||
break
|
||||
if found:
|
||||
continue
|
||||
leftovers.append(line)
|
||||
|
||||
assert len(leftovers) == 0
|
||||
|
||||
Reference in New Issue
Block a user