diff --git a/.gitignore b/.gitignore index 3912c13..a08d1d6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/freeipa-4.9.10.tar.gz +SOURCES/freeipa-4.9.11.tar.gz diff --git a/.ipa.metadata b/.ipa.metadata index 81f398b..f1dac03 100644 --- a/.ipa.metadata +++ b/.ipa.metadata @@ -1 +1 @@ -8f2b6a7f52348421fa7c67048dd5ae454f2642fb SOURCES/freeipa-4.9.10.tar.gz +4ef188d43f5f2a09e214dd2bae68595a5977bb61 SOURCES/freeipa-4.9.11.tar.gz diff --git a/SOURCES/0001-ipa-otpd-Fix-build-on-older-versions-of-gcc.patch b/SOURCES/0001-ipa-otpd-Fix-build-on-older-versions-of-gcc.patch deleted file mode 100644 index 4852df8..0000000 --- a/SOURCES/0001-ipa-otpd-Fix-build-on-older-versions-of-gcc.patch +++ /dev/null @@ -1,33 +0,0 @@ -From ff54fe2fdfbab11e08a138cdfd0da900ee865e3d Mon Sep 17 00:00:00 2001 -From: Rafael Guterres Jeffman -Date: Fri, 17 Jun 2022 11:22:32 -0300 -Subject: [PATCH] ipa-otpd: Fix build on older versions of gcc. - -Older versions of gcc do not support unnamed parameters. - -This patch fixes the build on older gcc by applying the same idiom for -unsued parameters as used by other functions in the same module. - -Signed-off-by: Rafael Guterres Jeffman ---- - daemons/ipa-otpd/oauth2.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/daemons/ipa-otpd/oauth2.c b/daemons/ipa-otpd/oauth2.c -index df1ffd50d..11d5c135f 100644 ---- a/daemons/ipa-otpd/oauth2.c -+++ b/daemons/ipa-otpd/oauth2.c -@@ -319,8 +319,9 @@ static int check_access_token_reply(struct child_ctx *child_ctx, - return ret; - } - --static void oauth2_on_child_readable(verto_ctx *, verto_ev *ev) -+static void oauth2_on_child_readable(verto_ctx *vctx, verto_ev *ev) - { -+ (void)vctx; /* Unused */ - static char buf[10240]; - ssize_t io = 0; - struct child_ctx *child_ctx = NULL; --- -2.36.1 - diff --git a/SOURCES/0001-updates-fix-memberManager-ACI-to-allow-managers-from-a-specified-group_rhbz#2056009.patch b/SOURCES/0001-updates-fix-memberManager-ACI-to-allow-managers-from-a-specified-group_rhbz#2056009.patch new file mode 100644 index 0000000..ecbb24f --- /dev/null +++ b/SOURCES/0001-updates-fix-memberManager-ACI-to-allow-managers-from-a-specified-group_rhbz#2056009.patch @@ -0,0 +1,41 @@ +From 651e28c1fb6b86ad1fbd4ea98644e00b7042499c Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Dec 02 2022 12:21:22 +0000 +Subject: updates: fix memberManager ACI to allow managers from a specified group + + +The original implementation of the member manager added support for both +user and group managers but left out upgrade scenario. This means when +upgrading existing installation a manager whose rights defined by the +group membership would not be able to add group members until the ACI is +fixed. + +Remove old ACI and add a full one during upgrade step. + +Fixes: https://pagure.io/freeipa/issue/9286 +Signed-off-by: Alexander Bokovoy +Reviewed-By: Florence Blanc-Renaud + +--- + +diff --git a/install/updates/20-aci.update b/install/updates/20-aci.update +index a168bb9..4a7ba13 100644 +--- a/install/updates/20-aci.update ++++ b/install/updates/20-aci.update +@@ -141,11 +141,13 @@ add:aci:(targetattr = "usercertificate")(version 3.0;acl "selfservice:Users can + + # Allow member managers to modify members of user groups + dn: cn=groups,cn=accounts,$SUFFIX +-add:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaUserGroup)")(version 3.0; acl "Allow member managers to modify members of user groups"; allow (write) userattr = "memberManager#USERDN";) ++remove:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaUserGroup)")(version 3.0; acl "Allow member managers to modify members of user groups"; allow (write) userattr = "memberManager#USERDN";) ++add:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaUserGroup)")(version 3.0; acl "Allow member managers to modify members of user groups"; allow (write) userattr = "memberManager#USERDN" or userattr = "memberManager#GROUPDN";) + + # Allow member managers to modify members of host groups + dn: cn=hostgroups,cn=accounts,$SUFFIX +-add:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaHostGroup)")(version 3.0; acl "Allow member managers to modify members of host groups"; allow (write) userattr = "memberManager#USERDN";) ++remove:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaHostGroup)")(version 3.0; acl "Allow member managers to modify members of host groups"; allow (write) userattr = "memberManager#USERDN";) ++add:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaHostGroup)")(version 3.0; acl "Allow member managers to modify members of host groups"; allow (write) userattr = "memberManager#USERDN" or userattr = "memberManager#GROUPDN";) + + # Hosts can add and delete their own services + dn: cn=services,cn=accounts,$SUFFIX + diff --git a/SOURCES/0002-trust-add-handle-missing-msSFU30MaxGidNumber_rhbz#2162355.patch b/SOURCES/0002-trust-add-handle-missing-msSFU30MaxGidNumber_rhbz#2162355.patch new file mode 100644 index 0000000..965e3bd --- /dev/null +++ b/SOURCES/0002-trust-add-handle-missing-msSFU30MaxGidNumber_rhbz#2162355.patch @@ -0,0 +1,46 @@ +From 703ab8c4dfb7f8fd1540c3849ad469d39695a26f Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Jan 25 2023 16:57:02 +0000 +Subject: trust-add: handle missing msSFU30MaxGidNumber + + +When ipa trust-add is executed with --range-type ad-trust-posix, +the server tries to find the max uidnumber and max gidnumber +from AD domain controller. +The values are extracted from the entry +CN=,CN=ypservers,CN=ypServ30,CN=RpcServices,CN=System, +in the msSFU30MaxUidNumber and msSFU30MaxGidNumber attributes. + +msSFU30MaxUidNumber is required but not msSFU30MaxGidNumber. +In case msSFU30MaxGidNumber is missing, the code is currently assigning +a "None" value and later on evaluates the max between this value and +msSFU30MaxUidNumber. The max function cannot compare None and a list +of string and triggers an exception. + +To avoid the exception, assign [b'0'] to max gid if msSFU30MaxGidNumber +is missing. This way, the comparison succeeds and max returns the +value from msSFU30MaxUidNumber. + +Fixes: https://pagure.io/freeipa/issue/9310 +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Rob Crittenden + +--- + +diff --git a/ipaserver/plugins/trust.py b/ipaserver/plugins/trust.py +index c074f6d..79264b8 100644 +--- a/ipaserver/plugins/trust.py ++++ b/ipaserver/plugins/trust.py +@@ -379,7 +379,10 @@ def add_range(myapi, trustinstance, range_name, dom_sid, *keys, **options): + range_type = u'ipa-ad-trust-posix' + + max_uid = info.get('msSFU30MaxUidNumber') +- max_gid = info.get('msSFU30MaxGidNumber', None) ++ # if max_gid is missing, assume 0 and the max will ++ # be obtained from max_uid. We just checked that ++ # msSFU30MaxUidNumber is defined ++ max_gid = info.get('msSFU30MaxGidNumber', [b'0']) + max_id = int(max(max_uid, max_gid)[0]) + + base_id = int(info.get('msSFU30OrderNumber')[0]) + diff --git a/SOURCES/0003-Backport-latest-test-fixes-python3-ipatests_rhbz#2166929.patch b/SOURCES/0003-Backport-latest-test-fixes-python3-ipatests_rhbz#2166929.patch new file mode 100644 index 0000000..b980ab8 --- /dev/null +++ b/SOURCES/0003-Backport-latest-test-fixes-python3-ipatests_rhbz#2166929.patch @@ -0,0 +1,76 @@ +From e8ef2c2f226704ce510525f07675107179124a95 Mon Sep 17 00:00:00 2001 +From: Sumedh Sidhaye +Date: Feb 02 2023 06:53:56 +0000 +Subject: With the commit #99a74d7, 389-ds changed the message returned in ipa-healthcheck. + + +Previously the message was: + +"\n\nIn Directory Server, we offer one hash suitable for this " +"(PBKDF2_SHA256) and one hash\nfor \"legacy\" support (SSHA512)." +"\n\nYour configuration does not use these for password storage " +"or the root password storage\nscheme.\n" + +but now the message is: + +\n\nIn Directory Server, we offer one hash suitable for this " +"(PBKDF2-SHA512) and one hash\nfor \"legacy\" support (SSHA512)." +"\n\nYour configuration does not use these for password storage " +"or the root password storage\nscheme.\n" + +PBKDF2_SHA256 has been replaced with PBKDF2-SHA512 + +Pagure: https://pagure.io/freeipa/issue/9238 + +Signed-off-by: Sumedh Sidhaye +Reviewed-By: Florence Blanc-Renaud +Reviewed-By: Alexander Bokovoy +Reviewed-By: Stanislav Levin +Reviewed-By: Florence Blanc-Renaud +Reviewed-By: Alexander Bokovoy +Reviewed-By: Stanislav Levin + +--- + +diff --git a/ipatests/test_integration/test_ipahealthcheck.py b/ipatests/test_integration/test_ipahealthcheck.py +index 18a665e..60e8de9 100644 +--- a/ipatests/test_integration/test_ipahealthcheck.py ++++ b/ipatests/test_integration/test_ipahealthcheck.py +@@ -1312,9 +1312,6 @@ class TestIpaHealthCheck(IntegrationTest): + """ + error_msg = ( + "\n\nIn Directory Server, we offer one hash suitable for this " +- "(PBKDF2_SHA256) and one hash\nfor \"legacy\" support (SSHA512)." +- "\n\nYour configuration does not use these for password storage " +- "or the root password storage\nscheme.\n" + ) + returncode, data = run_healthcheck( + self.master, "ipahealthcheck.ds.config", "ConfigCheck", + +From 1bdd8147e7fa1032025dc6f6868e26f285744ee1 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Jan 11 2023 11:56:30 +0000 +Subject: ipatests: mark test_smb as xfail + + +Mark the test test_smb.py::TestSMB::test_smb_service_s4u2self as xfail. + +Related: https://pagure.io/freeipa/issue/9124 +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Alexander Bokovoy + +--- + +diff --git a/ipatests/test_integration/test_smb.py b/ipatests/test_integration/test_smb.py +index eb3981b..30f8d59 100644 +--- a/ipatests/test_integration/test_smb.py ++++ b/ipatests/test_integration/test_smb.py +@@ -349,6 +349,7 @@ class TestSMB(IntegrationTest): + @pytest.mark.skipif( + osinfo.id == 'fedora' and osinfo.version_number <= (31,), + reason='Test requires krb 1.18') ++ @pytest.mark.xfail(reason="Pagure ticket 9124", strict=True) + def test_smb_service_s4u2self(self): + """Test S4U2Self operation by IPA service + against both AD and IPA users + diff --git a/SOURCES/0003-Preserve-user-fix-the-confusing-summary_rhbz#2022028.patch b/SOURCES/0003-Preserve-user-fix-the-confusing-summary_rhbz#2022028.patch deleted file mode 100644 index a7b9808..0000000 --- a/SOURCES/0003-Preserve-user-fix-the-confusing-summary_rhbz#2022028.patch +++ /dev/null @@ -1,131 +0,0 @@ -From ff4152539b96d309dcceaf854a3e0a49f435acff Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Mon, 20 Jun 2022 09:09:11 +0200 -Subject: [PATCH] Preserve user: fix the confusing summary - -When ipa user-del --preserve is called, the command output -prints a summary with: - Deleted user: user1 -although the user was preserved. -Replace the summary with - Preserved user: user1 -to reflect what was actually done. - -Fixes: https://pagure.io/freeipa/issue/9187 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Michal Polovka -Reviewed-By: Rob Crittenden ---- - ipaserver/plugins/user.py | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py -index 25d2bb6aa..fa8a67d3d 100644 ---- a/ipaserver/plugins/user.py -+++ b/ipaserver/plugins/user.py -@@ -56,6 +56,7 @@ from .idviews import remove_ipaobject_overrides - from ipalib.plugable import Registry - from .baseldap import ( - LDAPObject, -+ pkey_to_unicode, - pkey_to_value, - LDAPCreate, - LDAPSearch, -@@ -701,6 +702,7 @@ class user_del(baseuser_del): - __doc__ = _('Delete a user.') - - msg_summary = _('Deleted user "%(value)s"') -+ msg_summary_preserved = _('Preserved user "%(value)s"') - - takes_options = baseuser_del.takes_options + ( - Bool('preserve?', -@@ -831,6 +833,8 @@ class user_del(baseuser_del): - failed.append(pkey_to_value(pkey, options)) - - val = dict(result=dict(failed=failed), value=preserved) -+ val['summary'] = self.msg_summary_preserved % dict( -+ value=pkey_to_unicode(preserved)) - return val - else: - return super(user_del, self).execute(*keys, **options) --- -2.36.1 - -From 4984ff210a169129e4e56b10e54e9c795520855c Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Mon, 20 Jun 2022 09:12:14 +0200 -Subject: [PATCH] xmlrpc tests: updated expected output for preserved user - -Update the expected summary for the command -ipa user-del --preserve - -The command now displays: Preserved user: user1 -instead of Deleted user: user1 - -Related: https://pagure.io/freeipa/issue/9187 - -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Michal Polovka -Reviewed-By: Rob Crittenden ---- - ipatests/test_xmlrpc/test_stageuser_plugin.py | 5 ++++- - ipatests/test_xmlrpc/tracker/user_plugin.py | 7 ++++++- - 2 files changed, 10 insertions(+), 2 deletions(-) - -diff --git a/ipatests/test_xmlrpc/test_stageuser_plugin.py b/ipatests/test_xmlrpc/test_stageuser_plugin.py -index bc606b093..fd146876c 100644 ---- a/ipatests/test_xmlrpc/test_stageuser_plugin.py -+++ b/ipatests/test_xmlrpc/test_stageuser_plugin.py -@@ -479,11 +479,12 @@ class TestActive(XMLRPC_test): - - def test_delete_preserve(self, user): - user.ensure_exists() -- user.track_delete() -+ user.track_delete(preserve=True) - command = user.make_delete_command(no_preserve=False, preserve=True) - result = command() - user.check_delete(result) - -+ user.track_delete(preserve=False) - command = user.make_delete_command() - result = command() - user.check_delete(result) -@@ -622,6 +623,7 @@ class TestCustomAttr(XMLRPC_test): - assert 'BusinessCat' in result['result'][u'businesscategory'] - - # delete the user with --preserve -+ user_customattr.track_delete(preserve=True) - command = user_customattr.make_delete_command(no_preserve=False, - preserve=True) - result = command() -@@ -763,6 +765,7 @@ class TestGroups(XMLRPC_test): - result = command() - group.check_retrieve(result) - -+ user.track_delete(preserve=True) - command = user.make_delete_command(no_preserve=False, preserve=True) - result = command() - user.check_delete(result) -diff --git a/ipatests/test_xmlrpc/tracker/user_plugin.py b/ipatests/test_xmlrpc/tracker/user_plugin.py -index 03c106250..b04be4c19 100644 ---- a/ipatests/test_xmlrpc/tracker/user_plugin.py -+++ b/ipatests/test_xmlrpc/tracker/user_plugin.py -@@ -273,9 +273,14 @@ class UserTracker(CertmapdataMixin, KerberosAliasMixin, Tracker): - - def check_delete(self, result): - """ Check 'user-del' command result """ -+ if u'preserved' in self.attrs and self.attrs[u'preserved']: -+ summary = u'Preserved user "%s"' % self.uid -+ else: -+ summary = u'Deleted user "%s"' % self.uid -+ - assert_deepequal(dict( - value=[self.uid], -- summary=u'Deleted user "%s"' % self.uid, -+ summary=summary, - result=dict(failed=[]), - ), result) - --- -2.36.1 - diff --git a/SOURCES/0004-Only-calculate-LDAP-password-grace-when-the-password_rhbz#782917.patch b/SOURCES/0004-Only-calculate-LDAP-password-grace-when-the-password_rhbz#782917.patch deleted file mode 100644 index 54da08a..0000000 --- a/SOURCES/0004-Only-calculate-LDAP-password-grace-when-the-password_rhbz#782917.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 3675bd1d7aca443832bb9bb2f521cc4d3a088aec Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Wed, 29 Jun 2022 13:25:55 +0000 -Subject: [PATCH] Only calculate LDAP password grace when the password is - expired - -The user's pwd expiration was retrieved but inadvertently was never -compared to current time. So any LDAP bind, including from the -IPA API, counted against the grace period. There is no need to go -through the graceperiod code for non-expired passwords. - -https://pagure.io/freeipa/issue/1539 - -Signed-off-by: Rob Crittenden -Reviewed-By: Florence Blanc-Renaud ---- - .../ipa-graceperiod/ipa_graceperiod.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c b/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c -index 0860b5c20..a3f57cb4b 100644 ---- a/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c -+++ b/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c -@@ -359,7 +359,8 @@ static int ipagraceperiod_preop(Slapi_PBlock *pb) - Slapi_ValueSet *values = NULL; - long grace_limit = 0; - int grace_user_time; -- char *pwd_expiration = NULL; -+ char *tmpstr = NULL; -+ time_t pwd_expiration; - int pwresponse_requested = 0; - Slapi_PBlock *pbtm = NULL; - Slapi_Mods *smods = NULL; -@@ -414,12 +415,17 @@ static int ipagraceperiod_preop(Slapi_PBlock *pb) - } - slapi_value_free(&objectclass); - -- pwd_expiration = slapi_entry_attr_get_charptr(target_entry, "krbPasswordExpiration"); -- if (pwd_expiration == NULL) { -+ tmpstr = slapi_entry_attr_get_charptr(target_entry, "krbPasswordExpiration"); -+ if (tmpstr == NULL) { - /* No expiration means nothing to do */ - LOG_TRACE("No krbPasswordExpiration for %s, nothing to do\n", dn); - goto done; - } -+ pwd_expiration = ipapwd_gentime_to_time_t(tmpstr); -+ if (pwd_expiration > time(NULL)) { -+ /* Not expired, nothing to see here */ -+ goto done; -+ } - - ldrc = ipagraceperiod_getpolicy(target_entry, &policy_entry, - &values, &actual_type_name, --- -2.36.1 - diff --git a/SOURCES/0004-server-install-remove-error-log-about-missing-bkup-file_rhbz#2160389.patch b/SOURCES/0004-server-install-remove-error-log-about-missing-bkup-file_rhbz#2160389.patch new file mode 100644 index 0000000..63a358c --- /dev/null +++ b/SOURCES/0004-server-install-remove-error-log-about-missing-bkup-file_rhbz#2160389.patch @@ -0,0 +1,52 @@ +From 6f50b00953c0000d6da8db0f5e8974ae33d7b5d5 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Jan 16 2023 07:44:50 +0000 +Subject: server install: remove error log about missing bkup file + + +The client installer code can be called in 3 different ways: +- from ipa-client-install CLI +- from ipa-replica-install CLI if the client is not already installed +- from ipa-server-install + +In the last case, the client installer is called with +options.on_master=True +As a result, it's skipping the part that is creating the krb5 +configuration: + if not options.on_master: + nolog = tuple() + configure_krb5_conf(...) + +The configure_krb5_conf method is the place where the krb5.conf file is +backup'ed with the extention ".ipabkp". For a master installation, this +code is not called and the ipabkp file does not exist => delete raises +an error. + +When delete fails because the file does not exist, no need to log an +error message. + +Fixes: https://pagure.io/freeipa/issue/9306 +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Rob Crittenden + +--- + +diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py +index e5d3e82..6e7f17d 100644 +--- a/ipaclient/install/client.py ++++ b/ipaclient/install/client.py +@@ -124,10 +124,9 @@ def cleanup(func): + os.rmdir(ccache_dir) + except OSError: + pass +- try: +- os.remove(krb_name + ".ipabkp") +- except OSError: +- logger.error("Could not remove %s.ipabkp", krb_name) ++ # During master installation, the .ipabkp file is not created ++ # Ignore the delete error if it is "file does not exist" ++ remove_file(krb_name + ".ipabkp") + + return inner + + diff --git a/SOURCES/0005-Add-end-to-end-integration-tests-for-external-IdP.patch b/SOURCES/0005-Add-end-to-end-integration-tests-for-external-IdP.patch deleted file mode 100644 index 700df13..0000000 --- a/SOURCES/0005-Add-end-to-end-integration-tests-for-external-IdP.patch +++ /dev/null @@ -1,346 +0,0 @@ -From 857713c5a9c8e0b62c06dd92e69c09eeb34b2e99 Mon Sep 17 00:00:00 2001 -From: Anuja More -Date: Mon, 23 May 2022 12:26:34 +0530 -Subject: [PATCH] Add end to end integration tests for external IdP - -Added tests for HBAC and SUDO rule and other -test scenarios. - -Related : https://pagure.io/freeipa/issue/8805 -Related: https://pagure.io/freeipa/issue/8803 -Related: https://pagure.io/freeipa/issue/8804 - -Signed-off-by: Anuja More -Reviewed-By: Florence Blanc-Renaud -Reviewed-By: Florence Blanc-Renaud ---- - ipatests/test_integration/test_idp.py | 260 ++++++++++++++++++++++---- - 1 file changed, 226 insertions(+), 34 deletions(-) - -diff --git a/ipatests/test_integration/test_idp.py b/ipatests/test_integration/test_idp.py -index 8f9e92e6a..2ffe6a208 100644 ---- a/ipatests/test_integration/test_idp.py -+++ b/ipatests/test_integration/test_idp.py -@@ -1,6 +1,8 @@ - from __future__ import absolute_import - - import time -+import pytest -+import re - - import textwrap - from ipaplatform.paths import paths -@@ -22,12 +24,12 @@ driver.get(verification_uri) - try: - element = WebDriverWait(driver, 90).until( - EC.presence_of_element_located((By.ID, "username"))) -- driver.find_element_by_id("username").send_keys("testuser1") -- driver.find_element_by_id("password").send_keys("{passwd}") -- driver.find_element_by_id("kc-login").click() -+ driver.find_element(By.ID, "username").send_keys("testuser1") -+ driver.find_element(By.ID, "password").send_keys("{passwd}") -+ driver.find_element(By.ID, "kc-login").click() - element = WebDriverWait(driver, 90).until( - EC.presence_of_element_located((By.ID, "kc-login"))) -- driver.find_element_by_id("kc-login").click() -+ driver.find_element(By.ID, "kc-login").click() - assert "Device Login Successful" in driver.page_source - finally: - now = datetime.now().strftime("%M-%S") -@@ -39,18 +41,12 @@ finally: - def add_user_code(host, verification_uri): - contents = user_code_script.format(uri=verification_uri, - passwd=host.config.admin_password) -- host.put_file_contents("/tmp/add_user_code.py", contents) -- tasks.run_repeatedly( -- host, ['python3', '/tmp/add_user_code.py']) -- -- --def get_verification_uri(host, since, keycloak_server_name): -- command = textwrap.dedent(""" -- journalctl -u ipa-otpd\\* --since="%s" | grep "user_code:" | awk '{ print substr($7,2,9) }'""" % since) # noqa: E501 -- user_code = host.run_command(command).stdout_text.rstrip("\r\n") -- uri = ("https://{0}:8443/auth/realms/master/device?user_code={1}".format( -- keycloak_server_name, user_code)) -- return uri -+ try: -+ host.put_file_contents("/tmp/add_user_code.py", contents) -+ tasks.run_repeatedly( -+ host, ['python3', '/tmp/add_user_code.py']) -+ finally: -+ host.run_command(["rm", "-f", "/tmp/add_user_code.py"]) - - - def kinit_idp(host, user, keycloak_server): -@@ -58,11 +54,14 @@ def kinit_idp(host, user, keycloak_server): - tasks.kdestroy_all(host) - # create armor for FAST - host.run_command(["kinit", "-n", "-c", ARMOR]) -- since = time.strftime('%Y-%m-%d %H:%M:%S') - cmd = ["kinit", "-T", ARMOR, user] -+ - with host.spawn_expect(cmd, default_timeout=100) as e: -- e.expect('Authenticate at .+: ') -- uri = get_verification_uri(host, since, keycloak_server.hostname) -+ e.expect('Authenticate at (.+) and press ENTER.:') -+ prompt = e.get_last_output() -+ uri = re.search(r'Authenticate at (.*?) and press ENTER.:', prompt -+ ).group(1) -+ time.sleep(15) - if uri: - add_user_code(keycloak_server, uri) - e.sendline('\n') -@@ -74,21 +73,27 @@ def kinit_idp(host, user, keycloak_server): - - class TestIDPKeycloak(IntegrationTest): - -- num_replicas = 1 -+ num_replicas = 2 - topology = 'line' - - @classmethod - def install(cls, mh): -- tasks.install_master(cls.master, setup_dns=True) -- tasks.install_client(cls.master, cls.replicas[0]) -- content = cls.master.get_file_contents(paths.IPA_DEFAULT_CONF, -- encoding='utf-8') -- new_content = content + "\noidc_child_debug_level = 10" -- cls.master.put_file_contents(paths.IPA_DEFAULT_CONF, new_content) -+ cls.client = cls.replicas[0] -+ cls.replica = cls.replicas[1] -+ tasks.install_master(cls.master) -+ tasks.install_client(cls.master, cls.replicas[0], -+ extra_args=["--mkhomedir"]) -+ tasks.install_replica(cls.master, cls.replicas[1]) -+ for host in [cls.master, cls.replicas[0], cls.replicas[1]]: -+ content = host.get_file_contents(paths.IPA_DEFAULT_CONF, -+ encoding='utf-8') -+ new_content = content + "\noidc_child_debug_level = 10" -+ host.put_file_contents(paths.IPA_DEFAULT_CONF, new_content) - with tasks.remote_sssd_config(cls.master) as sssd_config: - sssd_config.edit_domain( - cls.master.domain, 'krb5_auth_timeout', 1100) - tasks.clear_sssd_cache(cls.master) -+ tasks.clear_sssd_cache(cls.replicas[0]) - tasks.kinit_admin(cls.master) - cls.master.run_command(["ipa", "config-mod", "--user-auth-type=idp", - "--user-auth-type=password"]) -@@ -97,20 +102,207 @@ class TestIDPKeycloak(IntegrationTest): - cls.replicas[0].run_command(xvfb) - - def test_auth_keycloak_idp(self): -- keycloak_srv = self.replicas[0] -- create_quarkus.setup_keycloakserver(keycloak_srv) -+ """ -+ Test case to check that OAuth 2.0 Device -+ Authorization Grant is working as -+ expected for user configured with external idp. -+ """ -+ create_quarkus.setup_keycloakserver(self.client) - time.sleep(60) -- create_quarkus.setup_keycloak_client(keycloak_srv) -+ create_quarkus.setup_keycloak_client(self.client) - tasks.kinit_admin(self.master) -- cmd = ["ipa", "idp-add", "keycloak", "--provider=keycloak", -+ cmd = ["ipa", "idp-add", "keycloakidp", "--provider=keycloak", - "--client-id=ipa_oidc_client", "--org=master", -- "--base-url={0}:8443/auth".format(keycloak_srv.hostname)] -+ "--base-url={0}:8443/auth".format(self.client.hostname)] - self.master.run_command(cmd, stdin_text="{0}\n{0}".format( -- keycloak_srv.config.admin_password)) -+ self.client.config.admin_password)) - tasks.user_add(self.master, 'keycloakuser', - extra_args=["--user-auth-type=idp", - "--idp-user-id=testuser1@ipa.test", -- "--idp=keycloak"] -+ "--idp=keycloakidp"] - ) -+ list_user = self.master.run_command( -+ ["ipa", "user-find", "--idp-user-id=testuser1@ipa.test"] -+ ) -+ assert "keycloakuser" in list_user.stdout_text -+ list_by_idp = self.master.run_command(["ipa", "user-find", -+ "--idp=keycloakidp"] -+ ) -+ assert "keycloakuser" in list_by_idp.stdout_text -+ list_by_user = self.master.run_command( -+ ["ipa", "user-find", "--idp-user-id=testuser1@ipa.test", "--all"] -+ ) -+ assert "keycloakidp" in list_by_user.stdout_text -+ tasks.clear_sssd_cache(self.master) -+ kinit_idp(self.master, 'keycloakuser', keycloak_server=self.client) -+ -+ @pytest.fixture -+ def hbac_setup_teardown(self): -+ # allow sshd only on given host -+ tasks.kinit_admin(self.master) -+ self.master.run_command(["ipa", "hbacrule-disable", "allow_all"]) -+ self.master.run_command(["ipa", "hbacrule-add", "rule1"]) -+ self.master.run_command(["ipa", "hbacrule-add-user", "rule1", -+ "--users=keycloakuser"] -+ ) -+ self.master.run_command(["ipa", "hbacrule-add-host", "rule1", -+ "--hosts", self.replica.hostname]) -+ self.master.run_command(["ipa", "hbacrule-add-service", "rule1", -+ "--hbacsvcs=sshd"] -+ ) -+ tasks.clear_sssd_cache(self.master) -+ tasks.clear_sssd_cache(self.replica) -+ yield -+ -+ # cleanup -+ tasks.kinit_admin(self.master) -+ self.master.run_command(["ipa", "hbacrule-enable", "allow_all"]) -+ self.master.run_command(["ipa", "hbacrule-del", "rule1"]) -+ -+ def test_auth_hbac(self, hbac_setup_teardown): -+ """ -+ Test case to check that hbacrule is working as -+ expected for user configured with external idp. -+ """ -+ kinit_idp(self.master, 'keycloakuser', keycloak_server=self.client) -+ ssh_cmd = "ssh -q -K -l keycloakuser {0} whoami" -+ valid_ssh = self.master.run_command( -+ ssh_cmd.format(self.replica.hostname)) -+ assert "keycloakuser" in valid_ssh.stdout_text -+ negative_ssh = self.master.run_command( -+ ssh_cmd.format(self.master.hostname), raiseonerr=False -+ ) -+ assert negative_ssh.returncode == 255 -+ -+ def test_auth_sudo_idp(self): -+ """ -+ Test case to check that sudorule is working as -+ expected for user configured with external idp. -+ """ -+ tasks.kdestroy_all(self.master) -+ tasks.kinit_admin(self.master) -+ # rule: keycloakuser are allowed to execute yum on -+ # the client machine as root. -+ cmdlist = [ -+ ["ipa", "sudocmd-add", "/usr/bin/yum"], -+ ["ipa", "sudorule-add", "sudorule"], -+ ['ipa', 'sudorule-add-user', '--users=keycloakuser', -+ 'sudorule'], -+ ['ipa', 'sudorule-add-host', '--hosts', -+ self.client.hostname, 'sudorule'], -+ ['ipa', 'sudorule-add-runasuser', -+ '--users=root', 'sudorule'], -+ ['ipa', 'sudorule-add-allow-command', -+ '--sudocmds=/usr/bin/yum', 'sudorule'], -+ ['ipa', 'sudorule-show', 'sudorule', '--all'], -+ ['ipa', 'sudorule-add-option', -+ 'sudorule', '--sudooption', "!authenticate"] -+ ] -+ for cmd in cmdlist: -+ self.master.run_command(cmd) -+ tasks.clear_sssd_cache(self.master) -+ tasks.clear_sssd_cache(self.client) -+ try: -+ cmd = 'sudo -ll -U keycloakuser' -+ test = self.client.run_command(cmd).stdout_text -+ assert "User keycloakuser may run the following commands" in test -+ assert "/usr/bin/yum" in test -+ kinit_idp(self.client, 'keycloakuser', self.client) -+ test_sudo = 'su -c "sudo yum list wget" keycloakuser' -+ self.client.run_command(test_sudo) -+ list_fail = self.master.run_command(cmd).stdout_text -+ assert "User keycloakuser is not allowed to run sudo" in list_fail -+ finally: -+ tasks.kinit_admin(self.master) -+ self.master.run_command(['ipa', 'sudorule-del', 'sudorule']) -+ self.master.run_command(["ipa", "sudocmd-del", "/usr/bin/yum"]) -+ -+ def test_auth_replica(self): -+ """ -+ Test case to check that OAuth 2.0 Device -+ Authorization is working as expected on replica. -+ """ -+ tasks.clear_sssd_cache(self.master) -+ tasks.clear_sssd_cache(self.replica) -+ tasks.kinit_admin(self.replica) -+ list_user = self.master.run_command( -+ ["ipa", "user-find", "--idp-user-id=testuser1@ipa.test"] -+ ) -+ assert "keycloakuser" in list_user.stdout_text -+ list_by_idp = self.replica.run_command(["ipa", "user-find", -+ "--idp=keycloakidp"] -+ ) -+ assert "keycloakuser" in list_by_idp.stdout_text -+ list_by_user = self.replica.run_command( -+ ["ipa", "user-find", "--idp-user-id=testuser1@ipa.test", "--all"] -+ ) -+ assert "keycloakidp" in list_by_user.stdout_text -+ kinit_idp(self.replica, 'keycloakuser', keycloak_server=self.client) -+ -+ def test_idp_with_services(self): -+ """ -+ Test case to check that services can be configured -+ auth indicator as idp. -+ """ - tasks.clear_sssd_cache(self.master) -- kinit_idp(self.master, 'keycloakuser', keycloak_srv) -+ tasks.kinit_admin(self.master) -+ domain = self.master.domain.name.upper() -+ services = [ -+ "DNS/{0}@{1}".format(self.master.hostname, domain), -+ "HTTP/{0}@{1}".format(self.client.hostname, domain), -+ "dogtag/{0}@{1}".format(self.master.hostname, domain), -+ "ipa-dnskeysyncd/{0}@{1}".format(self.master.hostname, domain) -+ ] -+ try: -+ for service in services: -+ test = self.master.run_command(["ipa", "service-mod", service, -+ "--auth-ind=idp"] -+ ) -+ assert "Authentication Indicators: idp" in test.stdout_text -+ finally: -+ for service in services: -+ self.master.run_command(["ipa", "service-mod", service, -+ "--auth-ind="]) -+ -+ def test_idp_backup_restore(self): -+ """ -+ Test case to check that after restore data is retrieved -+ with related idp configuration. -+ """ -+ tasks.kinit_admin(self.master) -+ user = "backupuser" -+ cmd = ["ipa", "idp-add", "testidp", "--provider=keycloak", -+ "--client-id=ipa_oidc_client", "--org=master", -+ "--base-url={0}:8443/auth".format(self.client.hostname)] -+ self.master.run_command(cmd, stdin_text="{0}\n{0}".format( -+ self.client.config.admin_password)) -+ -+ tasks.user_add(self.master, user, -+ extra_args=["--user-auth-type=idp", -+ "--idp-user-id=testuser1@ipa.test", -+ "--idp=testidp"] -+ ) -+ -+ backup_path = tasks.get_backup_dir(self.master) -+ # change data after backup -+ self.master.run_command(['ipa', 'user-del', user]) -+ self.master.run_command(['ipa', 'idp-del', 'testidp']) -+ dirman_password = self.master.config.dirman_password -+ self.master.run_command(['ipa-restore', backup_path], -+ stdin_text=dirman_password + '\nyes') -+ try: -+ list_user = self.master.run_command( -+ ['ipa', 'user-show', 'backupuser', '--all'] -+ ).stdout_text -+ assert "External IdP configuration: testidp" in list_user -+ assert "User authentication types: idp" in list_user -+ assert ("External IdP user identifier: " -+ "testuser1@ipa.test") in list_user -+ list_idp = self.master.run_command(['ipa', 'idp-find', 'testidp']) -+ assert "testidp" in list_idp.stdout_text -+ kinit_idp(self.master, user, self.client) -+ finally: -+ tasks.kdestroy_all(self.master) -+ tasks.kinit_admin(self.master) -+ self.master.run_command(["rm", "-rf", backup_path]) -+ self.master.run_command(["ipa", "idp-del", "testidp"]) --- -2.36.1 - diff --git a/SOURCES/0005-automember-rebuild-add-a-notice-about-high-CPU-usage_rhbz#2018198.patch b/SOURCES/0005-automember-rebuild-add-a-notice-about-high-CPU-usage_rhbz#2018198.patch new file mode 100644 index 0000000..4fc3a5d --- /dev/null +++ b/SOURCES/0005-automember-rebuild-add-a-notice-about-high-CPU-usage_rhbz#2018198.patch @@ -0,0 +1,64 @@ +From 2deaaa788cbdde22d5b15566599fdcf7a10f02c6 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Feb 02 2023 10:08:26 +0000 +Subject: automember-rebuild: add a notice about high CPU usage + + +The automember-rebuild task may require high CPU usage +if many users/hosts/groups are processed. +Add a note in the ipa automember-rebuild CLI output +and in the WebUI confirmation message. + +Fixes: https://pagure.io/freeipa/issue/9320 +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Francisco Trivino + +--- + +diff --git a/install/ui/test/data/i18n_messages.json b/install/ui/test/data/i18n_messages.json +index 49d2883..5b73548 100644 +--- a/install/ui/test/data/i18n_messages.json ++++ b/install/ui/test/data/i18n_messages.json +@@ -7,7 +7,7 @@ + "actions": { + "apply": "Apply", + "automember_rebuild": "Rebuild auto membership", +- "automember_rebuild_confirm": "Are you sure you want to rebuild auto membership?", ++ "automember_rebuild_confirm": "Are you sure you want to rebuild auto membership? In case of a high number of users, hosts or groups, the operation may require high CPU usage.", + "automember_rebuild_success": "Automember rebuild membership task completed", + "confirm": "Are you sure you want to proceed with the action?", + "delete_confirm": "Are you sure you want to delete ${object}?", +diff --git a/ipaclient/plugins/automember.py b/ipaclient/plugins/automember.py +index df4a2e5..7108dc9 100644 +--- a/ipaclient/plugins/automember.py ++++ b/ipaclient/plugins/automember.py +@@ -34,3 +34,11 @@ class automember_add_condition(MethodOverride): + flags=['suppress_empty'], + ), + ) ++ ++ ++@register(override=True, no_fail=True) ++class automember_rebuild(MethodOverride): ++ def interactive_prompt_callback(self, kw): ++ msg = _('IMPORTANT: In case of a high number of users, hosts or ' ++ 'groups, the operation may require high CPU usage.') ++ self.Backend.textui.print_plain(msg) +diff --git a/ipaserver/plugins/internal.py b/ipaserver/plugins/internal.py +index 5ffa7a2..e1e920f 100644 +--- a/ipaserver/plugins/internal.py ++++ b/ipaserver/plugins/internal.py +@@ -160,7 +160,11 @@ class i18n_messages(Command): + "actions": { + "apply": _("Apply"), + "automember_rebuild": _("Rebuild auto membership"), +- "automember_rebuild_confirm": _("Are you sure you want to rebuild auto membership?"), ++ "automember_rebuild_confirm": _( ++ "Are you sure you want to rebuild auto membership? In case of " ++ "a high number of users, hosts or groups, the operation " ++ "may require high CPU usage." ++ ), + "automember_rebuild_success": _("Automember rebuild membership task completed"), + "confirm": _("Are you sure you want to proceed with the action?"), + "delete_confirm": _("Are you sure you want to delete ${object}?"), + diff --git a/SOURCES/0006-ipa-kdb-PAC-consistency-checker-needs-to-handle-child-domains-as-well_rhbz#2166324.patch b/SOURCES/0006-ipa-kdb-PAC-consistency-checker-needs-to-handle-child-domains-as-well_rhbz#2166324.patch new file mode 100644 index 0000000..aa29c23 --- /dev/null +++ b/SOURCES/0006-ipa-kdb-PAC-consistency-checker-needs-to-handle-child-domains-as-well_rhbz#2166324.patch @@ -0,0 +1,185 @@ +From 2a0868fccbc9f4dfc540a7d3bb5dfa22c0bdce4e Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Mon, 30 Jan 2023 14:22:30 +0200 +Subject: [PATCH 1/2] ipa-kdb: PAC consistency checker needs to handle child + domains as well + +When PAC check is performed, we might get a signing TGT instead of the +client DB entry. This means it is a principal from a trusted domain but +we don't know which one exactly because we only have a krbtgt for the +forest root. This happens in MIT Kerberos 1.20 or later where KDB's +issue_pac() callback never gets the original client principal directly. + +Look into known child domains as well and make pass the check if both +NetBIOS name and SID correspond to one of the trusted domains under this +forest root. Move check for the SID before NetBIOS name check because we +can use SID of the domain in PAC to find out the right child domain in +our trusted domains' topology list. + +Fixes: https://pagure.io/freeipa/issue/9316 + +Signed-off-by: Alexander Bokovoy +--- + daemons/ipa-kdb/ipa_kdb_mspac.c | 51 +++++++++++++++++++++------------ + 1 file changed, 32 insertions(+), 19 deletions(-) + +diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c +index a15050e2166..476d1cb558a 100644 +--- a/daemons/ipa-kdb/ipa_kdb_mspac.c ++++ b/daemons/ipa-kdb/ipa_kdb_mspac.c +@@ -1827,11 +1827,43 @@ krb5_error_code filter_logon_info(krb5_context context, + bool result; + char *domstr = NULL; + ++ ipactx = ipadb_get_context(context); ++ if (!ipactx || !ipactx->mspac) { ++ return KRB5_KDB_DBNOTINITED; ++ } ++ + domain = get_domain_from_realm_update(context, realm); + if (!domain) { + return EINVAL; + } + ++ /* check exact sid */ ++ result = dom_sid_check(&domain->domsid, info->info->info3.base.domain_sid, true); ++ if (!result) { ++ struct ipadb_mspac *mspac_ctx = ipactx->mspac; ++ result = FALSE; ++ /* Didn't match but perhaps the original PAC was issued by a child domain's DC? */ ++ for (k = 0; k < mspac_ctx->num_trusts; k++) { ++ result = dom_sid_check(&mspac_ctx->trusts[k].domsid, ++ info->info->info3.base.domain_sid, true); ++ if (result) { ++ domain = &mspac_ctx->trusts[k]; ++ break; ++ } ++ } ++ if (!result) { ++ domstr = dom_sid_string(NULL, info->info->info3.base.domain_sid); ++ krb5_klog_syslog(LOG_ERR, "PAC Info mismatch: domain = %s, " ++ "expected domain SID = %s, " ++ "found domain SID = %s", ++ domain->domain_name, domain->domain_sid, ++ domstr ? domstr : ""); ++ talloc_free(domstr); ++ return EINVAL; ++ } ++ } ++ ++ /* At this point we may have changed the domain we look at, */ + /* check netbios/flat name */ + if (strcasecmp(info->info->info3.base.logon_domain.string, + domain->flat_name) != 0) { +@@ -1843,21 +1875,6 @@ krb5_error_code filter_logon_info(krb5_context context, + return EINVAL; + } + +- /* check exact sid */ +- result = dom_sid_check(&domain->domsid, info->info->info3.base.domain_sid, true); +- if (!result) { +- domstr = dom_sid_string(NULL, info->info->info3.base.domain_sid); +- if (!domstr) { +- return EINVAL; +- } +- krb5_klog_syslog(LOG_ERR, "PAC Info mismatch: domain = %s, " +- "expected domain SID = %s, " +- "found domain SID = %s", +- domain->domain_name, domain->domain_sid, domstr); +- talloc_free(domstr); +- return EINVAL; +- } +- + /* Check if this domain has been filtered out by the trust itself*/ + if (domain->parent != NULL) { + for(k = 0; k < domain->parent->len_sid_blocklist_incoming; k++) { +@@ -1944,10 +1961,6 @@ krb5_error_code filter_logon_info(krb5_context context, + * should include different possibilities into account + * */ + if (info->info->info3.sidcount != 0) { +- ipactx = ipadb_get_context(context); +- if (!ipactx || !ipactx->mspac) { +- return KRB5_KDB_DBNOTINITED; +- } + count = info->info->info3.sidcount; + i = 0; + j = 0; + +From 1a4f2597253c750696f6cd34613b375dc30fe456 Mon Sep 17 00:00:00 2001 +From: Anuja More +Date: Mon, 30 Jan 2023 19:27:49 +0530 +Subject: [PATCH 2/2] Add test for SSH with GSSAPI auth. + +Added test for aduser with GSSAPI authentication. + +Related : https://pagure.io/freeipa/issue/9316 + +Signed-off-by: Anuja More +--- + ipatests/test_integration/test_trust.py | 46 +++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + +diff --git a/ipatests/test_integration/test_trust.py b/ipatests/test_integration/test_trust.py +index 21c814ff1a9..a1ed906c6ae 100644 +--- a/ipatests/test_integration/test_trust.py ++++ b/ipatests/test_integration/test_trust.py +@@ -527,6 +527,35 @@ def test_subordinate_suffix(self): + .format(self.ad_domain, subordinate_suffix)) + self.ad.run_command(['powershell', '-c', cmd]) + ++ def test_ssh_aduser(self): ++ """Test ssh with GSSAPI is working with aduser ++ ++ When kerberos ticket is obtained for child domain user ++ and ssh with this ticket should be successful ++ with no password prompt. ++ ++ Related : https://pagure.io/freeipa/issue/9316 ++ """ ++ testuser = 'testuser@{0}'.format(self.ad_domain) ++ testusersub = 'subdomaintestuser@{0}'.format(self.ad_subdomain) ++ ++ def sshuser(host, user): ++ tasks.kdestroy_all(host) ++ try: ++ tasks.kinit_as_user(host, user, ++ host.config.ad_admin_password ++ ) ++ ssh_cmd = "ssh -q -K -l {user} {host} hostname" ++ valid_ssh = host.run_command( ++ ssh_cmd.format(user=user, host=host.hostname) ++ ) ++ assert host.hostname in valid_ssh.stdout_text ++ finally: ++ tasks.kdestroy_all(host) ++ ++ sshuser(self.master, testuser) ++ sshuser(self.master, testusersub) ++ + def test_remove_nonposix_trust(self): + self.remove_trust(self.ad) + tasks.unconfigure_dns_for_trust(self.master, self.ad) +@@ -784,6 +813,23 @@ def test_user_gid_uid_resolution_in_external_treedomain_trust(self): + assert re.search( + testuser_regex, result.stdout_text), result.stdout_text + ++ def test_ssh_adtreeuser(self): ++ testuser = 'treetestuser@{0}'.format(self.ad_treedomain) ++ self.master.run_command(["id", testuser]) ++ tasks.clear_sssd_cache(self.master) ++ tasks.kdestroy_all(self.master) ++ try: ++ tasks.kinit_as_user(self.master, testuser, ++ password="Secret123456" ++ ) ++ ssh_cmd = "ssh -q -K -l {user} {host} hostname" ++ valid_ssh = self.master.run_command( ++ ssh_cmd.format(user=testuser, host=self.master.hostname) ++ ) ++ assert self.master.hostname in valid_ssh.stdout_text ++ finally: ++ tasks.kdestroy_all(self.master) ++ + def test_remove_external_treedomain_trust(self): + self.remove_trust(self.tree_ad) + tasks.unconfigure_dns_for_trust(self.master, self.ad, self.tree_ad) diff --git a/SOURCES/0006-webui-Do-not-allow-empty-pagination-size_rhbz#2094672.patch b/SOURCES/0006-webui-Do-not-allow-empty-pagination-size_rhbz#2094672.patch deleted file mode 100644 index 25e9f72..0000000 --- a/SOURCES/0006-webui-Do-not-allow-empty-pagination-size_rhbz#2094672.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 991849cf58fa990ad4540a61214b5ab4fcd4baa1 Mon Sep 17 00:00:00 2001 -From: Armando Neto -Date: Fri, 8 Jul 2022 15:56:31 -0300 -Subject: [PATCH] webui: Do not allow empty pagination size - -Pagination size must be required, the current validators are triggered after -form is submitted, thus the only way for check if data is not empty is by making -the field required. - -Fixes: https://pagure.io/freeipa/issue/9192 - -Signed-off-by: Armando Neto -Reviewed-By: Florence Blanc-Renaud ---- - .../ui/src/freeipa/Application_controller.js | 1 + - ipatests/test_webui/test_misc_cases.py | 19 +++++++++++++++++++ - 2 files changed, 20 insertions(+) - -diff --git a/install/ui/src/freeipa/Application_controller.js b/install/ui/src/freeipa/Application_controller.js -index 46aabc9c4..140ee8fe0 100644 ---- a/install/ui/src/freeipa/Application_controller.js -+++ b/install/ui/src/freeipa/Application_controller.js -@@ -318,6 +318,7 @@ define([ - $type: 'text', - name: 'pagination_size', - label: '@i18n:customization.table_pagination', -+ required: true, - validators: ['positive_integer'] - } - ] -diff --git a/ipatests/test_webui/test_misc_cases.py b/ipatests/test_webui/test_misc_cases.py -index 5f7ffb54e..aca9e1a99 100644 ---- a/ipatests/test_webui/test_misc_cases.py -+++ b/ipatests/test_webui/test_misc_cases.py -@@ -11,6 +11,11 @@ from ipatests.test_webui.ui_driver import screenshot - import pytest - import re - -+try: -+ from selenium.webdriver.common.by import By -+except ImportError: -+ pass -+ - - @pytest.mark.tier1 - class TestMiscCases(UI_driver): -@@ -26,3 +31,17 @@ class TestMiscCases(UI_driver): - ver_re = re.compile('version: .*') - assert re.search(ver_re, about_text), 'Version not found' - self.dialog_button_click('ok') -+ -+ @screenshot -+ def test_customization_pagination_input_required(self): -+ """Test if 'pagination size' is required when submitting the form.""" -+ self.init_app() -+ -+ self.profile_menu_action('configuration') -+ self.fill_input('pagination_size', '') -+ self.dialog_button_click('save') -+ -+ pagination_size_elem = self.find( -+ ".widget[name='pagination_size']", By.CSS_SELECTOR) -+ -+ self.assert_field_validation_required(parent=pagination_size_elem) --- -2.36.1 - diff --git a/SOURCES/0007-Wipe-the-ipa-ca-DNS-record-when-updating-system-records_rhbz#2158775.patch b/SOURCES/0007-Wipe-the-ipa-ca-DNS-record-when-updating-system-records_rhbz#2158775.patch new file mode 100644 index 0000000..87b63ed --- /dev/null +++ b/SOURCES/0007-Wipe-the-ipa-ca-DNS-record-when-updating-system-records_rhbz#2158775.patch @@ -0,0 +1,64 @@ +From b35c75d864040b98ed3f9214d5d17d32f06d6ee1 Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Mon, 11 Jul 2022 14:20:32 -0400 +Subject: [PATCH] Wipe the ipa-ca DNS record when updating system records + +If a server with a CA has been marked as hidden and +contains the last A or AAAA address then that address +would remain in the ipa-ca entry. + +This is because update-dns-system-records did not delete +values, it just re-computed them. So if no A or AAAA +records were found then the existing value was left. + +Fixes: https://pagure.io/freeipa/issue/9195 + +Signed-off-by: Rob Crittenden +--- + ipaserver/dns_data_management.py | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/ipaserver/dns_data_management.py b/ipaserver/dns_data_management.py +index e2bc530ee8a..aaae5446856 100644 +--- a/ipaserver/dns_data_management.py ++++ b/ipaserver/dns_data_management.py +@@ -19,6 +19,7 @@ + from time import sleep, time + + from ipalib import errors ++from ipalib.constants import IPA_CA_RECORD + from ipalib.dns import record_name_format + from ipapython.dnsutil import DNSName + from ipaserver.install import installutils +@@ -187,7 +188,7 @@ def __add_uri_records( + + def __add_ca_records_from_hostname(self, zone_obj, hostname): + assert isinstance(hostname, DNSName) and hostname.is_absolute() +- r_name = DNSName('ipa-ca') + self.domain_abs ++ r_name = DNSName(IPA_CA_RECORD) + self.domain_abs + rrsets = None + end_time = time() + CA_RECORDS_DNS_TIMEOUT + while True: +@@ -210,6 +211,7 @@ def __add_ca_records_from_hostname(self, zone_obj, hostname): + + for rrset in rrsets: + for rd in rrset: ++ logger.debug("Adding CA IP %s for %s", rd.to_text(), hostname) + rdataset = zone_obj.get_rdataset( + r_name, rd.rdtype, create=True) + rdataset.add(rd, ttl=self.TTL) +@@ -461,6 +463,14 @@ def update_base_records(self): + ) + ) + ++ # Remove the ipa-ca record(s). They will be reconstructed in ++ # get_base_records(). ++ r_name = DNSName(IPA_CA_RECORD) + self.domain_abs ++ try: ++ self.api_instance.Command.dnsrecord_del( ++ self.domain_abs, r_name, del_all=True) ++ except errors.NotFound: ++ pass + base_zone = self.get_base_records() + for record_name, node in base_zone.items(): + set_cname_template = record_name in names_requiring_cname_templates diff --git a/SOURCES/0007-webui-Allow-grace-login-limit_rhbz#2109243.patch b/SOURCES/0007-webui-Allow-grace-login-limit_rhbz#2109243.patch deleted file mode 100644 index 93cfab9..0000000 --- a/SOURCES/0007-webui-Allow-grace-login-limit_rhbz#2109243.patch +++ /dev/null @@ -1,56 +0,0 @@ -From ade5093b08f92b279c200f341e96972a74f644d8 Mon Sep 17 00:00:00 2001 -From: Carla Martinez -Date: Fri, 29 Jul 2022 13:16:16 +0200 -Subject: [PATCH] webui: Allow grace login limit - -There was no support for setting the grace login limit on the WebUI. The -only way to so was only via CLI: - - `ipa pwpolicy-mod --gracelimit=2 global_policy` - -Thus, the grace login limit must be updated from the policy section and -this will reflect also on the user settings (under the 'Password Policy' -section) - -Fixes: https://pagure.io/freeipa/issue/9211 - -Signed-off-by: Carla Martinez -Reviewed-By: Florence Blanc-Renaud ---- - install/ui/src/freeipa/policy.js | 3 +++ - install/ui/src/freeipa/user.js | 5 +++++ - 2 files changed, 8 insertions(+) - -diff --git a/install/ui/src/freeipa/policy.js b/install/ui/src/freeipa/policy.js -index fa2028a52..7ec103636 100644 ---- a/install/ui/src/freeipa/policy.js -+++ b/install/ui/src/freeipa/policy.js -@@ -72,6 +72,9 @@ return { - { - name: 'cospriority', - required: true -+ }, -+ { -+ name: 'passwordgracelimit' - } - ] - }] -diff --git a/install/ui/src/freeipa/user.js b/install/ui/src/freeipa/user.js -index a580db035..b47c97f72 100644 ---- a/install/ui/src/freeipa/user.js -+++ b/install/ui/src/freeipa/user.js -@@ -318,6 +318,11 @@ return { - label: '@mo-param:pwpolicy:krbpwdlockoutduration:label', - read_only: true, - measurement_unit: 'seconds' -+ }, -+ { -+ name: 'passwordgracelimit', -+ label: '@mo-param:pwpolicy:passwordgracelimit:label', -+ read_only: true - } - ] - }, --- -2.37.2 - diff --git a/SOURCES/0008-check_repl_update-in-progress-is-a-boolean_rhbz#2117303.patch b/SOURCES/0008-check_repl_update-in-progress-is-a-boolean_rhbz#2117303.patch deleted file mode 100644 index 36629da..0000000 --- a/SOURCES/0008-check_repl_update-in-progress-is-a-boolean_rhbz#2117303.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 05a298f56485222583cb7dd4f6a3a4c5c77fc8cf Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Sun, 7 Aug 2022 12:44:47 +0200 -Subject: [PATCH] check_repl_update: in progress is a boolean - -With the fix for https://pagure.io/freeipa/issue/9171, -nsds5replicaUpdateInProgress is now handled as a boolean. -One remaining occurrence was still handling it as a string -and calling lower() on its value. - -Replace with direct boolean comparison. - -Fixes: https://pagure.io/freeipa/issue/9218 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Alexander Bokovoy ---- - ipaserver/install/replication.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py -index 16be3760c..9d9aa1c4b 100644 ---- a/ipaserver/install/replication.py -+++ b/ipaserver/install/replication.py -@@ -1152,7 +1152,7 @@ class ReplicationManager: - except (ValueError, TypeError, KeyError): - end = 0 - # incremental update is done if inprogress is false and end >= start -- done = inprogress and inprogress.lower() == 'false' and start <= end -+ done = inprogress is not None and not inprogress and start <= end - logger.info("Replication Update in progress: %s: status: %s: " - "start: %d: end: %d", - inprogress, status, start, end) --- -2.37.2 - diff --git a/SOURCES/0009-Disabling-gracelimit-does-not-prevent-LDAP-binds_rhbz#2109236.patch b/SOURCES/0009-Disabling-gracelimit-does-not-prevent-LDAP-binds_rhbz#2109236.patch deleted file mode 100644 index 17088cf..0000000 --- a/SOURCES/0009-Disabling-gracelimit-does-not-prevent-LDAP-binds_rhbz#2109236.patch +++ /dev/null @@ -1,125 +0,0 @@ -From 1316cd8b2252c2543cf2ef2186956a8833037b1e Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Thu, 21 Jul 2022 09:28:46 -0400 -Subject: [PATCH] Disabling gracelimit does not prevent LDAP binds - -Originally the code treated 0 as disabled. This was -changed during the review process to -1 but one remnant -was missed effetively allowing gracelimit 0 to also mean -disabled. - -Add explicit tests for testing with gracelimit = 0 and -gracelimit = -1. - -Also remove some extranous "str(self.master.domain.basedn)" -lines from some of the tests. - -Fixes: https://pagure.io/freeipa/issue/9206 - -Signed-off-by: Rob Crittenden -Reviewed-By: Francisco Trivino ---- - .../ipa-graceperiod/ipa_graceperiod.c | 2 +- - ipatests/test_integration/test_pwpolicy.py | 55 ++++++++++++++++++- - 2 files changed, 53 insertions(+), 4 deletions(-) - -diff --git a/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c b/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c -index a3f57cb4b..345e1dee7 100644 ---- a/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c -+++ b/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c -@@ -479,7 +479,7 @@ static int ipagraceperiod_preop(Slapi_PBlock *pb) - if (pwresponse_requested) { - slapi_pwpolicy_make_response_control(pb, -1, grace_limit - grace_user_time , -1); - } -- } else if ((grace_limit > 0) && (grace_user_time >= grace_limit)) { -+ } else if (grace_user_time >= grace_limit) { - LOG_TRACE("%s password is expired and out of grace limit\n", dn); - errstr = "Password is expired.\n"; - ret = LDAP_INVALID_CREDENTIALS; -diff --git a/ipatests/test_integration/test_pwpolicy.py b/ipatests/test_integration/test_pwpolicy.py -index 6d6698284..41d6e9070 100644 ---- a/ipatests/test_integration/test_pwpolicy.py -+++ b/ipatests/test_integration/test_pwpolicy.py -@@ -36,7 +36,7 @@ class TestPWPolicy(IntegrationTest): - cls.master.run_command(['ipa', 'group-add-member', POLICY, - '--users', USER]) - cls.master.run_command(['ipa', 'pwpolicy-add', POLICY, -- '--priority', '1']) -+ '--priority', '1', '--gracelimit', '-1']) - cls.master.run_command(['ipa', 'passwd', USER], - stdin_text='{password}\n{password}\n'.format( - password=PASSWORD -@@ -265,7 +265,6 @@ class TestPWPolicy(IntegrationTest): - - def test_graceperiod_expired(self): - """Test the LDAP bind grace period""" -- str(self.master.domain.basedn) - dn = "uid={user},cn=users,cn=accounts,{base_dn}".format( - user=USER, base_dn=str(self.master.domain.basedn)) - -@@ -308,7 +307,6 @@ class TestPWPolicy(IntegrationTest): - - def test_graceperiod_not_replicated(self): - """Test that the grace period is reset on password reset""" -- str(self.master.domain.basedn) - dn = "uid={user},cn=users,cn=accounts,{base_dn}".format( - user=USER, base_dn=str(self.master.domain.basedn)) - -@@ -341,3 +339,54 @@ class TestPWPolicy(IntegrationTest): - ) - assert 'passwordgraceusertime: 0' in result.stdout_text.lower() - self.reset_password(self.master) -+ -+ def test_graceperiod_zero(self): -+ """Test the LDAP bind with zero grace period""" -+ dn = "uid={user},cn=users,cn=accounts,{base_dn}".format( -+ user=USER, base_dn=str(self.master.domain.basedn)) -+ -+ self.master.run_command( -+ ["ipa", "pwpolicy-mod", POLICY, "--gracelimit", "0", ], -+ ) -+ -+ # Resetting the password will mark it as expired -+ self.reset_password(self.master) -+ -+ # Now grace is done and binds should fail. -+ result = self.master.run_command( -+ ["ldapsearch", "-e", "ppolicy", "-D", dn, -+ "-w", PASSWORD, "-b", dn], raiseonerr=False -+ ) -+ assert result.returncode == 49 -+ -+ assert 'Password is expired' in result.stderr_text -+ assert 'Password expired, 0 grace logins remain' in result.stderr_text -+ -+ def test_graceperiod_disabled(self): -+ """Test the LDAP bind with grace period disabled (-1)""" -+ str(self.master.domain.basedn) -+ dn = "uid={user},cn=users,cn=accounts,{base_dn}".format( -+ user=USER, base_dn=str(self.master.domain.basedn)) -+ -+ # This can fail if gracelimit is already -1 so ignore it -+ self.master.run_command( -+ ["ipa", "pwpolicy-mod", POLICY, "--gracelimit", "-1",], -+ raiseonerr=False, -+ ) -+ -+ # Ensure the password is expired -+ self.reset_password(self.master) -+ -+ result = self.kinit_as_user(self.master, PASSWORD, PASSWORD) -+ -+ for _i in range(0, 10): -+ result = self.master.run_command( -+ ["ldapsearch", "-e", "ppolicy", "-D", dn, -+ "-w", PASSWORD, "-b", dn] -+ ) -+ -+ # With graceperiod disabled it should not increment -+ result = tasks.ldapsearch_dm( -+ self.master, dn, ['passwordgraceusertime',], -+ ) -+ assert 'passwordgraceusertime: 0' in result.stdout_text.lower() --- -2.37.2 - diff --git a/SOURCES/0010-Set-passwordgracelimit-to-match-global-policy-on-group-pw-policies_rhbz#2115475.patch b/SOURCES/0010-Set-passwordgracelimit-to-match-global-policy-on-group-pw-policies_rhbz#2115475.patch deleted file mode 100644 index 952e49b..0000000 --- a/SOURCES/0010-Set-passwordgracelimit-to-match-global-policy-on-group-pw-policies_rhbz#2115475.patch +++ /dev/null @@ -1,230 +0,0 @@ -From 434620ee342ac4767beccec647a318bfa7743dfa Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Thu, 18 Aug 2022 08:21:58 -0400 -Subject: [PATCH] doc: Update LDAP grace period design with default values - -New group password policies will get -1 (unlimited) on creation -by default. - -Existing group password policies will remain untouched and -those created prior will be treated as no BIND allowed. - -Fixes: https://pagure.io/freeipa/issue/9212 - -Signed-off-by: Rob Crittenden -Reviewed-By: Florence Blanc-Renaud ---- - doc/designs/ldap_grace_period.md | 17 ++++++++++++++++- - 1 file changed, 16 insertions(+), 1 deletion(-) - -diff --git a/doc/designs/ldap_grace_period.md b/doc/designs/ldap_grace_period.md -index 4b9db3424..e26aedda9 100644 ---- a/doc/designs/ldap_grace_period.md -+++ b/doc/designs/ldap_grace_period.md -@@ -51,7 +51,22 @@ The basic flow is: - - On successful password reset (by anyone) reset the user's passwordGraceUserTime to 0. - --The default value on install/upgrade will be -1 to retail existing behavior. -+Range values for passwordgracelimit are: -+ -+-1 : password grace checking is disabled -+ 0 : no grace BIND are allowed at all post-expiration -+ 1..MAXINT: the number of BIND allowed post-expiration -+ -+The default value for the global policy on install/upgrade will be -1 to -+retain existing behavior. -+ -+New group password policies will default to -1 to retain previous -+behavior. -+ -+Existing group policies with no grace limit set are updated to use -+the default unlimited value, -1. This is done because lack of value in -+LDAP is treated as 0 so any existing group policies would not allow -+post-expiration BIND so this will avoid confusion. - - The per-user attempts will not be replicated. - --- -2.37.2 - -From 497a57e7a6872fa30d1855a1d91a455bfdbf9300 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Thu, 4 Aug 2022 12:04:22 -0400 -Subject: [PATCH] Set default gracelimit on group password policies to -1 - -This will retain previous behavior of unlimited LDAP BIND -post-expiration. - -Fixes: https://pagure.io/freeipa/issue/9212 - -Signed-off-by: Rob Crittenden -Reviewed-By: Florence Blanc-Renaud ---- - API.txt | 2 +- - ipaserver/plugins/pwpolicy.py | 2 ++ - ipatests/test_xmlrpc/test_pwpolicy_plugin.py | 2 ++ - 3 files changed, 5 insertions(+), 1 deletion(-) - -diff --git a/API.txt b/API.txt -index 5ba9add13..d7ea74f08 100644 ---- a/API.txt -+++ b/API.txt -@@ -4075,7 +4075,7 @@ option: Int('krbpwdlockoutduration?', cli_name='lockouttime') - option: Int('krbpwdmaxfailure?', cli_name='maxfail') - option: Int('krbpwdmindiffchars?', cli_name='minclasses') - option: Int('krbpwdminlength?', cli_name='minlength') --option: Int('passwordgracelimit?', cli_name='gracelimit', default=-1) -+option: Int('passwordgracelimit?', autofill=True, cli_name='gracelimit', default=-1) - option: Flag('raw', autofill=True, cli_name='raw', default=False) - option: Str('setattr*', cli_name='setattr') - option: Str('version?') -diff --git a/ipaserver/plugins/pwpolicy.py b/ipaserver/plugins/pwpolicy.py -index 4428aede2..f4ebffd5c 100644 ---- a/ipaserver/plugins/pwpolicy.py -+++ b/ipaserver/plugins/pwpolicy.py -@@ -408,6 +408,7 @@ class pwpolicy(LDAPObject): - minvalue=-1, - maxvalue=Int.MAX_UINT32, - default=-1, -+ autofill=True, - ), - ) - -@@ -539,6 +540,7 @@ class pwpolicy_add(LDAPCreate): - keys[-1], krbpwdpolicyreference=dn, - cospriority=options.get('cospriority') - ) -+ - return dn - - def post_callback(self, ldap, dn, entry_attrs, *keys, **options): -diff --git a/ipatests/test_xmlrpc/test_pwpolicy_plugin.py b/ipatests/test_xmlrpc/test_pwpolicy_plugin.py -index 8eee69c18..fc785223b 100644 ---- a/ipatests/test_xmlrpc/test_pwpolicy_plugin.py -+++ b/ipatests/test_xmlrpc/test_pwpolicy_plugin.py -@@ -387,6 +387,7 @@ class test_pwpolicy_mod_cospriority(Declarative): - krbpwdhistorylength=[u'10'], - krbpwdmindiffchars=[u'3'], - krbpwdminlength=[u'8'], -+ passwordgracelimit=[u'-1'], - objectclass=objectclasses.pwpolicy, - ), - summary=None, -@@ -417,6 +418,7 @@ class test_pwpolicy_mod_cospriority(Declarative): - krbpwdhistorylength=[u'10'], - krbpwdmindiffchars=[u'3'], - krbpwdminlength=[u'8'], -+ passwordgracelimit=[u'-1'], - ), - summary=None, - value=u'ipausers', --- -2.37.2 - -From a4ddaaf3048c4e8d78a1807af7266ee40ab3a30b Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Thu, 4 Aug 2022 12:04:41 -0400 -Subject: [PATCH] Set default on group pwpolicy with no grace limit in upgrade - -If an existing group policy lacks a password grace limit -update it to -1 on upgrade. - -Fixes: https://pagure.io/freeipa/issue/9212 - -Signed-off-by: Rob Crittenden -Reviewed-By: Florence Blanc-Renaud ---- - .../updates/90-post_upgrade_plugins.update | 1 + - ipaserver/install/plugins/update_pwpolicy.py | 66 +++++++++++++++++++ - 2 files changed, 67 insertions(+) - -diff --git a/install/updates/90-post_upgrade_plugins.update b/install/updates/90-post_upgrade_plugins.update -index c7ec71d49..6fe91aa6c 100644 ---- a/install/updates/90-post_upgrade_plugins.update -+++ b/install/updates/90-post_upgrade_plugins.update -@@ -26,6 +26,7 @@ plugin: update_ra_cert_store - plugin: update_mapping_Guests_to_nobody - plugin: fix_kra_people_entry - plugin: update_pwpolicy -+plugin: update_pwpolicy_grace - - # last - # DNS version 1 -diff --git a/ipaserver/install/plugins/update_pwpolicy.py b/ipaserver/install/plugins/update_pwpolicy.py -index dca44ce43..4185f0343 100644 ---- a/ipaserver/install/plugins/update_pwpolicy.py -+++ b/ipaserver/install/plugins/update_pwpolicy.py -@@ -78,3 +78,69 @@ class update_pwpolicy(Updater): - return False, [] - - return False, [] -+ -+ -+@register() -+class update_pwpolicy_grace(Updater): -+ """ -+ Ensure all group policies have a grace period set. -+ """ -+ -+ def execute(self, **options): -+ ldap = self.api.Backend.ldap2 -+ -+ base_dn = DN(('cn', self.api.env.realm), ('cn', 'kerberos'), -+ self.api.env.basedn) -+ search_filter = ( -+ "(&(objectClass=krbpwdpolicy)(!(passwordgracelimit=*)))" -+ ) -+ -+ while True: -+ # Run the search in loop to avoid issues when LDAP limits are hit -+ # during update -+ -+ try: -+ (entries, truncated) = ldap.find_entries( -+ search_filter, ['objectclass'], base_dn, time_limit=0, -+ size_limit=0) -+ -+ except errors.EmptyResult: -+ logger.debug("update_pwpolicy: no policies without " -+ "passwordgracelimit set") -+ return False, [] -+ -+ except errors.ExecutionError as e: -+ logger.error("update_pwpolicy: cannot retrieve list " -+ "of policies missing passwordgracelimit: %s", e) -+ return False, [] -+ -+ logger.debug("update_pwpolicy: found %d " -+ "policies to update, truncated: %s", -+ len(entries), truncated) -+ -+ error = False -+ -+ for entry in entries: -+ # Set unlimited BIND by default -+ entry['passwordgracelimit'] = -1 -+ try: -+ ldap.update_entry(entry) -+ except (errors.EmptyModlist, errors.NotFound): -+ pass -+ except errors.ExecutionError as e: -+ logger.debug("update_pwpolicy: cannot " -+ "update policy: %s", e) -+ error = True -+ -+ if error: -+ # Exit loop to avoid infinite cycles -+ logger.error("update_pwpolicy: error(s) " -+ "detected during pwpolicy update") -+ return False, [] -+ -+ elif not truncated: -+ # All affected entries updated, exit the loop -+ logger.debug("update_pwpolicy: all policies updated") -+ return False, [] -+ -+ return False, [] --- -2.37.2 - diff --git a/SOURCES/0011-fix-canonicalization-issue-in-Web-UI_rhbz#2133050.patch b/SOURCES/0011-fix-canonicalization-issue-in-Web-UI_rhbz#2133050.patch deleted file mode 100644 index 4fa0b23..0000000 --- a/SOURCES/0011-fix-canonicalization-issue-in-Web-UI_rhbz#2133050.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 109cd579e3b089b7fad4c92bf25594eba1af8a21 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Tue, 23 Aug 2022 16:58:07 +0300 -Subject: [PATCH] fix canonicalization issue in Web UI - -When Kerberos principal alias is used to login to a Web UI, we end up -with a request that is authenticated by a ticket issued in the alias -name but metadata processed for the canonical user name. This confuses -RPC layer of Web UI code and causes infinite loop to reload the page. - -Fix it by doing two things: - - - force use of canonicalization of an enterprise principal on server - side, not just specifying that the principal is an enterprise one; - - - recognize that a principal in the whoami()-returned object can have - aliases and the principal returned by the server in the JSON response - may be one of those aliases. - -Fixes: https://pagure.io/freeipa/issue/9226 - -Signed-off-by: Alexander Bokovoy -Reviewed-By: Armando Neto ---- - install/ui/src/freeipa/ipa.js | 8 +++++++- - ipaserver/rpcserver.py | 1 + - 2 files changed, 8 insertions(+), 1 deletion(-) - -diff --git a/install/ui/src/freeipa/ipa.js b/install/ui/src/freeipa/ipa.js -index 758db1b00..a08d632e9 100644 ---- a/install/ui/src/freeipa/ipa.js -+++ b/install/ui/src/freeipa/ipa.js -@@ -271,7 +271,13 @@ var IPA = function () { - var cn = that.whoami.data.krbcanonicalname; - if (cn) that.principal = cn[0]; - if (!that.principal) { -- that.principal = that.whoami.data.krbprincipalname[0]; -+ var principal = data.principal; -+ var idx = that.whoami.data.krbprincipalname.indexOf(principal); -+ if (idx > -1) { -+ that.principal = principal; -+ } else { -+ that.principal = that.whoami.data.krbprincipalname[0]; -+ } - } - } else if (entity === 'idoverrideuser') { - that.principal = that.whoami.data.ipaoriginaluid[0]; -diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py -index 1f85e9898..4e8a08b66 100644 ---- a/ipaserver/rpcserver.py -+++ b/ipaserver/rpcserver.py -@@ -1109,6 +1109,7 @@ class login_password(Backend, KerberosSession): - ccache_name, - armor_ccache_name=armor_path, - enterprise=True, -+ canonicalize=True, - lifetime=self.api.env.kinit_lifetime) - - if armor_path: --- -2.37.3 - diff --git a/SOURCES/0012-Defer-creating-the-final-krb5-conf-on-clients_rhbz#2150246.patch b/SOURCES/0012-Defer-creating-the-final-krb5-conf-on-clients_rhbz#2150246.patch deleted file mode 100644 index 30114a5..0000000 --- a/SOURCES/0012-Defer-creating-the-final-krb5-conf-on-clients_rhbz#2150246.patch +++ /dev/null @@ -1,473 +0,0 @@ -From 69413325158a3ea06d1491acd77ee6e0955ee89a Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Sep 26 2022 11:48:47 +0000 -Subject: Defer creating the final krb5.conf on clients - - -A temporary krb5.conf is created early during client enrollment -and was previously used only during the initial ipa-join call. -The final krb5.conf was written soon afterward. - -If there are multiple servers it is possible that the client -may then choose a different KDC to connect. If the client -is faster than replication then the client may not exist -on all servers and therefore enrollment will fail. - -This was seen in performance testing of how many simultaneous -client enrollments are possible. - -Use a decorator to wrap the _install() method to ensure the -temporary files created during installation are cleaned up. - -https://pagure.io/freeipa/issue/9228 - -Signed-off-by: Rob Crittenden -Reviewed-By: Florence Blanc-Renaud - ---- - -diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py -index 920c517..93bc740 100644 ---- a/ipaclient/install/client.py -+++ b/ipaclient/install/client.py -@@ -101,6 +101,37 @@ cli_basedn = None - # end of global variables - - -+def cleanup(func): -+ def inner(options, tdict): -+ # Add some additional options which contain the temporary files -+ # needed during installation. -+ fd, krb_name = tempfile.mkstemp() -+ os.close(fd) -+ ccache_dir = tempfile.mkdtemp(prefix='krbcc') -+ -+ tdict['krb_name'] = krb_name -+ tdict['ccache_dir'] = ccache_dir -+ -+ func(options, tdict) -+ -+ os.environ.pop('KRB5_CONFIG', None) -+ -+ try: -+ os.remove(krb_name) -+ except OSError: -+ logger.error("Could not remove %s", krb_name) -+ try: -+ os.rmdir(ccache_dir) -+ except OSError: -+ pass -+ try: -+ os.remove(krb_name + ".ipabkp") -+ except OSError: -+ logger.error("Could not remove %s.ipabkp", krb_name) -+ -+ return inner -+ -+ - def remove_file(filename): - """ - Deletes a file. If the file does not exist (OSError 2) does nothing. -@@ -2652,7 +2683,7 @@ def restore_time_sync(statestore, fstore): - - def install(options): - try: -- _install(options) -+ _install(options, dict()) - except ScriptError as e: - if e.rval == CLIENT_INSTALL_ERROR: - if options.force: -@@ -2679,7 +2710,8 @@ def install(options): - pass - - --def _install(options): -+@cleanup -+def _install(options, tdict): - env = {'PATH': SECURE_PATH} - - fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) -@@ -2687,6 +2719,9 @@ def _install(options): - - statestore.backup_state('installation', 'complete', False) - -+ krb_name = tdict['krb_name'] -+ ccache_dir = tdict['ccache_dir'] -+ - if not options.on_master: - # Try removing old principals from the keytab - purge_host_keytab(cli_realm) -@@ -2719,182 +2754,162 @@ def _install(options): - host_principal = 'host/%s@%s' % (hostname, cli_realm) - if not options.on_master: - nolog = tuple() -- # First test out the kerberos configuration -- fd, krb_name = tempfile.mkstemp() -- os.close(fd) -- ccache_dir = tempfile.mkdtemp(prefix='krbcc') -- try: -- configure_krb5_conf( -- cli_realm=cli_realm, -- cli_domain=cli_domain, -- cli_server=cli_server, -- cli_kdc=cli_kdc, -- dnsok=False, -- filename=krb_name, -- client_domain=client_domain, -- client_hostname=hostname, -- configure_sssd=options.sssd, -- force=options.force) -- env['KRB5_CONFIG'] = krb_name -- ccache_name = os.path.join(ccache_dir, 'ccache') -- join_args = [ -- paths.SBIN_IPA_JOIN, -- "-s", cli_server[0], -- "-b", str(realm_to_suffix(cli_realm)), -- "-h", hostname, -- "-k", paths.KRB5_KEYTAB -- ] -- if options.debug: -- join_args.append("-d") -- env['XMLRPC_TRACE_CURL'] = 'yes' -- if options.force_join: -- join_args.append("-f") -- if options.principal is not None: -- stdin = None -- principal = options.principal -- if principal.find('@') == -1: -- principal = '%s@%s' % (principal, cli_realm) -- if options.password is not None: -- stdin = options.password -+ configure_krb5_conf( -+ cli_realm=cli_realm, -+ cli_domain=cli_domain, -+ cli_server=cli_server, -+ cli_kdc=cli_kdc, -+ dnsok=False, -+ filename=krb_name, -+ client_domain=client_domain, -+ client_hostname=hostname, -+ configure_sssd=options.sssd, -+ force=options.force) -+ env['KRB5_CONFIG'] = krb_name -+ ccache_name = os.path.join(ccache_dir, 'ccache') -+ join_args = [ -+ paths.SBIN_IPA_JOIN, -+ "-s", cli_server[0], -+ "-b", str(realm_to_suffix(cli_realm)), -+ "-h", hostname, -+ "-k", paths.KRB5_KEYTAB -+ ] -+ if options.debug: -+ join_args.append("-d") -+ env['XMLRPC_TRACE_CURL'] = 'yes' -+ if options.force_join: -+ join_args.append("-f") -+ if options.principal is not None: -+ stdin = None -+ principal = options.principal -+ if principal.find('@') == -1: -+ principal = '%s@%s' % (principal, cli_realm) -+ if options.password is not None: -+ stdin = options.password -+ else: -+ if not options.unattended: -+ try: -+ stdin = getpass.getpass( -+ "Password for %s: " % principal) -+ except EOFError: -+ stdin = None -+ if not stdin: -+ raise ScriptError( -+ "Password must be provided for {}.".format( -+ principal), -+ rval=CLIENT_INSTALL_ERROR) - else: -- if not options.unattended: -- try: -- stdin = getpass.getpass( -- "Password for %s: " % principal) -- except EOFError: -- stdin = None -- if not stdin: -- raise ScriptError( -- "Password must be provided for {}.".format( -- principal), -- rval=CLIENT_INSTALL_ERROR) -+ if sys.stdin.isatty(): -+ logger.error( -+ "Password must be provided in " -+ "non-interactive mode.") -+ logger.info( -+ "This can be done via " -+ "echo password | ipa-client-install ... " -+ "or with the -w option.") -+ raise ScriptError(rval=CLIENT_INSTALL_ERROR) - else: -- if sys.stdin.isatty(): -- logger.error( -- "Password must be provided in " -- "non-interactive mode.") -- logger.info( -- "This can be done via " -- "echo password | ipa-client-install ... " -- "or with the -w option.") -- raise ScriptError(rval=CLIENT_INSTALL_ERROR) -- else: -- stdin = sys.stdin.readline() -+ stdin = sys.stdin.readline() - -+ try: -+ kinit_password(principal, stdin, ccache_name, -+ config=krb_name) -+ except RuntimeError as e: -+ print_port_conf_info() -+ raise ScriptError( -+ "Kerberos authentication failed: {}".format(e), -+ rval=CLIENT_INSTALL_ERROR) -+ elif options.keytab: -+ join_args.append("-f") -+ if os.path.exists(options.keytab): - try: -- kinit_password(principal, stdin, ccache_name, -- config=krb_name) -- except RuntimeError as e: -+ kinit_keytab(host_principal, -+ options.keytab, -+ ccache_name, -+ config=krb_name, -+ attempts=options.kinit_attempts) -+ except gssapi.exceptions.GSSError as e: - print_port_conf_info() - raise ScriptError( - "Kerberos authentication failed: {}".format(e), - rval=CLIENT_INSTALL_ERROR) -- elif options.keytab: -- join_args.append("-f") -- if os.path.exists(options.keytab): -- try: -- kinit_keytab(host_principal, -- options.keytab, -- ccache_name, -- config=krb_name, -- attempts=options.kinit_attempts) -- except gssapi.exceptions.GSSError as e: -- print_port_conf_info() -- raise ScriptError( -- "Kerberos authentication failed: {}".format(e), -- rval=CLIENT_INSTALL_ERROR) -- else: -- raise ScriptError( -- "Keytab file could not be found: {}".format( -- options.keytab), -- rval=CLIENT_INSTALL_ERROR) -- elif options.password: -- nolog = (options.password,) -- join_args.append("-w") -- join_args.append(options.password) -- elif options.prompt_password: -- if options.unattended: -- raise ScriptError( -- "Password must be provided in non-interactive mode", -- rval=CLIENT_INSTALL_ERROR) -- try: -- password = getpass.getpass("Password: ") -- except EOFError: -- password = None -- if not password: -- raise ScriptError( -- "Password must be provided.", -- rval=CLIENT_INSTALL_ERROR) -- join_args.append("-w") -- join_args.append(password) -- nolog = (password,) -- -- env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = ccache_name -- # Get the CA certificate -+ else: -+ raise ScriptError( -+ "Keytab file could not be found: {}".format( -+ options.keytab), -+ rval=CLIENT_INSTALL_ERROR) -+ elif options.password: -+ nolog = (options.password,) -+ join_args.append("-w") -+ join_args.append(options.password) -+ elif options.prompt_password: -+ if options.unattended: -+ raise ScriptError( -+ "Password must be provided in non-interactive mode", -+ rval=CLIENT_INSTALL_ERROR) - try: -- os.environ['KRB5_CONFIG'] = env['KRB5_CONFIG'] -- get_ca_certs(fstore, options, cli_server[0], cli_basedn, -- cli_realm) -- del os.environ['KRB5_CONFIG'] -- except errors.FileError as e: -- logger.error('%s', e) -- raise ScriptError(rval=CLIENT_INSTALL_ERROR) -- except Exception as e: -- logger.error("Cannot obtain CA certificate\n%s", e) -- raise ScriptError(rval=CLIENT_INSTALL_ERROR) -- -- # Now join the domain -- result = run( -- join_args, raiseonerr=False, env=env, nolog=nolog, -- capture_error=True) -- stderr = result.error_output -+ password = getpass.getpass("Password: ") -+ except EOFError: -+ password = None -+ if not password: -+ raise ScriptError( -+ "Password must be provided.", -+ rval=CLIENT_INSTALL_ERROR) -+ join_args.append("-w") -+ join_args.append(password) -+ nolog = (password,) - -- if result.returncode != 0: -- logger.error("Joining realm failed: %s", stderr) -- if not options.force: -- if result.returncode == 13: -- logger.info( -- "Use --force-join option to override the host " -- "entry on the server and force client enrollment.") -- raise ScriptError(rval=CLIENT_INSTALL_ERROR) -- logger.info( -- "Use ipa-getkeytab to obtain a host " -- "principal for this server.") -- else: -- logger.info("Enrolled in IPA realm %s", cli_realm) -+ env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = ccache_name -+ # Get the CA certificate -+ try: -+ os.environ['KRB5_CONFIG'] = env['KRB5_CONFIG'] -+ get_ca_certs(fstore, options, cli_server[0], cli_basedn, -+ cli_realm) -+ except errors.FileError as e: -+ logger.error('%s', e) -+ raise ScriptError(rval=CLIENT_INSTALL_ERROR) -+ except Exception as e: -+ logger.error("Cannot obtain CA certificate\n%s", e) -+ raise ScriptError(rval=CLIENT_INSTALL_ERROR) - -- if options.principal is not None: -- run([paths.KDESTROY], raiseonerr=False, env=env) -+ # Now join the domain -+ result = run( -+ join_args, raiseonerr=False, env=env, nolog=nolog, -+ capture_error=True) -+ stderr = result.error_output - -- # Obtain the TGT. We do it with the temporary krb5.conf, so that -- # only the KDC we're installing under is contacted. -- # Other KDCs might not have replicated the principal yet. -- # Once we have the TGT, it's usable on any server. -- try: -- kinit_keytab(host_principal, paths.KRB5_KEYTAB, CCACHE_FILE, -- config=krb_name, -- attempts=options.kinit_attempts) -- env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = CCACHE_FILE -- except gssapi.exceptions.GSSError as e: -- print_port_conf_info() -- logger.error("Failed to obtain host TGT: %s", e) -- # failure to get ticket makes it impossible to login and bind -- # from sssd to LDAP, abort installation and rollback changes -+ if result.returncode != 0: -+ logger.error("Joining realm failed: %s", stderr) -+ if not options.force: -+ if result.returncode == 13: -+ logger.info( -+ "Use --force-join option to override the host " -+ "entry on the server and force client enrollment.") - raise ScriptError(rval=CLIENT_INSTALL_ERROR) -+ logger.info( -+ "Use ipa-getkeytab to obtain a host " -+ "principal for this server.") -+ else: -+ logger.info("Enrolled in IPA realm %s", cli_realm) - -- finally: -- try: -- os.remove(krb_name) -- except OSError: -- logger.error("Could not remove %s", krb_name) -- try: -- os.rmdir(ccache_dir) -- except OSError: -- pass -- try: -- os.remove(krb_name + ".ipabkp") -- except OSError: -- logger.error("Could not remove %s.ipabkp", krb_name) -+ if options.principal is not None: -+ run([paths.KDESTROY], raiseonerr=False, env=env) -+ -+ # Obtain the TGT. We do it with the temporary krb5.conf, so that -+ # only the KDC we're installing under is contacted. -+ # Other KDCs might not have replicated the principal yet. -+ # Once we have the TGT, it's usable on any server. -+ try: -+ kinit_keytab(host_principal, paths.KRB5_KEYTAB, CCACHE_FILE, -+ config=krb_name, -+ attempts=options.kinit_attempts) -+ env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = CCACHE_FILE -+ except gssapi.exceptions.GSSError as e: -+ print_port_conf_info() -+ logger.error("Failed to obtain host TGT: %s", e) -+ # failure to get ticket makes it impossible to login and bind -+ # from sssd to LDAP, abort installation and rollback changes -+ raise ScriptError(rval=CLIENT_INSTALL_ERROR) - - # Configure ipa.conf - if not options.on_master: -@@ -2931,23 +2946,6 @@ def _install(options): - except gssapi.exceptions.GSSError as e: - logger.error("Failed to obtain host TGT: %s", e) - raise ScriptError(rval=CLIENT_INSTALL_ERROR) -- else: -- # Configure krb5.conf -- fstore.backup_file(paths.KRB5_CONF) -- configure_krb5_conf( -- cli_realm=cli_realm, -- cli_domain=cli_domain, -- cli_server=cli_server, -- cli_kdc=cli_kdc, -- dnsok=dnsok, -- filename=paths.KRB5_CONF, -- client_domain=client_domain, -- client_hostname=hostname, -- configure_sssd=options.sssd, -- force=options.force) -- -- logger.info( -- "Configured /etc/krb5.conf for IPA realm %s", cli_realm) - - # Clear out any current session keyring information - try: -@@ -3274,6 +3272,23 @@ def _install(options): - configure_nisdomain( - options=options, domain=cli_domain, statestore=statestore) - -+ # Configure the final krb5.conf -+ if not options.on_master: -+ fstore.backup_file(paths.KRB5_CONF) -+ configure_krb5_conf( -+ cli_realm=cli_realm, -+ cli_domain=cli_domain, -+ cli_server=cli_server, -+ cli_kdc=cli_kdc, -+ dnsok=dnsok, -+ filename=paths.KRB5_CONF, -+ client_domain=client_domain, -+ client_hostname=hostname, -+ configure_sssd=options.sssd, -+ force=options.force) -+ -+ logger.info("Configured /etc/krb5.conf for IPA realm %s", cli_realm) -+ - statestore.delete_state('installation', 'complete') - statestore.backup_state('installation', 'complete', True) - logger.info('Client configuration complete.') - diff --git a/SOURCES/0013-Vault-fix-interoperability-issues-with-older-RHEL-systems_rhbz#2148255.patch b/SOURCES/0013-Vault-fix-interoperability-issues-with-older-RHEL-systems_rhbz#2148255.patch deleted file mode 100644 index f8c55fe..0000000 --- a/SOURCES/0013-Vault-fix-interoperability-issues-with-older-RHEL-systems_rhbz#2148255.patch +++ /dev/null @@ -1,123 +0,0 @@ -From c643e56e4c45b7cb61aa53989657143627c23e04 Mon Sep 17 00:00:00 2001 -From: Francisco Trivino -Date: Nov 22 2022 06:56:00 +0000 -Subject: Vault: fix interoperability issues with older RHEL systems - - -AES-128-CBC was recently enabled as default wrapping algorithm for transport of secrets. -This change was done in favor of FIPS as crypto-policies disabled 3DES in RHEL9, but -setting AES as default ended-up breaking backwards compatibility with older RHEL systems. - -This commit is tuning some defaults so that interoperability with older RHEL systems -works again. The new logic reflects: - -- when an old client is calling a new server, it doesn't send any value for wrapping_algo - and the old value is used (3DES), so that the client can decrypt using 3DES. - -- when a new client is calling a new server, it sends wrapping_algo = AES128_CBC - -- when a new client is calling an old server, it doesn't send any value and the default is - to use 3DES. - -Finally, as this logic is able to handle overlapping wrapping algorithm between server and -client, the Option "--wrapping-algo" is hidden from "ipa vault-archive --help" and "ipa -vault-retrieve --help" commands. - -Fixes: https://pagure.io/freeipa/issue/9259 -Signed-off-by: Francisco Trivino -Reviewed-By: Florence Blanc-Renaud -Reviewed-By: Rob Crittenden - ---- - -diff --git a/API.txt b/API.txt -index 9892211..2bd1cc2 100644 ---- a/API.txt -+++ b/API.txt -@@ -6666,7 +6666,7 @@ option: Flag('shared?', autofill=True, default=False) - option: Str('username?', cli_name='user') - option: Bytes('vault_data') - option: Str('version?') --option: StrEnum('wrapping_algo?', autofill=True, default=u'aes-128-cbc', values=[u'aes-128-cbc', u'des-ede3-cbc']) -+option: StrEnum('wrapping_algo?', autofill=True, default=u'des-ede3-cbc', values=[u'aes-128-cbc', u'des-ede3-cbc']) - output: Entry('result') - output: Output('summary', type=[, ]) - output: PrimaryKey('value') -@@ -6766,7 +6766,7 @@ option: Bytes('session_key') - option: Flag('shared?', autofill=True, default=False) - option: Str('username?', cli_name='user') - option: Str('version?') --option: StrEnum('wrapping_algo?', autofill=True, default=u'aes-128-cbc', values=[u'aes-128-cbc', u'des-ede3-cbc']) -+option: StrEnum('wrapping_algo?', autofill=True, default=u'des-ede3-cbc', values=[u'aes-128-cbc', u'des-ede3-cbc']) - output: Entry('result') - output: Output('summary', type=[, ]) - output: PrimaryKey('value') -diff --git a/VERSION.m4 b/VERSION.m4 -index 7d60b01..b4b1774 100644 ---- a/VERSION.m4 -+++ b/VERSION.m4 -@@ -86,8 +86,8 @@ define(IPA_DATA_VERSION, 20100614120000) - # # - ######################################################## - define(IPA_API_VERSION_MAJOR, 2) --# Last change: add graceperiodlimit --define(IPA_API_VERSION_MINOR, 248) -+# Last change: fix vault interoperability issues. -+define(IPA_API_VERSION_MINOR, 251) - - ######################################################## - # Following values are auto-generated from values above -diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py -index 115171c..d4c84eb 100644 ---- a/ipaclient/plugins/vault.py -+++ b/ipaclient/plugins/vault.py -@@ -687,7 +687,7 @@ class ModVaultData(Local): - default_algo = config.get('wrapping_default_algorithm') - if default_algo is None: - # old server -- wrapping_algo = constants.VAULT_WRAPPING_AES128_CBC -+ wrapping_algo = constants.VAULT_WRAPPING_3DES - elif default_algo in constants.VAULT_WRAPPING_SUPPORTED_ALGOS: - # try to use server default - wrapping_algo = default_algo -@@ -801,7 +801,8 @@ class vault_archive(ModVaultData): - if option.name not in ('nonce', - 'session_key', - 'vault_data', -- 'version'): -+ 'version', -+ 'wrapping_algo'): - yield option - for option in super(vault_archive, self).get_options(): - yield option -@@ -1053,7 +1054,7 @@ class vault_retrieve(ModVaultData): - - def get_options(self): - for option in self.api.Command.vault_retrieve_internal.options(): -- if option.name not in ('session_key', 'version'): -+ if option.name not in ('session_key', 'version', 'wrapping_algo'): - yield option - for option in super(vault_retrieve, self).get_options(): - yield option -diff --git a/ipaserver/plugins/vault.py b/ipaserver/plugins/vault.py -index 4d40f66..574c83a 100644 ---- a/ipaserver/plugins/vault.py -+++ b/ipaserver/plugins/vault.py -@@ -1051,7 +1051,7 @@ class vault_archive_internal(PKQuery): - 'wrapping_algo?', - doc=_('Key wrapping algorithm'), - values=VAULT_WRAPPING_SUPPORTED_ALGOS, -- default=VAULT_WRAPPING_DEFAULT_ALGO, -+ default=VAULT_WRAPPING_3DES, - autofill=True, - ), - ) -@@ -1130,7 +1130,7 @@ class vault_retrieve_internal(PKQuery): - 'wrapping_algo?', - doc=_('Key wrapping algorithm'), - values=VAULT_WRAPPING_SUPPORTED_ALGOS, -- default=VAULT_WRAPPING_DEFAULT_ALGO, -+ default=VAULT_WRAPPING_3DES, - autofill=True, - ), - ) diff --git a/SOURCES/1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch b/SOURCES/1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch index e1a74ff..fe9eba6 100644 --- a/SOURCES/1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch +++ b/SOURCES/1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch @@ -15,7 +15,7 @@ diff --git a/freeipa.spec.in b/freeipa.spec.in index 8f5c370e5..e20edb7bc 100755 --- a/freeipa.spec.in +++ b/freeipa.spec.in -@@ -576,11 +576,9 @@ Requires: %{name}-server = %{version}-%{release} +@@ -585,11 +585,9 @@ Requires: %{name}-server = %{version}-%{release} Requires: bind-dyndb-ldap >= 11.2-2 Requires: bind >= %{bind_version} Requires: bind-utils >= %{bind_version} @@ -32,15 +32,16 @@ diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py index 7d21367ec..42a47f1df 100644 --- a/ipaplatform/base/paths.py +++ b/ipaplatform/base/paths.py -@@ -259,7 +259,6 @@ class BasePathNamespace: +@@ -258,8 +258,7 @@ class BasePathNamespace: IPA_PKI_RETRIEVE_KEY = "/usr/libexec/ipa/ipa-pki-retrieve-key" IPA_HTTPD_PASSWD_READER = "/usr/libexec/ipa/ipa-httpd-pwdreader" IPA_PKI_WAIT_RUNNING = "/usr/libexec/ipa/ipa-pki-wait-running" - DNSSEC_KEYFROMLABEL = "/usr/sbin/dnssec-keyfromlabel" -+ DNSSEC_KEYFROMLABEL = "/usr/sbin/dnssec-keyfromlabel-pkcs11" - DNSSEC_KEYFROMLABEL_9_17 = "/usr/bin/dnssec-keyfromlabel" ++ DNSSEC_KEYFROMLABEL = "/usr/sbin/dnssec-keyfromlabel-pkcs11" GETSEBOOL = "/usr/sbin/getsebool" GROUPADD = "/usr/sbin/groupadd" + USERMOD = "/usr/sbin/usermod" diff --git a/ipaplatform/fedora/paths.py b/ipaplatform/fedora/paths.py index 4e993c063..92a948966 100644 --- a/ipaplatform/fedora/paths.py diff --git a/SOURCES/0002-webui-IdP-Remove-arrow-notation-due-to-uglify-js-lim.patch b/SOURCES/1003-webui-IdP-Remove-arrow-notation-due-to-uglify-js-lim.patch similarity index 100% rename from SOURCES/0002-webui-IdP-Remove-arrow-notation-due-to-uglify-js-lim.patch rename to SOURCES/1003-webui-IdP-Remove-arrow-notation-due-to-uglify-js-lim.patch diff --git a/SOURCES/1004-Revert-DNSResolver-Fix-use-of-nameservers-with-ports.patch b/SOURCES/1004-Revert-DNSResolver-Fix-use-of-nameservers-with-ports.patch new file mode 100644 index 0000000..d5fe2d3 --- /dev/null +++ b/SOURCES/1004-Revert-DNSResolver-Fix-use-of-nameservers-with-ports.patch @@ -0,0 +1,114 @@ +From 9a33838407f244e481523fe643bc0626874e8b1a Mon Sep 17 00:00:00 2001 +From: Rafael Guterres Jeffman +Date: Mon, 19 Dec 2022 14:57:03 -0300 +Subject: [PATCH] Revert "DNSResolver: Fix use of nameservers with ports" + +This reverts commit 5e2e4664aec641886923c2bec61ce25b96edb62a. +--- + ipapython/dnsutil.py | 41 ------------------------- + ipatests/test_ipapython/test_dnsutil.py | 40 ------------------------ + 2 files changed, 81 deletions(-) + +diff --git a/ipapython/dnsutil.py b/ipapython/dnsutil.py +index 58de365ab..4baeaf8cc 100644 +--- a/ipapython/dnsutil.py ++++ b/ipapython/dnsutil.py +@@ -144,47 +144,6 @@ class DNSResolver(dns.resolver.Resolver): + nameservers.remove(ipv4_loopback) + self.nameservers = nameservers + +- @dns.resolver.Resolver.nameservers.setter +- def nameservers(self, nameservers): +- """ +- *nameservers*, a ``list`` of nameservers with optional ports: +- "SERVER_IP port PORT_NUMBER". +- +- Overloads dns.resolver.Resolver.nameservers setter to split off ports +- into nameserver_ports after setting nameservers successfully with the +- setter in dns.resolver.Resolver. +- """ +- # Get nameserver_ports if it is already set +- if hasattr(self, "nameserver_ports"): +- nameserver_ports = self.nameserver_ports +- else: +- nameserver_ports = {} +- +- # Check nameserver items in list and split out converted port number +- # into nameserver_ports: { nameserver: port } +- if isinstance(nameservers, list): +- _nameservers = [] +- for nameserver in nameservers: +- splits = nameserver.split() +- if len(splits) == 3 and splits[1] == "port": +- nameserver = splits[0] +- try: +- port = int(splits[2]) +- if port < 0 or port > 65535: +- raise ValueError() +- except ValueError: +- raise ValueError( +- "invalid nameserver: %s is not a valid port" % +- splits[2]) +- nameserver_ports[nameserver] = port +- _nameservers.append(nameserver) +- nameservers = _nameservers +- +- # Call dns.resolver.Resolver.nameservers setter +- dns.resolver.Resolver.nameservers.__set__(self, nameservers) +- # Set nameserver_ports after successfull call to setter +- self.nameserver_ports = nameserver_ports +- + + class DNSZoneAlreadyExists(dns.exception.DNSException): + supp_kwargs = {'zone', 'ns'} +diff --git a/ipatests/test_ipapython/test_dnsutil.py b/ipatests/test_ipapython/test_dnsutil.py +index 09463c69d..5e7a46197 100644 +--- a/ipatests/test_ipapython/test_dnsutil.py ++++ b/ipatests/test_ipapython/test_dnsutil.py +@@ -101,43 +101,3 @@ class TestSortURI: + assert dnsutil.sort_prio_weight([h3, h2, h1]) == [h1, h2, h3] + assert dnsutil.sort_prio_weight([h3, h3, h3]) == [h3] + assert dnsutil.sort_prio_weight([h2, h2, h1, h1]) == [h1, h2] +- +- +-class TestDNSResolver: +- def test_nameservers(self): +- res = dnsutil.DNSResolver() +- res.nameservers = ["4.4.4.4", "8.8.8.8"] +- assert res.nameservers == ["4.4.4.4", "8.8.8.8"] +- +- def test_nameservers_with_ports(self): +- res = dnsutil.DNSResolver() +- res.nameservers = ["4.4.4.4 port 53", "8.8.8.8 port 8053"] +- assert res.nameservers == ["4.4.4.4", "8.8.8.8"] +- assert res.nameserver_ports == {"4.4.4.4": 53, "8.8.8.8": 8053} +- +- res.nameservers = ["4.4.4.4 port 53", "8.8.8.8 port 8053"] +- assert res.nameservers == ["4.4.4.4", "8.8.8.8"] +- assert res.nameserver_ports == {"4.4.4.4": 53, "8.8.8.8": 8053} +- +- def test_nameservers_with_bad_ports(self): +- res = dnsutil.DNSResolver() +- try: +- res.nameservers = ["4.4.4.4 port a"] +- except ValueError: +- pass +- else: +- pytest.fail("No fail on bad port a") +- +- try: +- res.nameservers = ["4.4.4.4 port -1"] +- except ValueError: +- pass +- else: +- pytest.fail("No fail on bad port -1") +- +- try: +- res.nameservers = ["4.4.4.4 port 65536"] +- except ValueError: +- pass +- else: +- pytest.fail("No fail on bad port 65536") +-- +2.38.1 + diff --git a/SOURCES/freeipa-4.9.10.tar.gz.asc b/SOURCES/freeipa-4.9.10.tar.gz.asc deleted file mode 100644 index 2804c24..0000000 --- a/SOURCES/freeipa-4.9.10.tar.gz.asc +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIzBAABCAAdFiEE11Z2TU1+KXxtrRFyaYdvcqbi008FAmKp71wACgkQaYdvcqbi -008rbg/9G5w7KXgJcrhwBx5qqd4fqzSnwJdyN5oaBIEKNsAigMD7LIYawqgnO3g/ -/3FmJTbeCrOj9EoakvE1YNRT+75oxAO+rMFcRvFHlJyfMCa3r3lrS4LrlQiiyNwZ -IHovcXr0Q3fizhp/V3acyZqx2pbnSh24CK4q5a1CNUs8SPkEFcOfpAJIMQCHeH6t -ScfxuWOp8R1FnaNQc/9x3vy3ySQbHMxIWLSfJy7pk7FhLGAvgVNQBAz70Bg7BfR1 -R1V6syGeaPmqLOQw0jV05YMxyKwkbnSK/h2DlCg/iNQ/S71rXhOpuk01dDf73CI4 -Fu1H9TX50Indq31+4qbOlKZqDshhNzRRpn2m2qVvzeTfObHlZMbYNyVamovP9fEZ -pfJcppI8aNDURjqpf/sVy4G8mhI5FQS+Q7bKvv9C04iE3XpTutg8q5mLMXGwWekY -yeklBAmdygOKsY1uWb7BCH9eoWCVWKIwi4m5uYteZNxBt4aqsa/VFsxCE1P2T7/S -+yc1Jo7hXWW8v3wm+dIGJj+Lz9YlJxC9SAiC72a6kTwIe2gnKlxoYbqe/18hEWm6 -0jESl2LiXfBhXz0YQlv2HjcPWZMMrNuhSCGTMgzP8KfZB258mtxpbBTk5/e9Wgsk -29GCfaMWFUqZsrteG10HT/P6cotre6EVffQl9lNlPNQpX+DUKy4= -=azus ------END PGP SIGNATURE----- diff --git a/SOURCES/freeipa-4.9.11.tar.gz.asc b/SOURCES/freeipa-4.9.11.tar.gz.asc new file mode 100644 index 0000000..47ddb7d --- /dev/null +++ b/SOURCES/freeipa-4.9.11.tar.gz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCAAdFiEE11Z2TU1+KXxtrRFyaYdvcqbi008FAmOA8kcACgkQaYdvcqbi +00887g/9GTvueJCypiuTqxKsbkTbWamOyH3W+AqtHw9Ff+wM/hnkSloGizhQ4EZZ +4Zs1e6bfM1pGXT7DXU9WbiYtcVtUhY5l9SnT9moCMaG1z4aB7z9UCxsqsSCuy3bG +KQq6AO2z4DaqHiz6ez3QXi+MUCNnPziWmS3bLdDCrTK0PNxqiMPIotlXMgVFgDL7 +go/TAUvUL27zH4ELvG4parSGEKVEqe//RzXklOwGrInyj/4u42x7lUdO2ugOolCI +wNod8v+NWQWVgxNyhfTjP5VBZzO9wkGx4xruF2cAjVdjnIUGcG0FR3hI/bpi7Lyv +EmIozbQMK92MLel63E7Z/d5Jxfmuw/n1t5NrgSth+9hhWnBEpiaKkD2zAmUATqHf ++y4mbrtajmjzewEnfUnQfCvSLDPyTpnQKkRY8hUvk7u/J+/ZFWMQl9RdGNw3M0Zr +WrsqkKLK/n5IOHYHb/lBRaUidssKjQYFIvyNfHDP/lu6iiyLOpi5MIdk9BakO5wc +oDMk3w9xY7tPPmoesW40BThnAdOR9U4aad8zVvOxhMfzAYRwu95HGQoHnk7/rNut +IfzMZVjVTLQ8gyApcBlWzu/buiOoEXTKaMyzs0S9RMptknj5Xf0CGRz3bVrZRfJd +umyhD6/rNk3eZW/yEIv3IqFev0h1txTBPSTlczYUIz6uc7nx82E= +=8YVm +-----END PGP SIGNATURE----- diff --git a/SPECS/ipa.spec b/SPECS/ipa.spec index 83173c6..4aab5cf 100644 --- a/SPECS/ipa.spec +++ b/SPECS/ipa.spec @@ -68,8 +68,7 @@ %global krb5_kdb_version 8.0 # 0.7.16: https://github.com/drkjam/netaddr/issues/71 %global python_netaddr_version 0.7.19 -# Require 4.14.5-13 which brings CVE-2020-25717 fixes -%global samba_version 4.14.5-13 +%global samba_version 4.17.2-1 %global selinux_policy_version 3.14.3-52 %global slapi_nis_version 0.56.4 %global python_ldap_version 3.1.0-1 @@ -93,8 +92,7 @@ # 0.7.16: https://github.com/drkjam/netaddr/issues/71 %global python_netaddr_version 0.7.16 -# Require 4.14.6 which brings CVE-2020-25717 fixes -%global samba_version 2:4.14.6 +%global samba_version 2:4.17.2 # 3.14.5-45 or later includes a number of interfaces fixes for IPA interface %global selinux_policy_version 3.14.5-45 @@ -178,7 +176,7 @@ # Work-around fact that RPM SPEC parser does not accept # "Version: @VERSION@" in freeipa.spec.in used for Autoconf string replacement -%define IPA_VERSION 4.9.10 +%define IPA_VERSION 4.9.11 # Release candidate version -- uncomment with one percent for RC versions #%%global rc_version %%nil %define AT_SIGN @ @@ -191,7 +189,7 @@ Name: %{package_name} Version: %{IPA_VERSION} -Release: 9%{?rc_version:.%rc_version}%{?dist} +Release: 5%{?rc_version:.%rc_version}%{?dist} Summary: The Identity, Policy and Audit system License: GPLv3+ @@ -211,27 +209,28 @@ Source1: https://releases.pagure.org/freeipa/freeipa-%{version}%{?rc_vers # RHEL spec file only: START %if %{NON_DEVELOPER_BUILD} %if 0%{?rhel} >= 8 -Patch0001: 0001-ipa-otpd-Fix-build-on-older-versions-of-gcc.patch -Patch0002: 0002-webui-IdP-Remove-arrow-notation-due-to-uglify-js-lim.patch -Patch0003: 0003-Preserve-user-fix-the-confusing-summary_rhbz#2022028.patch -Patch0004: 0004-Only-calculate-LDAP-password-grace-when-the-password_rhbz#782917.patch -Patch0005: 0005-Add-end-to-end-integration-tests-for-external-IdP.patch -Patch0006: 0006-webui-Do-not-allow-empty-pagination-size_rhbz#2094672.patch -Patch0007: 0007-webui-Allow-grace-login-limit_rhbz#2109243.patch -Patch0008: 0008-check_repl_update-in-progress-is-a-boolean_rhbz#2117303.patch -Patch0009: 0009-Disabling-gracelimit-does-not-prevent-LDAP-binds_rhbz#2109236.patch -Patch0010: 0010-Set-passwordgracelimit-to-match-global-policy-on-group-pw-policies_rhbz#2115475.patch -Patch0011: 0011-fix-canonicalization-issue-in-Web-UI_rhbz#2133050.patch -Patch0012: 0012-Defer-creating-the-final-krb5-conf-on-clients_rhbz#2150246.patch -Patch0013: 0013-Vault-fix-interoperability-issues-with-older-RHEL-systems_rhbz#2148255.patch +Patch0001: 0001-updates-fix-memberManager-ACI-to-allow-managers-from-a-specified-group_rhbz#2056009.patch +Patch0002: 0002-trust-add-handle-missing-msSFU30MaxGidNumber_rhbz#2162355.patch +Patch0003: 0003-Backport-latest-test-fixes-python3-ipatests_rhbz#2166929.patch +Patch0004: 0004-server-install-remove-error-log-about-missing-bkup-file_rhbz#2160389.patch +Patch0005: 0005-automember-rebuild-add-a-notice-about-high-CPU-usage_rhbz#2018198.patch +Patch0006: 0006-ipa-kdb-PAC-consistency-checker-needs-to-handle-child-domains-as-well_rhbz#2166324.patch +Patch0007: 0007-Wipe-the-ipa-ca-DNS-record-when-updating-system-records_rhbz#2158775.patch Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch Patch1002: 1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch +Patch1003: 1003-webui-IdP-Remove-arrow-notation-due-to-uglify-js-lim.patch +# Due to behavior changes in python3-dns 2.2.0, IPA overrides the setting of the +# nameserver property inherited from dns.resolver.Resolver class to allow the +# setting of nameservers with custom ports. The method used is only needed, and +# only works, on version 2.2.0, or later, of python3-dns. For RHEL 8, which uses +# series 1.xx, the method override is not needed to provide the same behavior. +Patch1004: 1004-Revert-DNSResolver-Fix-use-of-nameservers-with-ports.patch %endif %endif # RHEL spec file only: END -# For the timestamp trick in patch application -BuildRequires: diffstat +## For the timestamp trick in patch application +#BuildRequires: diffstat BuildRequires: openldap-devel # For KDB DAL version, make explicit dependency so that increase of version @@ -298,6 +297,7 @@ BuildRequires: cracklib-dicts # Build dependencies for makeapi/makeaci # BuildRequires: python3-cffi +# RHEL 8 packages will not work with python3-dns 2.2.0 or newer. BuildRequires: python3-dns BuildRequires: python3-ldap >= %{python_ldap_version} BuildRequires: python3-libsss_nss_idmap @@ -350,6 +350,7 @@ BuildRequires: python3-cryptography >= 1.6 BuildRequires: python3-custodia >= 0.3.1 BuildRequires: python3-dateutil BuildRequires: python3-dbus +# RHEL 8 packages will not work with python3-dns 2.2.0 or newer. BuildRequires: python3-dns >= 1.15 BuildRequires: python3-docker BuildRequires: python3-gssapi >= 1.2.0 @@ -424,7 +425,6 @@ Requires: nss-tools >= %{nss_version} Requires(post): krb5-server >= %{krb5_version} Requires(post): krb5-server >= %{krb5_base_version} Requires: krb5-kdb-version = %{krb5_kdb_version} -Requires: krb5-pkinit-openssl >= %{krb5_version} Requires: cyrus-sasl-gssapi%{?_isa} Requires: chrony Requires: httpd >= %{httpd_version} @@ -522,6 +522,7 @@ Requires: python3-augeas Requires: augeas-libs >= %{augeas_version} Requires: python3-custodia >= 0.3.1 Requires: python3-dbus +# RHEL 8 packages will not work with python3-dns 2.2.0 or newer. Requires: python3-dns >= 1.15 Requires: python3-gssapi >= 1.2.0 Requires: python3-ipaclient = %{version}-%{release} @@ -652,6 +653,8 @@ Requires: python3-sssdconfig >= %{sssd_version} Requires: cyrus-sasl-gssapi%{?_isa} Requires: chrony Requires: krb5-workstation >= %{krb5_version} +# Support pkinit with client install +Requires: krb5-pkinit-openssl >= %{krb5_version} # authselect: sssd profile with-subid %if 0%{?fedora} >= 36 Requires: authselect >= 1.4.0 @@ -751,6 +754,7 @@ Requires: %{name}-common = %{version}-%{release} Requires: python3-ipalib = %{version}-%{release} Requires: python3-augeas Requires: augeas-libs >= %{augeas_version} +# RHEL 8 packages will not work with python3-dns 2.2.0 or newer. Requires: python3-dns >= 1.15 Requires: python3-jinja2 @@ -831,6 +835,7 @@ Requires: python3-cffi Requires: python3-cryptography >= 1.6 Requires: python3-dateutil Requires: python3-dbus +# RHEL 8 packages will not work with python3-dns 2.2.0 or newer. Requires: python3-dns >= 1.15 Requires: python3-gssapi >= 1.2.0 Requires: python3-jwcrypto >= 0.4.2 @@ -947,22 +952,8 @@ Custom SELinux policy module for FreeIPA %prep -# Update timestamps on the files touched by a patch, to avoid non-equal -# .pyc/.pyo files across the multilib peers within a build, where "Level" -# is the patch prefix option (e.g. -p1) -# Taken from specfile for sssd and python-simplejson -UpdateTimestamps() { - Level=$1 - PatchFile=$2 - # Locate the affected files: - for f in $(diffstat $Level -l $PatchFile); do - # Set the files to have the same timestamp as that of the patch: - touch -c -r $PatchFile $f - done -} - -%setup -n freeipa-%{version}%{?rc_version} -q +%autosetup -n freeipa-%{version}%{?rc_version} -N -p1 # To allow proper application patches to the stripped po files, strip originals pushd po @@ -972,10 +963,8 @@ for i in *.po ; do done popd -for p in %patches ; do - %__patch -p1 -i $p - UpdateTimestamps -p1 $p -done +%autopatch -p1 + %build # PATH is workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1005235 @@ -1245,7 +1234,7 @@ if [ $1 -gt 1 ] ; then %{__python3} -c 'from ipaclient.install.client import configure_krb5_snippet; configure_krb5_snippet()' >>/var/log/ipaupgrade.log 2>&1 %{__python3} -c 'from ipaclient.install.client import update_ipa_nssdb; update_ipa_nssdb()' >>/var/log/ipaupgrade.log 2>&1 - chmod 0600 /var/log/ipaupgrade.lo + chmod 0600 /var/log/ipaupgrade.log SSH_CLIENT_SYSTEM_CONF="/etc/ssh/ssh_config" if [ -f "$SSH_CLIENT_SYSTEM_CONF" ]; then sed -E --in-place=.orig 's/^(HostKeyAlgorithms ssh-rsa,ssh-dss)$/# disabled by ipa-client update\n# \1/' "$SSH_CLIENT_SYSTEM_CONF" @@ -1726,19 +1715,63 @@ fi %endif %changelog -* Mon Dec 5 2022 Rafael Jeffman - 4.9.10-9 -- Exclude installed policy module file from RPM verification - Resolves: RHBZ#2150243 +* Fri Feb 10 2023 Rafael Jeffman - 4.9.11-5 +- Wipe the ipa-ca DNS record when updating system records + Resolves: RHBZ#2158775 -* Fri Dec 2 2022 Rafael Jeffman - 4.9.10-8 +* Thu Feb 09 2023 Rafael Jeffman - 4.9.11-4 +- trust-add: handle missinf msSFU30MaxGidNumber + Resolves: RHBZ#2162355 +- Backport latest test fixes for python3-ipatests + Resolves: RHBZ#2166929 +- server install: remove error log about missing bkup file + Resolves: RHBZ#2160389 +- automember-rebuild: add a notice about high CPU usage + Resolves: RHBZ#2018198 +- ipa-kdb: PAC consistency checker needs to handle child domains as well + Resolves: RHBZ#2166324 + +* Mon Dec 19 2022 Rafael Jeffman - 4.9.11-3 +- Revert DNSResolver Fix use of nameservers with ports. + Related: RHBZ#2141316 + +* Fri Dec 16 2022 Rafael Jeffman - 4.9.11-2 +- webui IdP: Remove arrow notation due to uglify-js limitation + Related: RHBZ#2141316 + +* Wed Dec 14 2022 Rafael Jeffman - 4.9.11-1 +- Rebase ipa to 4.9.11 + Resolves: RHBZ#2141316 +- updates: fix memberManager ACI to allow managers from a specified group + Resolves: RHBZ#2056009 - Defer creating the final krb5.conf on clients - Resolves: RHBZ#2150246 -- Vault: fix interoperability issues with older RHEL systems - Resolves: RHBZ#2148255 + Resolves: RHBZ#2148259 +- Exclude installed policy module file from RPM verification + Resolves: RHBZ#2149567 +- Spec file: ipa-client depends on krb5-pkinit-openssl + Resolves: RHBZ#2149889 -* Thu Oct 13 2022 Rafael Jeffman - 4.9.10-7 +* Thu Nov 24 2022 Rafael Jeffman - 4.9.10-8 +- ipa man page format the EXAMPLES section + Resolves: RHBZ#2129895 - Fix canonicalization issue in Web UI - Resolves: RHBZ#2133050 + Resolves: RHBZ#2127035 +- Remove idnssoaserial argument from dns zone API. + Resolves: RHBZ#2108630 +- Warn for permissions with read/write/search/compare and no attrs + Resolves: RHBZ#2098187 +- Add PKINIT support to ipa-client-install + Resolves: RHBZ#2075452 +- Generate CNAMEs for TXT+URI location krb records + Resolves: RHBZ#2104185 +- Vault: fix interoperability issues with older RHEL systems + Resolves: RHBZ#2144737 +- Fix typo on ipaupgrade.log chmod during RPM %post snipppet + Resolves: RHBZ#2140994 + +* Tue Nov 1 2022 Rafael Jeffman - 4.9.10-7 +- Rebuild to samba 4.17.2. + Related: RHBZ#2132051 * Mon Aug 22 2022 Rafael Jeffman - 4.9.10-6 - webui: Allow grace login limit