URL: https://github.com/freeipa/freeipa/pull/5378
Author: abbra
 Title: #5378: [Backport][ipa-4-9] Fix uninstall without dns
Action: opened

PR body:
"""
This PR was opened automatically because PR #5376 was pushed to master and 
backport to ipa-4-9 is required.
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/5378/head:pr5378
git checkout pr5378
From d1d75e3f96c730c0ed3dfe47ea8c6634669e3ca7 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <aboko...@redhat.com>
Date: Tue, 22 Dec 2020 09:11:51 +0200
Subject: [PATCH 1/3] opendnssecinstance: use late binding for UID/GID
 resolution

Move actual resolution of UID/GID values for 'ods' and 'named' entities
to the code that needs them. This prevents failures when uninstalling
IPA server set up without DNS feature. In particular, 'named' group is
created when 'bind' package is installed and if 'bind' package is not
installed, uninstall fails in OpenDNSSEC instance constructor.

We use common pattern for all services during uninstall:

 svc = SVCClass(..)
 if svc.is_configured()
     svc.uninstall()

This requires that the class constructor should not rely on artifacts
that only exist when the service is configured.

Fixes: https://pagure.io/freeipa/issue/8630

Signed-off-by: Alexander Bokovoy <aboko...@redhat.com>
---
 ipaserver/install/opendnssecinstance.py | 30 ++++++++++++++-----------
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/ipaserver/install/opendnssecinstance.py b/ipaserver/install/opendnssecinstance.py
index 415e7710ed1..6d5557f24c7 100644
--- a/ipaserver/install/opendnssecinstance.py
+++ b/ipaserver/install/opendnssecinstance.py
@@ -67,9 +67,6 @@ def __init__(self, fstore=None):
             self, "ods-enforcerd",
             service_desc="OpenDNSSEC enforcer daemon",
         )
-        self.named_gid = constants.NAMED_GROUP.gid
-        self.ods_uid = constants.ODS_USER.uid
-        self.ods_gid = constants.ODS_GROUP.gid
         self.conf_file_dict = {
             'SOFTHSM_LIB': paths.LIBSOFTHSM2_SO,
             'TOKEN_LABEL': SOFTHSM_DNSSEC_TOKEN_LABEL,
@@ -194,8 +191,8 @@ def __setup_conf_files(self):
                                       quotes=False, separator='=')
 
     def __setup_ownership_file_modes(self):
-        assert self.ods_uid is not None
-        assert self.ods_gid is not None
+        assert constants.ODS_USER.uid is not None
+        assert constants.ODS_GROUP.gid is not None
 
         # workarounds for packaging bugs in opendnssec-1.4.5-2.fc20.x86_64
         # https://bugzilla.redhat.com/show_bug.cgi?id=1098188
@@ -204,24 +201,25 @@ def __setup_ownership_file_modes(self):
                 dir_path = os.path.join(root, directory)
                 os.chmod(dir_path, 0o770)
                 # chown to root:ods
-                os.chown(dir_path, 0, self.ods_gid)
+                os.chown(dir_path, 0, constants.ODS_GROUP.gid)
             for filename in files:
                 file_path = os.path.join(root, filename)
                 os.chmod(file_path, 0o660)
                 # chown to root:ods
-                os.chown(file_path, 0, self.ods_gid)
+                os.chown(file_path, 0, constants.ODS_GROUP.gid)
 
         for (root, dirs, files) in os.walk(paths.VAR_OPENDNSSEC_DIR):
             for directory in dirs:
                 dir_path = os.path.join(root, directory)
                 os.chmod(dir_path, 0o770)
                 # chown to ods:ods
-                os.chown(dir_path, self.ods_uid, self.ods_gid)
+                constants.ODS_USER.chown(dir_path, gid=constants.ODS_GROUP.gid)
             for filename in files:
                 file_path = os.path.join(root, filename)
                 os.chmod(file_path, 0o660)
                 # chown to ods:ods
-                os.chown(file_path, self.ods_uid, self.ods_gid)
+                constants.ODS_USER.chown(file_path,
+                                         gid=constants.ODS_GROUP.gid)
 
     def __generate_master_key(self):
 
@@ -242,11 +240,15 @@ def __generate_master_key(self):
                 for directory in dirs:
                     dir_path = os.path.join(root, directory)
                     os.chmod(dir_path, 0o770 | stat.S_ISGID)
-                    os.chown(dir_path, self.ods_uid, self.named_gid)  # chown to ods:named
+                    # chown to ods:named
+                    constants.ODS_USER.chown(dir_path,
+                                             gid=constants.NAMED_GROUP.gid)
                 for filename in files:
                     file_path = os.path.join(root, filename)
                     os.chmod(file_path, 0o660 | stat.S_ISGID)
-                    os.chown(file_path, self.ods_uid, self.named_gid)  # chown to ods:named
+                    # chown to ods:named
+                    constants.ODS_USER.chown(file_path,
+                                             gid=constants.NAMED_GROUP.gid)
 
         finally:
             p11.finalize()
@@ -266,7 +268,8 @@ def __setup_dnssec(self):
             # copy user specified kasp.db to proper location and set proper
             # privileges
             shutil.copy(self.kasp_db_file, paths.OPENDNSSEC_KASP_DB)
-            os.chown(paths.OPENDNSSEC_KASP_DB, self.ods_uid, self.ods_gid)
+            constants.ODS_USER.chown(paths.OPENDNSSEC_KASP_DB,
+                                     gid=constants.ODS_GROUP.gid)
             os.chmod(paths.OPENDNSSEC_KASP_DB, 0o660)
 
         else:
@@ -290,7 +293,8 @@ def __start(self):
             )
             with open(paths.OPENDNSSEC_ZONELIST_FILE, 'w') as f:
                 f.write(result.output)
-                os.fchown(f.fileno(), self.ods_uid, self.ods_gid)
+                constants.ODS_USER.chown(f.fileno(),
+                                         gid=constants.ODS_GROUP.gid)
                 os.fchmod(f.fileno(), 0o660)
 
     def uninstall(self):

From d2e3e9750d009bac9fac7a6e051285660827337e Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <aboko...@redhat.com>
Date: Tue, 22 Dec 2020 09:20:52 +0200
Subject: [PATCH 2/3] dnskeysyncinstance: use late binding for UID/GID
 resolution

Move actual resolution of UID/GID values for 'ods' and 'named' entities
to the code that needs them. This prevents failures when uninstalling
IPA server set up without DNS feature. In particular, 'named' group is
created when 'bind' package is installed and if 'bind' package is not
installed, uninstall fails in OpenDNSSEC instance constructor.

We use common pattern for all services during uninstall:

 svc = SVCClass(..)
 if svc.is_configured()
     svc.uninstall()

This requires that the class constructor should not rely on artifacts
that only exist when the service is configured.

Fixes: https://pagure.io/freeipa/issue/8630

Signed-off-by: Alexander Bokovoy <aboko...@redhat.com>
---
 ipaserver/install/dnskeysyncinstance.py | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/ipaserver/install/dnskeysyncinstance.py b/ipaserver/install/dnskeysyncinstance.py
index 16870b73b5c..b5eca31da79 100644
--- a/ipaserver/install/dnskeysyncinstance.py
+++ b/ipaserver/install/dnskeysyncinstance.py
@@ -55,10 +55,6 @@ def __init__(self, fstore=None, logger=logger):
             keytab=paths.IPA_DNSKEYSYNCD_KEYTAB
         )
         self.extra_config = [u'dnssecVersion 1', ]  # DNSSEC enabled
-        self.named_uid = constants.NAMED_USER.uid
-        self.named_gid = constants.NAMED_GROUP.gid
-        self.ods_uid = constants.ODS_USER.uid
-        self.ods_gid = constants.ODS_GROUP.gid
 
     suffix = ipautil.dn_attribute_property('_suffix')
 
@@ -78,7 +74,7 @@ def set_dyndb_ldap_workdir_permissions(self):
             else:
                 os.chmod(directory, 0o770)
             # dnssec daemons require to have access into the directory
-            os.chown(directory, self.named_uid, self.named_gid)
+            constants.NAMED_USER.chown(directory, gid=constants.NAMED_GROUP.gid)
 
     def remove_replica_public_keys(self, replica_fqdn):
         ldap = api.Backend.ldap2
@@ -180,7 +176,7 @@ def setup_named_openssl_conf(self):
             )
             with open(paths.DNSSEC_OPENSSL_CONF, 'w') as f:
                 os.fchmod(f.fileno(), 0o640)
-                os.fchown(f.fileno(), 0, self.named_gid)
+                os.fchown(f.fileno(), 0, gid=constants.NAMED_GROUP.gid)
                 f.write(named_openssl_txt)
 
     def setup_named_sysconfig(self):
@@ -235,7 +231,8 @@ def __setup_softhsm(self):
             os.mkdir(paths.IPA_DNSSEC_DIR)
             os.chmod(paths.IPA_DNSSEC_DIR, 0o770)
             # chown ods:named
-            os.chown(paths.IPA_DNSSEC_DIR, self.ods_uid, self.named_gid)
+            constants.ODS_USER.chown(paths.IPA_DNSSEC_DIR,
+                                     gid=constants.NAMED_GROUP.gid)
 
         # setup softhsm2 config file
         softhsm_conf_txt = ("# SoftHSM v2 configuration file \n"
@@ -272,7 +269,8 @@ def __setup_softhsm(self):
         os.mkdir(paths.DNSSEC_TOKENS_DIR)
         os.chmod(paths.DNSSEC_TOKENS_DIR, 0o770 | stat.S_ISGID)
         # chown to ods:named
-        os.chown(paths.DNSSEC_TOKENS_DIR, self.ods_uid, self.named_gid)
+        constants.ODS_USER.chown(paths.DNSSEC_TOKENS_DIR,
+                                 gid=constants.NAMED_GROUP.gid)
 
         # generate PINs for softhsm
         pin_length = 30  # Bind allows max 32 bytes including ending '\0'
@@ -284,7 +282,7 @@ def __setup_softhsm(self):
         logger.debug("Saving user PIN to %s", paths.DNSSEC_SOFTHSM_PIN)
         with open(paths.DNSSEC_SOFTHSM_PIN, 'w') as f:
             # chown to ods:named
-            os.fchown(f.fileno(), self.ods_uid, self.named_gid)
+            constants.ODS_USER.chown(f.fileno(), gid=constants.NAMED_GROUP.gid)
             os.fchmod(f.fileno(), 0o660)
             f.write(pin)
 
@@ -419,12 +417,14 @@ def __setup_replica_keys(self):
                 dir_path = os.path.join(root, directory)
                 os.chmod(dir_path, 0o770 | stat.S_ISGID)
                 # chown to ods:named
-                os.chown(dir_path, self.ods_uid, self.named_gid)
+                constants.ODS_USER.chown(dir_path,
+                                         gid=constants.NAMED_GROUP.gid)
             for filename in files:
                 file_path = os.path.join(root, filename)
                 os.chmod(file_path, 0o660 | stat.S_ISGID)
                 # chown to ods:named
-                os.chown(file_path, self.ods_uid, self.named_gid)
+                constants.ODS_USER.chown(file_path,
+                                         gid=constants.NAMED_GROUP.gid)
 
     def __enable(self):
         try:
@@ -449,7 +449,7 @@ def __setup_principal(self):
             dnssynckey_principal_dn = p
 
         # Make sure access is strictly reserved to the named user
-        os.chown(self.keytab, 0, self.ods_gid)
+        os.chown(self.keytab, 0, constants.ODS_GROUP.gid)
         os.chmod(self.keytab, 0o440)
 
         dns_group = DN(('cn', 'DNS Servers'), ('cn', 'privileges'),

From a7c92d60d768ada3ecb021e5b68cc726b1bdbbed Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <aboko...@redhat.com>
Date: Tue, 22 Dec 2020 09:25:01 +0200
Subject: [PATCH 3/3] odsexporterinstance: use late binding for UID/GID
 resolution

Move actual resolution of UID/GID values for 'ods' entities to the code
that needs them. This prevents failures when uninstalling IPA server set
up without DNS feature. In particular, 'ods' user and group are created
when 'opendnssec' package is installed and if 'opendnssec' package is
not installed, uninstall fails in OpenDNSSEC Exporter instance
constructor.

We use common pattern of checking the service during uninstall:

 svc = SVCClass()
 if svc.is_configured():
    svc.uninstall()

Thus, service class constructor must not do UID/GID resolution

Fixes: https://pagure.io/freeipa/issue/8630

Signed-off-by: Alexander Bokovoy <aboko...@redhat.com>
---
 ipaserver/install/odsexporterinstance.py | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/ipaserver/install/odsexporterinstance.py b/ipaserver/install/odsexporterinstance.py
index d9fa46d0a36..414705b6ed9 100644
--- a/ipaserver/install/odsexporterinstance.py
+++ b/ipaserver/install/odsexporterinstance.py
@@ -31,8 +31,6 @@ def __init__(self, fstore=None):
             keytab=paths.IPA_ODS_EXPORTER_KEYTAB,
             service_prefix=u'ipa-ods-exporter'
         )
-        self.ods_uid = constants.ODS_USER.uid
-        self.ods_gid = constants.ODS_GROUP.gid
         self.enable_if_exists = False
 
     suffix = ipautil.dn_attribute_property('_suffix')
@@ -71,7 +69,7 @@ def __setup_key_exporter(self):
                                    quotes=False, separator='=')
 
     def __setup_principal(self):
-        assert self.ods_uid is not None
+        assert constants.ODS_GROUP.gid is not None
 
         for f in [paths.IPA_ODS_EXPORTER_CCACHE, self.keytab]:
             try:
@@ -95,7 +93,7 @@ def __setup_principal(self):
 
         # Make sure access is strictly reserved to the ods user
         os.chmod(self.keytab, 0o440)
-        os.chown(self.keytab, 0, self.ods_gid)
+        os.chown(self.keytab, 0, constants.ODS_GROUP.gid)
 
         dns_group = DN(('cn', 'DNS Servers'), ('cn', 'privileges'),
                        ('cn', 'pbac'), self.suffix)
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/freeipa-devel@lists.fedorahosted.org

Reply via email to