import ipa-4.10.1-6.el9

This commit is contained in:
CentOS Sources 2023-05-09 05:18:49 +00:00 committed by Stepan Oksanichenko
parent d43259bde1
commit 8d6169b43d
44 changed files with 2900 additions and 17713 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/freeipa-4.10.0.tar.gz SOURCES/freeipa-4.10.1.tar.gz

View File

@ -1 +1 @@
901ede9686abffef511c6477d90d5e6fd32d6fbc SOURCES/freeipa-4.10.0.tar.gz 6203cf7c2e003c35eb9ac40e4fd2954c6bea1856 SOURCES/freeipa-4.10.1.tar.gz

View File

@ -1,56 +0,0 @@
From 22d1392a8a0d2887c389dcd78be06104cff88d30 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
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 <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
---
.../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 0860b5c20fc86687f80ee6f2426e23c87123130f..a3f57cb4bd7a2a66d70fae98cca0f62a8f0c017f 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

View File

@ -0,0 +1,44 @@
From 42be04fe4ff317efe599dcbc2637f94ecc6fa220 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Mon, 21 Nov 2022 16:12:46 +0200
Subject: [PATCH] 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 <abokovoy@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
install/updates/20-aci.update | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/install/updates/20-aci.update b/install/updates/20-aci.update
index a168bb9573a9fbb9ff15f0b19bb8ec75b48d82a9..4a7ba137c4711aa3f8b064fdd482ffee76c59949 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
--
2.38.1

View File

@ -0,0 +1,42 @@
From 2d0a0cc40fb8674f30ba62980b1953cef840009e Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Thu, 1 Dec 2022 13:58:58 +0100
Subject: [PATCH] Spec file: ipa-client depends on krb5-pkinit-openssl
Now that ipa-client-installs supports pkinit, the package
depends on krb5-pkinit-openssl.
Update the spec file, move the dependency from ipa-server
to ipa-client subpackage.
Fixes: https://pagure.io/freeipa/issue/9290
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
---
freeipa.spec.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/freeipa.spec.in b/freeipa.spec.in
index f09741d7ad6c09e52c4bd24fcc9300584f83a49d..7dcf2e66abe40e6bde3491268b9c012f7578a8b6 100755
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -449,7 +449,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}
@@ -675,6 +674,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
--
2.38.1

View File

@ -1,67 +0,0 @@
From 02d3fb8266d8199fd1ed983de6c57b269546df82 Mon Sep 17 00:00:00 2001
From: Armando Neto <abiagion@redhat.com>
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 <abiagion@redhat.com>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
---
.../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 46aabc9c4dd47aa3874cb3ddf27da048607b7516..140ee8fe0d7adc274396248aae0be2f4559db27a 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 5f7ffb54ee33e9b453d6b987b7bf84d6f4311ebd..aca9e1a99e1e2cf60790fe8c33a65430e0d535e2 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

View File

@ -0,0 +1,54 @@
From 894dca12c120f0bfa705307a0609da47326b8fb2 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Thu, 12 Jan 2023 11:26:53 +0100
Subject: [PATCH] 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 <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
ipaclient/install/client.py | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py
index e5d3e8223efa1ebb69a1b7e963c394f9e1f38816..6e7f17d5b69581320866627cb5747a050cb6e32e 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
--
2.39.1

View File

@ -1,69 +0,0 @@
From aca97507cd119ad55e0c3c18ca65087cb5576c82 Mon Sep 17 00:00:00 2001
From: Sumedh Sidhaye <ssidhaye@redhat.com>
Date: Mon, 13 Jun 2022 13:49:08 +0530
Subject: [PATCH] Added a check while removing 'cert_dir'. The teardown method
is called even if all the tests are skipped since the required PKI version is
not present. The teardown is trying to remove a non-existent directory.
Currently the cert_dir attribute is only present if IPA installation was
done. If IPA was not installed the attribute does not exist.
In order that the uninstall code finds the attribute a class attribute
is added.
Pagure Issue: https://pagure.io/freeipa/issue/9179
Signed-off-by: Sumedh Sidhaye <ssidhaye@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
ipatests/test_integration/test_caless.py | 12 +++++++++++-
.../test_integration/test_random_serial_numbers.py | 6 ++++++
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/ipatests/test_integration/test_caless.py b/ipatests/test_integration/test_caless.py
index 96f477bbe4b0e25184605a80659b5ec6529a2320..4c370f77e84215714e533b1b6ebeb89216319c0f 100644
--- a/ipatests/test_integration/test_caless.py
+++ b/ipatests/test_integration/test_caless.py
@@ -122,6 +122,15 @@ def replica_install_teardown(func):
class CALessBase(IntegrationTest):
+ # The teardown method is called even if all the tests are skipped
+ # since the required PKI version is not present.
+ # The teardown is trying to remove a non-existent directory.
+ # Currently the cert_dir attribute is only present if IPA installation was
+ # done. If IPA was not installed the attribute does not exist.
+ # In order that the uninstall code finds the attribute a class attribute
+ # is added.
+ cert_dir = None
+
@classmethod
def install(cls, mh):
cls.cert_dir = tempfile.mkdtemp(prefix="ipatest-")
@@ -164,7 +173,8 @@ class CALessBase(IntegrationTest):
@classmethod
def uninstall(cls, mh):
# Remove the NSS database
- shutil.rmtree(cls.cert_dir)
+ if cls.cert_dir:
+ shutil.rmtree(cls.cert_dir)
super(CALessBase, cls).uninstall(mh)
@classmethod
diff --git a/ipatests/test_integration/test_random_serial_numbers.py b/ipatests/test_integration/test_random_serial_numbers.py
index a931c7b562f00f94e10d1e9e891fbf0624d5fd88..c52cfa4ed50e2718791b0844d743fb240d26b365 100644
--- a/ipatests/test_integration/test_random_serial_numbers.py
+++ b/ipatests/test_integration/test_random_serial_numbers.py
@@ -64,3 +64,9 @@ class TestServerCALessToExternalCA_RSN(TestServerCALessToExternalCA):
if not pki_supports_RSNv3(mh.master):
raise pytest.skip("RNSv3 not supported")
super(TestServerCALessToExternalCA_RSN, cls).install(mh)
+
+ @classmethod
+ def uninstall(cls, mh):
+ if not pki_supports_RSNv3(mh.master):
+ raise pytest.skip("RSNv3 not supported")
+ super(TestServerCALessToExternalCA_RSN, cls).uninstall(mh)
--
2.37.2

View File

@ -0,0 +1,118 @@
From 2520a7adff7a49ddcddaaf19f0e586425dc0d878 Mon Sep 17 00:00:00 2001
From: Filip Dvorak <fdvorak@redhat.com>
Date: Tue, 6 Dec 2022 15:51:27 +0100
Subject: [PATCH] ipa tests: Add LANG before kinit command to fix issue with
locale settings
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Michal Polovka <mpolovka@redhat.com>
---
ipatests/test_integration/test_krbtpolicy.py | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/ipatests/test_integration/test_krbtpolicy.py b/ipatests/test_integration/test_krbtpolicy.py
index eae16247bdfb195c1d91209cf2d11eac4c25018f..269cfb0a191821c229aaeb5a3eda0181c6e3ae62 100644
--- a/ipatests/test_integration/test_krbtpolicy.py
+++ b/ipatests/test_integration/test_krbtpolicy.py
@@ -23,7 +23,7 @@ PASSWORD = "Secret123"
USER1 = "testuser1"
USER2 = "testuser2"
MAXLIFE = 86400
-
+LANG_PKG = ["langpacks-en"]
def maxlife_within_policy(input, maxlife, slush=3600):
"""Given klist output of the TGT verify that it is within policy
@@ -45,7 +45,6 @@ def maxlife_within_policy(input, maxlife, slush=3600):
return maxlife >= diff >= maxlife - slush
-
@pytest.fixture
def reset_to_default_policy():
"""Reset default user authentication and user authentication type"""
@@ -70,7 +69,7 @@ def reset_to_default_policy():
def kinit_check_life(master, user):
"""Acquire a TGT and check if it's within the lifetime window"""
master.run_command(["kinit", user], stdin_text=f"{PASSWORD}\n")
- result = master.run_command("klist | grep krbtgt")
+ result = master.run_command("LANG=en_US.utf-8 klist | grep krbtgt")
assert maxlife_within_policy(result.stdout_text, MAXLIFE) is True
@@ -81,6 +80,7 @@ class TestPWPolicy(IntegrationTest):
@classmethod
def install(cls, mh):
+ tasks.install_packages(cls.master, LANG_PKG)
tasks.install_master(cls.master)
tasks.create_active_user(cls.master, USER1, PASSWORD)
tasks.create_active_user(cls.master, USER2, PASSWORD)
@@ -100,7 +100,7 @@ class TestPWPolicy(IntegrationTest):
master.run_command(['kinit', USER1],
stdin_text=PASSWORD + '\n')
- result = master.run_command('klist | grep krbtgt')
+ result = master.run_command("LANG=en_US.utf-8 klist | grep krbtgt")
assert maxlife_within_policy(result.stdout_text, MAXLIFE) is True
def test_krbtpolicy_password_and_hardended(self):
@@ -122,7 +122,7 @@ class TestPWPolicy(IntegrationTest):
master.run_command(['kinit', USER1],
stdin_text=PASSWORD + '\n')
- result = master.run_command('klist | grep krbtgt')
+ result = master.run_command('LANG=en_US.utf-8 klist | grep krbtgt')
assert maxlife_within_policy(result.stdout_text, 600,
slush=600) is True
@@ -131,7 +131,7 @@ class TestPWPolicy(IntegrationTest):
# Verify that the short policy only applies to USER1
master.run_command(['kinit', USER2],
stdin_text=PASSWORD + '\n')
- result = master.run_command('klist | grep krbtgt')
+ result = master.run_command('LANG=en_US.utf-8 klist | grep krbtgt')
assert maxlife_within_policy(result.stdout_text, MAXLIFE) is True
def test_krbtpolicy_hardended(self):
@@ -151,7 +151,7 @@ class TestPWPolicy(IntegrationTest):
master.run_command(['kinit', USER1],
stdin_text=PASSWORD + '\n')
- result = master.run_command('klist | grep krbtgt')
+ result = master.run_command('LANG=en_US.utf-8 klist | grep krbtgt')
assert maxlife_within_policy(result.stdout_text, 1800,
slush=1800) is True
@@ -160,7 +160,7 @@ class TestPWPolicy(IntegrationTest):
# Verify that the short policy only applies to USER1
master.run_command(['kinit', USER2],
stdin_text=PASSWORD + '\n')
- result = master.run_command('klist | grep krbtgt')
+ result = master.run_command('LANG=en_US.utf-8 klist | grep krbtgt')
assert maxlife_within_policy(result.stdout_text, MAXLIFE) is True
def test_krbtpolicy_password(self):
@@ -173,7 +173,7 @@ class TestPWPolicy(IntegrationTest):
master.run_command(['kinit', USER2],
stdin_text=PASSWORD + '\n')
- result = master.run_command('klist | grep krbtgt')
+ result = master.run_command('LANG=en_US.utf-8 klist | grep krbtgt')
assert maxlife_within_policy(result.stdout_text, 1200,
slush=1200) is True
@@ -183,7 +183,7 @@ class TestPWPolicy(IntegrationTest):
master.run_command(['ipa', 'krbtpolicy-reset', USER2])
master.run_command(['kinit', USER2],
stdin_text=PASSWORD + '\n')
- result = master.run_command('klist | grep krbtgt')
+ result = master.run_command('LANG=en_US.utf-8 klist | grep krbtgt')
assert maxlife_within_policy(result.stdout_text, MAXLIFE) is True
def test_krbtpolicy_otp(self, reset_to_default_policy):
--
2.39.1

View File

@ -1,55 +0,0 @@
From c55185d3dc3c6cd2ffebab77fbf8caa40a32bcd1 Mon Sep 17 00:00:00 2001
From: Erik <ebelko@redhat.com>
Date: Mon, 18 Jul 2022 11:59:24 +0200
Subject: [PATCH] ipatests: healthcheck: test if system is FIPS enabled
Test if FIPS is enabled and the check exists.
Related: https://pagure.io/freeipa/issue/8951
Signed-off-by: Erik Belko <ebelko@redhat.com>
Reviewed-By: Michal Polovka <mpolovka@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
.../test_integration/test_ipahealthcheck.py | 25 +++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/ipatests/test_integration/test_ipahealthcheck.py b/ipatests/test_integration/test_ipahealthcheck.py
index 23af09f3a7eaa8012e7a898ce6a534d1fad45323..a0c85f79e6e84f9e63072c6d70276480e4af97ad 100644
--- a/ipatests/test_integration/test_ipahealthcheck.py
+++ b/ipatests/test_integration/test_ipahealthcheck.py
@@ -340,6 +340,31 @@ class TestIpaHealthCheck(IntegrationTest):
assert returncode == 0
assert output == "No issues found."
+ def test_ipa_healthcheck_fips_enabled(self):
+ """
+ Test if FIPS is enabled and the check exists.
+
+ https://pagure.io/freeipa/issue/8951
+ """
+ returncode, check = run_healthcheck(self.master,
+ source="ipahealthcheck.meta.core",
+ check="MetaCheck",
+ output_type="json",
+ failures_only=False)
+ assert returncode == 0
+
+ cmd = self.master.run_command(['fips-mode-setup', '--is-enabled'],
+ raiseonerr=False)
+ returncode = cmd.returncode
+
+ # If this produces IndexError, the check does not exist
+ if check[0]["kw"]["fips"] == "disabled":
+ assert returncode == 2
+ elif check[0]["kw"]["fips"] == "enabled":
+ assert returncode == 0
+ else:
+ assert returncode == 1
+
def test_ipa_healthcheck_after_certupdate(self):
"""
Verify that ipa-certupdate hasn't messed up tracking
--
2.37.2

View File

@ -0,0 +1,48 @@
From 97fc368df2db3b559a9def236d3c3e0a12bcdd0a Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Mon, 23 Jan 2023 20:28:17 +0100
Subject: [PATCH] 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=<domain>,CN=ypservers,CN=ypServ30,CN=RpcServices,CN=System,<AD suffix>
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 <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
ipaserver/plugins/trust.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/ipaserver/plugins/trust.py b/ipaserver/plugins/trust.py
index c074f6d6e609476e416c95bcbe607654718ae9ce..79264b8d8a3b15dd4e5d0553e4ce42194b0ae044 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])
--
2.39.1

View File

@ -1,125 +0,0 @@
From 1bb4ff9ed2313fb3c2bd1418258c5bcec557b6a5 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
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 <rcritten@redhat.com>
Reviewed-By: Francisco Trivino <ftrivino@redhat.com>
---
.../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 a3f57cb4bd7a2a66d70fae98cca0f62a8f0c017f..345e1dee7d163167373ca82dedb1e827f0e1bc8c 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 6d66982848ac5a0061b47d30fad022be055c93e4..41d6e9070a90c2bde7b3182ad6ecf1a923bba203 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

View File

@ -0,0 +1,337 @@
From 51b1c22d025bf40e9ef488bb0faf0c8dff303ccd Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Thu, 8 Dec 2022 16:18:07 -0500
Subject: [PATCH] doc: Design for certificate pruning
This describes how the certificate pruning capability of PKI
introduced in v11.3.0 will be integrated into IPA, primarily for
ACME.
Related: https://pagure.io/freeipa/issue/9294
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
---
doc/designs/expired_certificate_pruning.md | 297 +++++++++++++++++++++
doc/designs/index.rst | 1 +
2 files changed, 298 insertions(+)
create mode 100644 doc/designs/expired_certificate_pruning.md
diff --git a/doc/designs/expired_certificate_pruning.md b/doc/designs/expired_certificate_pruning.md
new file mode 100644
index 0000000000000000000000000000000000000000..2c10d914020d3c12b6abb028323cd6796ec33e00
--- /dev/null
+++ b/doc/designs/expired_certificate_pruning.md
@@ -0,0 +1,297 @@
+# Expired Certificate Pruning
+
+## Overview
+
+https://pagure.io/dogtagpki/issue/1750
+
+When using short-lived certs and regular issuance, the expired certs can build up in the PKI database and cause issues with replication, performance and overall database size.
+
+PKI has provided a new feature in 11.3.0, pruning, which is a job that can be executed on a schedule or manually to remove expired certificates and requests.
+
+Random Serial Numbers v3 (RSNv3) is mandatory to enable pruning.
+
+Both pruning and RSNv3 require PKI 11.3.0 or higher.
+
+## Use Cases
+
+ACME certificates in particular are generally short-lived and expired certificates can build up quickly in a dynamic environment. An example is a CI system that requests one or more certificates per run. These will build up infinitely without a way to remove the expired certificates.
+
+Another case is simply a very long-lived installation. Over time as hosts come and go certificates build up.
+
+## How to Use
+
+https://github.com/dogtagpki/pki/wiki/Configuring-CA-Database-Pruning provides a thorough description of the capabilities of the pruning job.
+
+The default configuration is to remove expired certificates and incomplete requests after 30 days.
+
+Pruning is disabled by default.
+
+Configuration is a four-step process:
+
+1. Configure the expiration thresholds
+2. Enable the job
+3. Schedule the job
+4. Restart the CA
+
+The job will be scheduled to use the PKI built-in cron-like timer. It is configured nearly identically to `crontab(5)`. On execution it will remove certificates and requests that fall outside the configured thresholds. LDAP search/time limits can be used to control how many are removed at once.
+
+In addition to the automated schedule it is possible to manually run the pruning job.
+
+The tool will not restart the CA. It will be left as an exercise for the user, who will be notified as needed.
+
+### Where to use
+
+The pruning configuration is not replicated. It should not be necessary to enable this task on all IPA servers, or more than one.
+
+Running the task simultaneously on multiple servers has a few downsides:
+
+* Additional stress on the LDAP server searching for expired certificates and requests
+* Unnecessary replication load deleting the same entries on multiple servers
+
+While enabling this on a single server represents a single-point-of-failure there should be no catastrophic consequences other than expired certificates and requests potentially building up. This can be cleared by enabling pruning on a different server. Depending on the size of the backlog this could take a couple of executions to catch up.
+
+## Design
+
+There are several operations, most of which act locally and one of which uses the PKI REST API.
+
+1. Updating the job configuration (enable, thresholds, etc). This will be done by running the `pki-server ca-config-set` command which modifies CS.cfg directly per the PKI wiki. A restart is required.
+
+2. Retrieving the current configuration for display. The `pki-server ca-config-find` command returns the entire configuration so the results will need to be filtered.
+
+3. Managing the job. This can be done using the REST API, https://github.com/dogtagpki/pki/wiki/PKI-REST-API . Operations include enabling the job and triggering it to run now.
+
+Theoretically for operations 1 and 2 we could use existing code to manually update `CS.cfg` and retrieve values. For future-proofing purposes calling `pki-server` is probably the better long-term option given the limited number of times this will be used. Configuration is likely to be one and done.
+
+There are four values each that can be managed for pruning certificates and requests:
+
+* expired cert/incomplete request time
+* time unit
+* LDAP search size limit
+* LDAP search time limit
+
+The first two configure when an expired certificate or incomplete request will be deleted. The unit can be one of: minute, hour, day, year. By default it is 30 days.
+
+The LDAP limits control how many entries are returned and how long the search can take. By default it is 1000 entries and unlimited time.
+
+### Configuration settings
+
+The configuration values will be set by running `pki-server ca-config-set` This will ensure best forward compatibility. The options are case-sensitive and not validated by the CA until restart. The values are not applied until the CA is restarted.
+
+### Configuring job execution time
+
+The CA provides a cron-like interface for scheduling jobs. To configure the job to run at midnight on the first of every month the PKI equivalent command-line is:
+
+```
+pki-server ca-config-set jobsScheduler.job.pruning.cron `"0 0 1 * *"`
+```
+
+This will be the default when pruning is enabled. A separate configuration option will be available for fine-tuning execution time.
+
+The format is defined https://access.redhat.com/documentation/en-us/red_hat_certificate_system/9/html/administration_guide/setting_up_specific_jobs#Frequency_Settings_for_Automated_Jobs
+
+### REST Authentication and Authorization
+
+The REST API for pruning is documented at https://github.com/dogtagpki/pki/wiki/PKI-Start-Job-REST-API
+
+A PKI job can define an owner that can manage the job over the REST API. We will automatically define the owner as `ipara` when pruning is enabled.
+
+Manually running the job will be done using the PKI REST API. Authentication to this API for our purposes is done at the `/ca/rest/account/login` endpoint. A cookie is returned which will be used in any subsequent calls. The IPA RA agent certificate will be used for authentication and authorization.
+
+### Commands
+
+This will be implemented in the ipa-acme-manage command. While strictly not completely ACME-related this is the primary driver for pruning.
+
+A new verb will be added, pruning, to be used for enabling and configuring pruning.
+
+### Enabling pruning
+
+`# ipa-acme-manage pruning --enable=TRUE`
+
+Enabling the job will call
+
+`# pki-server ca-config-set jobsScheduler.job.pruning.enabled true`
+
+This will also set jobsScheduler.job.pruning.cron to `"0 0 1 * *"` if it has not already been set.
+
+Additionally it will set the job owner to `ipara` with:
+
+`# pki-server ca-config-set jobsScheduler.job.pruning.owner ipara`
+
+Disabling the job will call
+
+`# pki-server ca-config-unset jobsScheduler.job.pruning.enabled`
+
+### Cron settings
+
+To modify the cron settings:
+
+`# ipa-acme-manage pruning --cron="Minute Hour Day_of_month Month_of_year Day_of_week"`
+
+Validation of the value will be:
+* each of the options is an integer
+* minute is within 0-59
+* hour is within 0-23
+* day of month is within 0-31
+* month of year is within 1-12
+* day of week is within 0-6
+
+No validation of setting February 31st will be done. That will be left to PKI. Buyer beware.
+
+### Disabling pruning
+
+`$ ipa-acme-manage pruning --enable=FALSE`
+
+This will remove the configuration option for `jobsScheduler.job.pruning.cron` just to be sure it no longer runs.
+
+### Configuration
+
+#### Pruning certificates
+
+`$ ipa-acme-manage pruning --certretention=VALUE --certretentionunit=UNIT`
+
+will be the equivalent of:
+
+`$ pki-server ca-config-set jobsScheduler.job.pruning.certRetentionTime 30`
+
+`$ pki-server ca-config-set jobsScheduler.job.pruning.certRetentionUnit day`
+
+The unit will always be required when modifying the time.
+
+`$ ipa-acme-manage pruning --certsearchsizelimit=VALUE --certsearchtimelimit=VALUE`
+
+will be the equivalent of:
+
+`$ pki-server ca-config-set jobsScheduler.job.pruning.certSearchSizeLimit 1000`
+
+`$ pki-server ca-config-set jobsScheduler.job.pruning.certSearchTimeLimit 0`
+
+A value of 0 for searchtimelimit is unlimited.
+
+#### Pruning requests
+
+`$ ipa-acme-manage pruning --requestretention=VALUE --requestretentionunit=UNIT`
+
+will be the equivalent of:
+
+`$ pki-server ca-config-set jobsScheduler.job.pruning.requestRetentionTime 30`
+
+`$ pki-server ca-config-set jobsScheduler.job.pruning.requestRetentionUnit day`
+
+The unit will always be required when modifying the time.
+
+`$ ipa-acme-manage pruning --requestsearchsizelimit=VALUE --requestsearchtimelimit=VALUE`
+
+
+will be the equivalent of:
+
+`$ pki-server ca-config-set jobsScheduler.job.pruning.requestSearchSizeLimit 1000`
+
+`$ pki-server ca-config-set jobsScheduler.job.pruning.requestSearchTimeLimit 0`
+
+A value of 0 for searchtimelimit is unlimited.
+
+These options set the client-side limits. The server imposes its own search size and look through limits. This can be tuned for the uid=pkidbuser,ou=people,o=ipaca user via https://access.redhat.com/documentation/en-us/red_hat_directory_server/11/html/administration_guide/ldapsearch-ex-complex-range
+
+### Showing the Configuration
+
+To display the current configuration run `pki-server ca-config-find` and filter the results to only those that contain `jobsScheduler.job.pruning`.
+
+Default values are not included so will need to be set by `ipa-acme-manage` before displaying.
+
+Output may look something like:
+
+```console
+# ipa-acme-manage pruning --config-show
+Enabled: TRUE
+Certificate retention time: 30 days
+Certificate search size limit: 1000
+Certificate search time limit: 0
+Request retention time: 30 days
+Request search size limit: 1000
+Request search time limit: 0
+Cron: 0 0 1 * *
+```
+
+## Implementation
+
+For online REST operations (login, run job) we will use the `ipaserver/plugins/dogtag.py::RestClient` class to manage the requests. This will take care of the authentication cookie, etc.
+
+The class uses dogtag.https_request() will can take PEM cert and key files as arguments. These will be used for authentication.
+
+For the non-REST operations (configuration, cron settings) the tool will fork out to pki-server ca-config-set.
+
+### UI
+
+This will only be configurable on the command-line.
+
+### CLI
+
+Overview of the CLI commands. Example:
+
+
+| Command | Options |
+| --- | ----- |
+| ipa-acme-manage pruning | --enable=TRUE |
+| ipa-acme-manage pruning | --enable=FALSE |
+| ipa-acme-manage pruning | --cron=`"0 0 1 * *"` |
+| ipa-acme-manage pruning | --certretention=30 --certretentionunit=day |
+| ipa-acme-manage pruning | --certsearchsizelimit=1000 --certsearchtimelimit=0 |
+| ipa-acme-manage pruning | --requestretention=30 --requestretentionunit=day |
+| ipa-acme-manage pruning | --requestsearchsizelimit=1000 --requestsearchtimelimit=0 |
+| ipa-acme-manage pruning | --config-show |
+
+ipa-acme-manage can only be run as root.
+
+### Configuration
+
+Configuration changes will be made to /etc/pki/pki-tomcat/ca/CS.cfg
+
+## Upgrade
+
+No expected impact on upgrades.
+
+## Test plan
+
+Testing will consist of:
+
+* Use the default configuration
+* enabling the pruning job
+* issue one or more certificates
+* move time forward +1 days after expiration
+* manually running the job
+* validating that the certificates are removed
+
+For size/time limit testing, create a large number of certificates/requests and set the search limit to a low value, then ensure that the number of deleted certs is equal to the search limit. Testing timelimit in this way may be less predictable as it may require a massive number of entries to find to timeout on a non-busy server.
+
+## Troubleshooting and debugging
+
+The PKI debug log will contain job information.
+
+```
+2022-12-08 21:14:25 [https-jsse-nio-8443-exec-8] INFO: JobService: Starting job pruning
+2022-12-08 21:14:25 [https-jsse-nio-8443-exec-8] INFO: JobService: - principal: null
+2022-12-08 21:14:51 [https-jsse-nio-8443-exec-10] INFO: JobService: Starting job pruning 2022-12-08 21:14:51 [https-jsse-nio-8443-exec-10] INFO: JobService: - principal: null
+2022-12-08 21:15:11 [https-jsse-nio-8443-exec-11] INFO: PKIRealm: Authenticating certificate chain:
+2022-12-08 21:15:11 [https-jsse-nio-8443-exec-11] INFO: PKIRealm: - CN=IPA RA,O=EXAMPLE.TEST
+2022-12-08 21:15:11 [https-jsse-nio-8443-exec-11] INFO: PKIRealm: - CN=Certificate Authority,O=EXAMPLE.TEST
+2022-12-08 21:15:11 [https-jsse-nio-8443-exec-11] INFO: LDAPSession: Retrieving cn=19072098145751813471503860299601579276,ou=certificateRepository, ou=ca,o=ipaca
+2022-12-08 21:15:11 [https-jsse-nio-8443-exec-11] INFO: CertUserDBAuthentication: UID ipara authenticated.
+2022-12-08 21:15:11 [https-jsse-nio-8443-exec-11] INFO: PKIRealm: User ipara authenticated
+2022-12-08 21:15:11 [https-jsse-nio-8443-exec-11] INFO: UGSubsystem: Retrieving user uid=ipara,ou=People,o=ipaca
+2022-12-08 21:15:11 [https-jsse-nio-8443-exec-11] INFO: PKIRealm: User DN: uid=ipara,ou=people,o=ipaca
+2022-12-08 21:15:11 [https-jsse-nio-8443-exec-11] INFO: PKIRealm: Roles:
+2022-12-08 21:15:11 [https-jsse-nio-8443-exec-11] INFO: PKIRealm: - Certificate Manager Agents
+2022-12-08 21:15:11 [https-jsse-nio-8443-exec-11] INFO: PKIRealm: - Registration Manager Agents
+2022-12-08 21:15:11 [https-jsse-nio-8443-exec-11] INFO: PKIRealm: - Security Domain Administrators
+2022-12-08 21:15:11 [https-jsse-nio-8443-exec-11] INFO: PKIRealm: - Enterprise ACME Administrators
+2022-12-08 21:15:24 [https-jsse-nio-8443-exec-12] INFO: JobService: Starting job pruning
+2022-12-08 21:15:24 [https-jsse-nio-8443-exec-12] INFO: JobService: - principal: GenericPrincipal[ipara(Certificate Manager Agents,Enterprise ACME Administrators,Registration Manager Agents,Security Domain Administrators,)]
+2022-12-08 21:15:24 [https-jsse-nio-8443-exec-12] INFO: JobsScheduler: Starting job pruning
+2022-12-08 21:15:24 [pruning] INFO: PruningJob: Running pruning job at Thu Dec 08 21:15:24 UTC 2022
+2022-12-08 21:15:24 [pruning] INFO: PruningJob: Pruning certs expired before Tue Nov 08 21:15:24 UTC 2022
+2022-12-08 21:15:24 [pruning] INFO: PruningJob: - filter: (&(x509Cert.notAfter<=1667942124527)(!(x509Cert.notAfter=1667942124527)))
+2022-12-08 21:15:24 [pruning] INFO: LDAPSession: Searching ou=certificateRepository, ou=ca,o=ipaca for (&(notAfter<=20221108211524Z)(!(notAfter=20221108211524Z)))
+2022-12-08 21:15:24 [pruning] INFO: PruningJob: Pruning incomplete requests last modified before Tue Nov 08 21:15:24 UTC 2022
+2022-12-08 21:15:24 [pruning] INFO: PruningJob: - filter: (&(!(requestState=complete))(requestModifyTime<=1667942124527)(!(requestModifyTime=1667942124527)))
+2022-12-08 21:15:24 [pruning] INFO: LDAPSession: Searching ou=ca, ou=requests,o=ipaca for (&(!(requestState=complete))(dateOfModify<=20221108211524Z)(!(dateOfModify=20221108211524Z)))
+```
diff --git a/doc/designs/index.rst b/doc/designs/index.rst
index 570e526fe35d510feeac62a44dd59224289e0506..1d41c0f84f0d7d3d5f184a47e31b4e71a890805d 100644
--- a/doc/designs/index.rst
+++ b/doc/designs/index.rst
@@ -14,6 +14,7 @@ FreeIPA design documentation
hsm.md
krb-ticket-policy.md
extdom-plugin-protocol.md
+ expired_certificate_pruning.md
expiring-password-notification.md
ldap_grace_period.md
ldap_pam_passthrough.md
--
2.39.1

View File

@ -0,0 +1,684 @@
From 9246a8a003b2b0062e07c289cd7cde8fe902b16f Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Thu, 12 Jan 2023 15:06:27 -0500
Subject: [PATCH] ipa-acme-manage: add certificate/request pruning management
Configures PKI to remove expired certificates and non-resolved
requests on a schedule.
This is geared towards ACME which can generate a lot of certificates
over a short period of time but is general purpose. It lives in
ipa-acme-manage because that is the primary reason for including it.
Random Serial Numbers v3 must be enabled for this to work.
Enabling pruning enables the job scheduler within CS and sets the
job user as the IPA RA user which has full rights to certificates
and requests.
Disabling pruning does not disable the job scheduler because the
tool is stateless. Having the scheduler enabled should not be a
problem.
A restart of PKI is required to apply any changes. This tool forks
out to pki-server which does direct writes to CS.cfg. It might
be easier to use our own tooling for this but this makes the
integration tighter so we pick up any improvements in PKI.
The "cron" setting is quite limited, taking only integer values
and *. It does not accept ranges, either - or /.
No error checking is done in PKI when setting a value, only when
attempting to use it, so some rudimentary validation is done.
Fixes: https://pagure.io/freeipa/issue/9294
Signed-off-by: Rob Crittenden rcritten@redhat.com
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
install/tools/man/ipa-acme-manage.1 | 83 +++++++
ipaserver/install/ipa_acme_manage.py | 303 ++++++++++++++++++++++++-
ipatests/test_integration/test_acme.py | 158 +++++++++++++
3 files changed, 534 insertions(+), 10 deletions(-)
diff --git a/install/tools/man/ipa-acme-manage.1 b/install/tools/man/ipa-acme-manage.1
index e15d25bd0017d8bd71e425fcb633827fa6f67693..e6cec4e4a7fd460c514a72456a2dc9a2e3682ebd 100644
--- a/install/tools/man/ipa-acme-manage.1
+++ b/install/tools/man/ipa-acme-manage.1
@@ -27,6 +27,89 @@ Disable the ACME service on this host.
.TP
\fBstatus\fR
Display the status of the ACME service.
+.TP
+\fBpruning\fR
+Configure certificate and request pruning.
+
+.SH "PRUNING"
+Pruning is a job that runs in the CA that can remove expired
+certificates and certificate requests which have not been issued.
+This is particularly important when using short-lived certificates
+like those issued with the ACME protocol. Pruning requires that
+the IPA server be installed with random serial numbers enabled.
+
+The CA needs to be restarted after modifying the pruning configuration.
+
+The job is a cron-like task within the CA that is controlled by a
+number of options which dictate how long after the certificate or
+request is considered no longer valid and removed from the LDAP
+database.
+
+The cron time and date fields are:
+.IP
+.ta 1.5i
+field allowed values
+.br
+----- --------------
+.br
+minute 0-59
+.br
+hour 0-23
+.br
+day of month 1-31
+.br
+month 1-12
+.br
+day of week 0-6 (0 is Sunday)
+.br
+.PP
+
+The cron syntax is limited to * or specific numbers. Ranges are not supported.
+
+.TP
+\fB\-\-enable\fR
+Enable certificate pruning.
+.TP
+\fB\-\-disable\fR
+Disable certificate pruning.
+.TP
+\fB\-\-cron=CRON\fR
+Configure the pruning cron job. The syntax is similar to crontab(5) syntax.
+For example, "0 0 1 * *" schedules the job to run at 12:00am on the first
+day of each month.
+.TP
+\fB\-\-certretention=CERTRETENTION\fR
+Certificate retention time. The default is 30.
+.TP
+\fB\-\-certretentionunit=CERTRETENTIONUNIT\fR
+Certificate retention units. Valid units are: minute, hour, day, year.
+The default is days.
+.TP
+\fB\-\-certsearchsizelimit=CERTSEARCHSIZELIMIT\fR
+LDAP search size limit searching for expired certificates. The default is 1000. This is a client-side limit. There may be additional server-side limitations.
+.TP
+\fB\-\-certsearchtimelimit=CERTSEARCHTIMELIMIT\fR
+LDAP search time limit searching for expired certificates. The default is 0, no limit. This is a client-side limit. There may be additional server-side limitations.
+.TP
+\fB\-\-requestretention=REQUESTRETENTION\fR
+Request retention time. The default is 30.
+.TP
+\fB\-\-requestretentionunit=REQUESTRETENTIONUNIT\fR
+Request retention units. Valid units are: minute, hour, day, year.
+The default is days.
+.TP
+\fB\-\-requestsearchsizelimit=REQUESTSEARCHSIZELIMIT\fR
+LDAP search size limit searching for unfulfilled requests. The default is 1000. There may be additional server-side limitations.
+.TP
+\fB\-\-requestsearchtimelimit=REQUESTSEARCHTIMELIMIT\fR
+LDAP search time limit searching for unfulfilled requests. The default is 0, no limit. There may be additional server-side limitations.
+.TP
+\fB\-\-config\-show\fR
+Show the current pruning configuration
+.TP
+\fB\-\-run\fR
+Run the pruning job now. The IPA RA certificate is used to authenticate to the PKI REST backend.
+
.SH "EXIT STATUS"
0 if the command was successful
diff --git a/ipaserver/install/ipa_acme_manage.py b/ipaserver/install/ipa_acme_manage.py
index 0474b9f4a051063ac6df41a81877a2af9d4a2096..b7b2111d9edcec2580aa4a485d7a7340146ff065 100644
--- a/ipaserver/install/ipa_acme_manage.py
+++ b/ipaserver/install/ipa_acme_manage.py
@@ -2,7 +2,12 @@
# Copyright (C) 2020 FreeIPA Contributors see COPYING for license
#
+
import enum
+import pki.util
+import logging
+
+from optparse import OptionGroup # pylint: disable=deprecated-module
from ipalib import api, errors, x509
from ipalib import _
@@ -10,10 +15,64 @@ from ipalib.facts import is_ipa_configured
from ipaplatform.paths import paths
from ipapython.admintool import AdminTool
from ipapython import cookie, dogtag
+from ipapython.ipautil import run
+from ipapython.certdb import NSSDatabase, EXTERNAL_CA_TRUST_FLAGS
from ipaserver.install import cainstance
+from ipaserver.install.ca import lookup_random_serial_number_version
from ipaserver.plugins.dogtag import RestClient
+logger = logging.getLogger(__name__)
+
+default_pruning_options = {
+ 'certRetentionTime': '30',
+ 'certRetentionUnit': 'day',
+ 'certSearchSizeLimit': '1000',
+ 'certSearchTimeLimit': '0',
+ 'requestRetentionTime': 'day',
+ 'requestRetentionUnit': '30',
+ 'requestSearchSizeLimit': '1000',
+ 'requestSearchTimeLimit': '0',
+ 'cron': ''
+}
+
+pruning_labels = {
+ 'certRetentionTime': 'Certificate Retention Time',
+ 'certRetentionUnit': 'Certificate Retention Unit',
+ 'certSearchSizeLimit': 'Certificate Search Size Limit',
+ 'certSearchTimeLimit': 'Certificate Search Time Limit',
+ 'requestRetentionTime': 'Request Retention Time',
+ 'requestRetentionUnit': 'Request Retention Unit',
+ 'requestSearchSizeLimit': 'Request Search Size Limit',
+ 'requestSearchTimeLimit': 'Request Search Time Limit',
+ 'cron': 'cron Schedule'
+}
+
+
+def validate_range(val, min, max):
+ """dogtag appears to have no error checking in the cron
+ entry so do some minimum amount of validation. It is
+ left as an exercise for the user to do month/day
+ validation so requesting Feb 31 will be accepted.
+
+ Only * and a number within a min/max range are allowed.
+ """
+ if val == '*':
+ return
+
+ if '-' in val or '/' in val:
+ raise ValueError(f"{val} ranges are not supported")
+
+ try:
+ int(val)
+ except ValueError:
+ # raise a clearer error
+ raise ValueError(f"{val} is not a valid integer")
+
+ if int(val) < min or int(val) > max:
+ raise ValueError(f"{val} not within the range {min}-{max}")
+
+
# Manages the FreeIPA ACME service on a per-server basis.
#
# This program is a stop-gap until the deployment-wide management of
@@ -66,32 +125,121 @@ class acme_state(RestClient):
status, unused, _unused = self._request('/acme/disable',
headers=headers)
if status != 200:
- raise RuntimeError('Failed to disble ACME')
+ raise RuntimeError('Failed to disable ACME')
class Command(enum.Enum):
ENABLE = 'enable'
DISABLE = 'disable'
STATUS = 'status'
+ PRUNE = 'pruning'
class IPAACMEManage(AdminTool):
command_name = "ipa-acme-manage"
- usage = "%prog [enable|disable|status]"
+ usage = "%prog [enable|disable|status|pruning]"
description = "Manage the IPA ACME service"
+ @classmethod
+ def add_options(cls, parser):
+
+ group = OptionGroup(parser, 'Pruning')
+ group.add_option(
+ "--enable", dest="enable", action="store_true",
+ default=False, help="Enable certificate pruning")
+ group.add_option(
+ "--disable", dest="disable", action="store_true",
+ default=False, help="Disable certificate pruning")
+ group.add_option(
+ "--cron", dest="cron", action="store",
+ default=None, help="Configure the pruning cron job")
+ group.add_option(
+ "--certretention", dest="certretention", action="store",
+ default=None, help="Certificate retention time", type=int)
+ group.add_option(
+ "--certretentionunit", dest="certretentionunit", action="store",
+ choices=['minute', 'hour', 'day', 'year'],
+ default=None, help="Certificate retention units")
+ group.add_option(
+ "--certsearchsizelimit", dest="certsearchsizelimit",
+ action="store",
+ default=None, help="LDAP search size limit", type=int)
+ group.add_option(
+ "--certsearchtimelimit", dest="certsearchtimelimit", action="store",
+ default=None, help="LDAP search time limit", type=int)
+ group.add_option(
+ "--requestretention", dest="requestretention", action="store",
+ default=None, help="Request retention time", type=int)
+ group.add_option(
+ "--requestretentionunit", dest="requestretentionunit",
+ choices=['minute', 'hour', 'day', 'year'],
+ action="store", default=None, help="Request retention units")
+ group.add_option(
+ "--requestsearchsizelimit", dest="requestsearchsizelimit",
+ action="store",
+ default=None, help="LDAP search size limit", type=int)
+ group.add_option(
+ "--requestsearchtimelimit", dest="requestsearchtimelimit",
+ action="store",
+ default=None, help="LDAP search time limit", type=int)
+ group.add_option(
+ "--config-show", dest="config_show", action="store_true",
+ default=False, help="Show the current pruning configuration")
+ group.add_option(
+ "--run", dest="run", action="store_true",
+ default=False, help="Run the pruning job now")
+ parser.add_option_group(group)
+ super(IPAACMEManage, cls).add_options(parser, debug_option=True)
+
+
def validate_options(self):
- # needs root now - if/when this program changes to an API
- # wrapper we will no longer need root.
super(IPAACMEManage, self).validate_options(needs_root=True)
if len(self.args) < 1:
self.option_parser.error(f'missing command argument')
- else:
- try:
- self.command = Command(self.args[0])
- except ValueError:
- self.option_parser.error(f'unknown command "{self.args[0]}"')
+
+ if self.args[0] == "pruning":
+ if self.options.enable and self.options.disable:
+ self.option_parser.error("Cannot both enable and disable")
+ elif (
+ any(
+ [
+ self.options.enable,
+ self.options.disable,
+ self.options.cron,
+ self.options.certretention,
+ self.options.certretentionunit,
+ self.options.requestretention,
+ self.options.requestretentionunit,
+ self.options.certsearchsizelimit,
+ self.options.certsearchtimelimit,
+ self.options.requestsearchsizelimit,
+ self.options.requestsearchtimelimit,
+ ]
+ )
+ and (self.options.config_show or self.options.run)
+ ):
+
+ self.option_parser.error(
+ "Cannot change and show config or run at the same time"
+ )
+ elif self.options.cron:
+ if len(self.options.cron.split()) != 5:
+ self.option_parser.error("Invalid format for --cron")
+ # dogtag does no validation when setting an option so
+ # do the minimum. The dogtag cron is limited compared to
+ # crontab(5).
+ opt = self.options.cron.split()
+ validate_range(opt[0], 0, 59)
+ validate_range(opt[1], 0, 23)
+ validate_range(opt[2], 1, 31)
+ validate_range(opt[3], 1, 12)
+ validate_range(opt[4], 0, 6)
+
+ try:
+ self.command = Command(self.args[0])
+ except ValueError:
+ self.option_parser.error(f'unknown command "{self.args[0]}"')
def check_san_status(self):
"""
@@ -100,6 +248,140 @@ class IPAACMEManage(AdminTool):
cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE)
cainstance.check_ipa_ca_san(cert)
+ def pruning(self):
+ def run_pki_server(command, directive, prefix, value=None):
+ """Take a set of arguments to append to pki-server"""
+ args = [
+ 'pki-server', command,
+ f'{prefix}.{directive}'
+ ]
+ if value:
+ args.extend([str(value)])
+ logger.debug(args)
+ result = run(args, raiseonerr=False, capture_output=True,
+ capture_error=True)
+ if result.returncode != 0:
+ raise RuntimeError(result.error_output)
+ return result
+
+ def ca_config_set(directive, value,
+ prefix='jobsScheduler.job.pruning'):
+ run_pki_server('ca-config-set', directive, prefix, value)
+ # ca-config-set always succeeds, even if the option is
+ # not supported.
+ newvalue = ca_config_show(directive)
+ if str(value) != newvalue.strip():
+ raise RuntimeError('Updating %s failed' % directive)
+
+ def ca_config_show(directive):
+ result = run_pki_server('ca-config-show', directive,
+ prefix='jobsScheduler.job.pruning')
+ return result.output.strip()
+
+ def config_show():
+ status = ca_config_show('enabled')
+ if status.strip() == 'true':
+ print("Status: enabled")
+ else:
+ print("Status: disabled")
+ for option in (
+ 'certRetentionTime', 'certRetentionUnit',
+ 'certSearchSizeLimit', 'certSearchTimeLimit',
+ 'requestRetentionTime', 'requestRetentionUnit',
+ 'requestSearchSizeLimit', 'requestSearchTimeLimit',
+ 'cron',
+ ):
+ value = ca_config_show(option)
+ if value:
+ print("{}: {}".format(pruning_labels[option], value))
+ else:
+ print("{}: {}".format(pruning_labels[option],
+ default_pruning_options[option]))
+
+ def run_pruning():
+ """Run the pruning job manually"""
+
+ with NSSDatabase() as tmpdb:
+ print("Preparing...")
+ tmpdb.create_db()
+ tmpdb.import_files((paths.RA_AGENT_PEM, paths.RA_AGENT_KEY),
+ import_keys=True)
+ tmpdb.import_files((paths.IPA_CA_CRT,))
+ for nickname, trust_flags in tmpdb.list_certs():
+ if trust_flags.has_key:
+ ra_nickname = nickname
+ continue
+ # external is suffucient for our purposes: C,,
+ tmpdb.trust_root_cert(nickname, EXTERNAL_CA_TRUST_FLAGS)
+ print("Starting job...")
+ args = ['pki', '-C', tmpdb.pwd_file, '-d', tmpdb.secdir,
+ '-n', ra_nickname,
+ 'ca-job-start', 'pruning']
+ logger.debug(args)
+ run(args, stdin='y')
+
+ pki_version = pki.util.Version(pki.specification_version())
+ if pki_version < pki.util.Version("11.3.0"):
+ raise RuntimeError(
+ 'Certificate pruning is not supported in PKI version %s'
+ % pki_version
+ )
+
+ if lookup_random_serial_number_version(api) == 0:
+ raise RuntimeError(
+ 'Certificate pruning requires random serial numbers'
+ )
+
+ if self.options.config_show:
+ config_show()
+ return
+
+ if self.options.run:
+ run_pruning()
+ return
+
+ # Don't play the enable/disable at the same time game
+ if self.options.enable:
+ ca_config_set('owner', 'ipara')
+ ca_config_set('enabled', 'true')
+ ca_config_set('enabled', 'true', 'jobsScheduler')
+ elif self.options.disable:
+ ca_config_set('enabled', 'false')
+
+ # pki-server ca-config-set can only set one option at a time so
+ # loop through all the options and set what is there.
+ if self.options.certretention:
+ ca_config_set('certRetentionTime',
+ self.options.certretention)
+ if self.options.certretentionunit:
+ ca_config_set('certRetentionUnit',
+ self.options.certretentionunit)
+ if self.options.certsearchtimelimit:
+ ca_config_set('certSearchTimeLimit',
+ self.options.certsearchtimelimit)
+ if self.options.certsearchsizelimit:
+ ca_config_set('certSearchSizeLimit',
+ self.options.certsearchsizelimit)
+ if self.options.requestretention:
+ ca_config_set('requestRetentionTime',
+ self.options.requestretention)
+ if self.options.requestretentionunit:
+ ca_config_set('requestRetentionUnit',
+ self.options.requestretentionunit)
+ if self.options.requestsearchsizelimit:
+ ca_config_set('requestSearchSizeLimit',
+ self.options.requestsearchsizelimit)
+ if self.options.requestsearchtimelimit:
+ ca_config_set('requestSearchTimeLimit',
+ self.options.requestsearchtimelimit)
+ if self.options.cron:
+ ca_config_set('cron', self.options.cron)
+
+ config_show()
+
+ print("The CA service must be restarted for changes to take effect")
+
+
def run(self):
if not is_ipa_configured():
print("IPA is not configured.")
@@ -123,7 +405,8 @@ class IPAACMEManage(AdminTool):
elif self.command == Command.STATUS:
status = "enabled" if dogtag.acme_status() else "disabled"
print("ACME is {}".format(status))
- return 0
+ elif self.command == Command.PRUNE:
+ self.pruning()
else:
raise RuntimeError('programmer error: unhandled enum case')
diff --git a/ipatests/test_integration/test_acme.py b/ipatests/test_integration/test_acme.py
index 15d7543cfb0fa0fcb921166f7cd8f13d0535a41d..93e785d8febd9fa8d7b3ef87ecb3f2eb42ac5da2 100644
--- a/ipatests/test_integration/test_acme.py
+++ b/ipatests/test_integration/test_acme.py
@@ -12,6 +12,9 @@ from ipalib.constants import IPA_CA_RECORD
from ipatests.test_integration.base import IntegrationTest
from ipatests.pytest_ipa.integration import tasks
from ipatests.test_integration.test_caless import CALessBase, ipa_certs_cleanup
+from ipatests.test_integration.test_random_serial_numbers import (
+ pki_supports_RSNv3
+)
from ipaplatform.osinfo import osinfo
from ipaplatform.paths import paths
from ipatests.test_integration.test_external_ca import (
@@ -388,6 +391,16 @@ class TestACME(CALessBase):
status = check_acme_status(self.replicas[0], 'disabled')
assert status == 'disabled'
+ def test_acme_pruning_no_random_serial(self):
+ """This ACME install is configured without random serial
+ numbers. Verify that we can't enable pruning on it."""
+ self.master.run_command(['ipa-acme-manage', 'enable'])
+ result = self.master.run_command(
+ ['ipa-acme-manage', 'pruning', '--enable'],
+ raiseonerr=False)
+ assert result.returncode == 1
+ assert "requires random serial numbers" in result.stderr_text
+
@server_install_teardown
def test_third_party_certs(self):
"""Require ipa-ca SAN on replacement web certificates"""
@@ -630,3 +643,148 @@ class TestACMERenew(IntegrationTest):
renewed_expiry = cert.not_valid_after
assert initial_expiry != renewed_expiry
+
+
+class TestACMEPrune(IntegrationTest):
+ """Validate that ipa-acme-manage configures dogtag for pruning"""
+
+ random_serial = True
+
+ @classmethod
+ def install(cls, mh):
+ if not pki_supports_RSNv3(mh.master):
+ raise pytest.skip("RNSv3 not supported")
+ tasks.install_master(cls.master, setup_dns=True,
+ random_serial=True)
+
+ @classmethod
+ def uninstall(cls, mh):
+ if not pki_supports_RSNv3(mh.master):
+ raise pytest.skip("RSNv3 not supported")
+ super(TestACMEPrune, cls).uninstall(mh)
+
+ def test_enable_pruning(self):
+ if (tasks.get_pki_version(self.master)
+ < tasks.parse_version('11.3.0')):
+ raise pytest.skip("Certificate pruning is not available")
+ cs_cfg = self.master.get_file_contents(paths.CA_CS_CFG_PATH)
+ assert "jobsScheduler.job.pruning.enabled=false".encode() in cs_cfg
+
+ self.master.run_command(['ipa-acme-manage', 'pruning', '--enable'])
+
+ cs_cfg = self.master.get_file_contents(paths.CA_CS_CFG_PATH)
+ assert "jobsScheduler.enabled=true".encode() in cs_cfg
+ assert "jobsScheduler.job.pruning.enabled=true".encode() in cs_cfg
+ assert "jobsScheduler.job.pruning.owner=ipara".encode() in cs_cfg
+
+ def test_pruning_options(self):
+ if (tasks.get_pki_version(self.master)
+ < tasks.parse_version('11.3.0')):
+ raise pytest.skip("Certificate pruning is not available")
+
+ self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ '--certretention=60',
+ '--certretentionunit=minute',
+ '--certsearchsizelimit=2000',
+ '--certsearchtimelimit=5',]
+ )
+ cs_cfg = self.master.get_file_contents(paths.CA_CS_CFG_PATH)
+ assert (
+ "jobsScheduler.job.pruning.certRetentionTime=60".encode()
+ in cs_cfg
+ )
+ assert (
+ "jobsScheduler.job.pruning.certRetentionUnit=minute".encode()
+ in cs_cfg
+ )
+ assert (
+ "jobsScheduler.job.pruning.certSearchSizeLimit=2000".encode()
+ in cs_cfg
+ )
+ assert (
+ "jobsScheduler.job.pruning.certSearchTimeLimit=5".encode()
+ in cs_cfg
+ )
+
+ self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ '--requestretention=60',
+ '--requestretentionunit=minute',
+ '--requestresearchsizelimit=2000',
+ '--requestsearchtimelimit=5',]
+ )
+ cs_cfg = self.master.get_file_contents(paths.CA_CS_CFG_PATH)
+ assert (
+ "jobsScheduler.job.pruning.requestRetentionTime=60".encode()
+ in cs_cfg
+ )
+ assert (
+ "jobsScheduler.job.pruning.requestRetentionUnit=minute".encode()
+ in cs_cfg
+ )
+ assert (
+ "jobsScheduler.job.pruning.requestSearchSizeLimit=2000".encode()
+ in cs_cfg
+ )
+ assert (
+ "jobsScheduler.job.pruning.requestSearchTimeLimit=5".encode()
+ in cs_cfg
+ )
+
+ self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ '--cron="0 23 1 * *',]
+ )
+ cs_cfg = self.master.get_file_contents(paths.CA_CS_CFG_PATH)
+ assert (
+ "jobsScheduler.job.pruning.cron=0 23 1 * *".encode()
+ in cs_cfg
+ )
+
+ def test_pruning_negative_options(self):
+ """Negative option testing for things we directly cover"""
+ if (tasks.get_pki_version(self.master)
+ < tasks.parse_version('11.3.0')):
+ raise pytest.skip("Certificate pruning is not available")
+
+ result = self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ '--enable', '--disable'],
+ raiseonerr=False
+ )
+ assert result.returncode == 1
+ assert "Cannot both enable and disable" in result.stderr_text
+
+ for cmd in ('--config-show', '--run'):
+ result = self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ cmd, '--enable'],
+ raiseonerr=False
+ )
+ assert result.returncode == 1
+ assert "Cannot change and show config" in result.stderr_text
+
+ result = self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ '--cron="* *"'],
+ raiseonerr=False
+ )
+ assert result.returncode == 1
+ assert "Invalid format format --cron" in result.stderr_text
+
+ result = self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ '--cron="100 * * * *"'],
+ raiseonerr=False
+ )
+ assert result.returncode == 1
+ assert "100 not within the range 0-59" in result.stderr_text
+
+ result = self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ '--cron="10 1-5 * * *"'],
+ raiseonerr=False
+ )
+ assert result.returncode == 1
+ assert "1-5 ranges are not supported" in result.stderr_text
--
2.39.1

View File

@ -1,144 +0,0 @@
From a39af6b7228d8ba85b9e97aa5decbc056d081c77 Mon Sep 17 00:00:00 2001
From: Sudhir Menon <sumenon@redhat.com>
Date: Thu, 23 Jun 2022 16:14:39 +0530
Subject: [PATCH] ipatests: ipa-client-install --subid adds entry in
nsswitch.conf
This testcase checks that when ipa-client-install command
is run with --subid option, /etc/nsswitch.conf file is updated
with the below entry
subid: nss
Related: https://pagure.io/freeipa/issue/9159
Since the newly added testsuite required client
system, hence modified the below yaml files to change the topology
from *master_1repl to *master_1repl_1client in the below files
gating.yaml
nightly_latest.yaml
nightly_rawhide.yaml
Signed-off-by: Sudhir Menon <sumenon@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Michal Polovka <mpolovka@redhat.com>
Reviewed-By: Stanislav Levin <slev@altlinux.org>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
Signed-off-by: Sudhir Menon <sumenon@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Michal Polovka <mpolovka@redhat.com>
Reviewed-By: Stanislav Levin <slev@altlinux.org>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
---
ipatests/prci_definitions/gating.yaml | 2 +-
.../nightly_ipa-4-10_latest.yaml | 2 +-
.../nightly_ipa-4-10_latest_selinux.yaml | 2 +-
.../nightly_ipa-4-10_previous.yaml | 2 +-
ipatests/test_integration/test_subids.py | 38 +++++++++++++++++++
5 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/ipatests/prci_definitions/gating.yaml b/ipatests/prci_definitions/gating.yaml
index 4083c650a17ce76bdefa243f1a7c5924039ff0bb..db4875dcfae8676287ef771805b34d988330bb40 100644
--- a/ipatests/prci_definitions/gating.yaml
+++ b/ipatests/prci_definitions/gating.yaml
@@ -309,4 +309,4 @@ jobs:
test_suite: test_integration/test_subids.py
template: *ci-ipa-4-10-latest
timeout: 3600
- topology: *master_1repl
+ topology: *master_1repl_1client
diff --git a/ipatests/prci_definitions/nightly_ipa-4-10_latest.yaml b/ipatests/prci_definitions/nightly_ipa-4-10_latest.yaml
index 24aa6e7cf29e448ba9d838d1cb98169213ea63ef..027b2a5b6c0b7ec3c3b5784ec4569661a06d4ed7 100644
--- a/ipatests/prci_definitions/nightly_ipa-4-10_latest.yaml
+++ b/ipatests/prci_definitions/nightly_ipa-4-10_latest.yaml
@@ -1748,7 +1748,7 @@ jobs:
test_suite: test_integration/test_subids.py
template: *ci-ipa-4-10-latest
timeout: 3600
- topology: *master_1repl
+ topology: *master_1repl_1client
fedora-latest-ipa-4-10/test_custom_plugins:
requires: [fedora-latest-ipa-4-10/build]
diff --git a/ipatests/prci_definitions/nightly_ipa-4-10_latest_selinux.yaml b/ipatests/prci_definitions/nightly_ipa-4-10_latest_selinux.yaml
index f22cc08384b3d50e49278d38e73bf93cd7804e80..bcc17bef935666735bfb2c2e51209362a374b511 100644
--- a/ipatests/prci_definitions/nightly_ipa-4-10_latest_selinux.yaml
+++ b/ipatests/prci_definitions/nightly_ipa-4-10_latest_selinux.yaml
@@ -1887,7 +1887,7 @@ jobs:
test_suite: test_integration/test_subids.py
template: *ci-ipa-4-10-latest
timeout: 3600
- topology: *master_1repl
+ topology: *master_1repl_1client
fedora-latest-ipa-4-10/test_custom_plugins:
requires: [fedora-latest-ipa-4-10/build]
diff --git a/ipatests/prci_definitions/nightly_ipa-4-10_previous.yaml b/ipatests/prci_definitions/nightly_ipa-4-10_previous.yaml
index df98a66871fd90daaebd83f063e48f1580675049..37d38762e696a6394ef146a0e2b68bbc8ced515d 100644
--- a/ipatests/prci_definitions/nightly_ipa-4-10_previous.yaml
+++ b/ipatests/prci_definitions/nightly_ipa-4-10_previous.yaml
@@ -1748,7 +1748,7 @@ jobs:
test_suite: test_integration/test_subids.py
template: *ci-ipa-4-10-previous
timeout: 3600
- topology: *master_1repl
+ topology: *master_1repl_1client
fedora-previous-ipa-4-10/test_custom_plugins:
requires: [fedora-previous-ipa-4-10/build]
diff --git a/ipatests/test_integration/test_subids.py b/ipatests/test_integration/test_subids.py
index f6d8607f237bf03358baae008dd2a6ad819751c0..8158499e1a2b71bdc1a308dec0939fd0d491599d 100644
--- a/ipatests/test_integration/test_subids.py
+++ b/ipatests/test_integration/test_subids.py
@@ -17,6 +17,7 @@ from ipatests.test_integration.base import IntegrationTest
class TestSubordinateId(IntegrationTest):
num_replicas = 0
+ num_clients = 1
topology = "star"
def _parse_result(self, result):
@@ -268,3 +269,40 @@ class TestSubordinateId(IntegrationTest):
f"--subuid={subuid}"])
owner = self._parse_result(result)["owner"]
assert owner == uid
+
+ def test_nsswitch_doesnot_contain_subid_entry(self):
+ """
+ This testcase checks that when ipa-client-install
+ is installed without subid option, the nsswitch.conf
+ does not contain subid entry or does not use sss as
+ source for subid
+ """
+ cmd = self.clients[0].run_command(
+ ["grep", "^subid", "/etc/nsswitch.conf"],
+ raiseonerr=False
+ )
+ # a source is defined for the subid database.
+ # Ensure it is not "sss"
+ if cmd.returncode == 0:
+ assert 'sss' not in cmd.stdout_text
+ else:
+ # grep command returncode 1 means no matching line
+ # was found = no source is defined for the subid database,
+ # which is valid other return codes would
+ # mean an error occurred
+ assert cmd.returncode == 1
+
+ def test_nsswitch_is_updated_with_subid_entry(self):
+ """
+ This test case checks that when ipa-client-install
+ is installed with --subid option, the nsswitch.conf
+ file is modified with the entry 'subid: sss'
+ """
+ tasks.uninstall_client(self.clients[0])
+ tasks.install_client(self.master, self.clients[0],
+ extra_args=['--subid'])
+ cmd = self.clients[0].run_command(
+ ["grep", "^subid", "/etc/nsswitch.conf"]
+ )
+ subid = cmd.stdout_text.split()
+ assert ['subid:', 'sss'] == subid
--
2.37.2

View File

@ -0,0 +1,138 @@
From f10d1a0f84ed0f16ab4a1469f16ffadb3e79e59e Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Fri, 27 Jan 2023 14:05:37 -0500
Subject: [PATCH] doc: add the --run command for manual job execution
A manual method was mentioned with no specificity. Include
the --run command. Also update the troubleshooting section
to show what failure to restart the CA after configuration
looks like.
Import the IPA CA chain for manual execution.
Also fix up some $ -> # to indicate root is needed.
Related: https://pagure.io/freeipa/issue/9294
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
doc/designs/expired_certificate_pruning.md | 46 +++++++++++++++-------
1 file changed, 32 insertions(+), 14 deletions(-)
diff --git a/doc/designs/expired_certificate_pruning.md b/doc/designs/expired_certificate_pruning.md
index 2c10d914020d3c12b6abb028323cd6796ec33e00..a23e452696ba2a150c4ad5a3e57360ae0a16a338 100644
--- a/doc/designs/expired_certificate_pruning.md
+++ b/doc/designs/expired_certificate_pruning.md
@@ -139,7 +139,7 @@ No validation of setting February 31st will be done. That will be left to PKI. B
### Disabling pruning
-`$ ipa-acme-manage pruning --enable=FALSE`
+`# ipa-acme-manage pruning --enable=FALSE`
This will remove the configuration option for `jobsScheduler.job.pruning.cron` just to be sure it no longer runs.
@@ -147,46 +147,46 @@ This will remove the configuration option for `jobsScheduler.job.pruning.cron` j
#### Pruning certificates
-`$ ipa-acme-manage pruning --certretention=VALUE --certretentionunit=UNIT`
+`# ipa-acme-manage pruning --certretention=VALUE --certretentionunit=UNIT`
will be the equivalent of:
-`$ pki-server ca-config-set jobsScheduler.job.pruning.certRetentionTime 30`
+`# pki-server ca-config-set jobsScheduler.job.pruning.certRetentionTime 30`
-`$ pki-server ca-config-set jobsScheduler.job.pruning.certRetentionUnit day`
+`# pki-server ca-config-set jobsScheduler.job.pruning.certRetentionUnit day`
The unit will always be required when modifying the time.
-`$ ipa-acme-manage pruning --certsearchsizelimit=VALUE --certsearchtimelimit=VALUE`
+`# ipa-acme-manage pruning --certsearchsizelimit=VALUE --certsearchtimelimit=VALUE`
will be the equivalent of:
-`$ pki-server ca-config-set jobsScheduler.job.pruning.certSearchSizeLimit 1000`
+`# pki-server ca-config-set jobsScheduler.job.pruning.certSearchSizeLimit 1000`
-`$ pki-server ca-config-set jobsScheduler.job.pruning.certSearchTimeLimit 0`
+`# pki-server ca-config-set jobsScheduler.job.pruning.certSearchTimeLimit 0`
A value of 0 for searchtimelimit is unlimited.
#### Pruning requests
-`$ ipa-acme-manage pruning --requestretention=VALUE --requestretentionunit=UNIT`
+`# ipa-acme-manage pruning --requestretention=VALUE --requestretentionunit=UNIT`
will be the equivalent of:
-`$ pki-server ca-config-set jobsScheduler.job.pruning.requestRetentionTime 30`
+`# pki-server ca-config-set jobsScheduler.job.pruning.requestRetentionTime 30`
-`$ pki-server ca-config-set jobsScheduler.job.pruning.requestRetentionUnit day`
+`# pki-server ca-config-set jobsScheduler.job.pruning.requestRetentionUnit day`
The unit will always be required when modifying the time.
-`$ ipa-acme-manage pruning --requestsearchsizelimit=VALUE --requestsearchtimelimit=VALUE`
+`# ipa-acme-manage pruning --requestsearchsizelimit=VALUE --requestsearchtimelimit=VALUE`
will be the equivalent of:
-`$ pki-server ca-config-set jobsScheduler.job.pruning.requestSearchSizeLimit 1000`
+`# pki-server ca-config-set jobsScheduler.job.pruning.requestSearchSizeLimit 1000`
-`$ pki-server ca-config-set jobsScheduler.job.pruning.requestSearchTimeLimit 0`
+`# pki-server ca-config-set jobsScheduler.job.pruning.requestSearchTimeLimit 0`
A value of 0 for searchtimelimit is unlimited.
@@ -212,10 +212,15 @@ Request search time limit: 0
Cron: 0 0 1 * *
```
+### Manual pruning
+
+`# ipa-acme-manage pruning --run`
+
+This is useful for testing the configuration or if the user wants to use the system cron or systemd timers for handling automation.
+
## Implementation
For online REST operations (login, run job) we will use the `ipaserver/plugins/dogtag.py::RestClient` class to manage the requests. This will take care of the authentication cookie, etc.
-
The class uses dogtag.https_request() will can take PEM cert and key files as arguments. These will be used for authentication.
For the non-REST operations (configuration, cron settings) the tool will fork out to pki-server ca-config-set.
@@ -239,6 +244,7 @@ Overview of the CLI commands. Example:
| ipa-acme-manage pruning | --requestretention=30 --requestretentionunit=day |
| ipa-acme-manage pruning | --requestsearchsizelimit=1000 --requestsearchtimelimit=0 |
| ipa-acme-manage pruning | --config-show |
+| ipa-acme-manage pruning | --run |
ipa-acme-manage can only be run as root.
@@ -295,3 +301,15 @@ The PKI debug log will contain job information.
2022-12-08 21:15:24 [pruning] INFO: PruningJob: - filter: (&(!(requestState=complete))(requestModifyTime<=1667942124527)(!(requestModifyTime=1667942124527)))
2022-12-08 21:15:24 [pruning] INFO: LDAPSession: Searching ou=ca, ou=requests,o=ipaca for (&(!(requestState=complete))(dateOfModify<=20221108211524Z)(!(dateOfModify=20221108211524Z)))
```
+
+### Manual execution fails with Forbidden
+
+If manually running pruning fails with a message like:
+
+```console
+# ipa-acme-manage pruning --run
+CalledProcessError(Command ['pki', '-C', '/tmp/tmppyyd3hfq/pwdfile.txt', '-d', '/tmp/tmppyyd3hfq', '-n', 'CN=IPA RA,O=EXAMPLE.TEST', 'ca-job-start', 'pruning'] returned non-zero exit status 255: 'PKIException: Forbidden\n')
+The ipa-acme-manage command failed.
+```
+
+You probably forgot to restart the CA after enabling pruning.
--
2.39.1

View File

@ -1,56 +0,0 @@
From 7a1e1d9f1cb13679c28f12d05b156a08bcc4d856 Mon Sep 17 00:00:00 2001
From: Carla Martinez <carlmart@redhat.com>
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 <carlmart@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
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 fa2028a52b1118b6125f91153280da0a2ffe0584..7ec103636ced0cce34997d81a02b25ba73bda33f 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 a580db03599457eefd85f8c23d74c284946393c7..b47c97f72008f2f4e75b4cb88e9ff6756827b26e 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

View File

@ -1,226 +0,0 @@
From bfe074ed478c20a9537dc2a714bba50dbc2cd34f Mon Sep 17 00:00:00 2001
From: Sumedh Sidhaye <ssidhaye@redhat.com>
Date: Fri, 5 Aug 2022 11:22:59 +0530
Subject: [PATCH] Additional tests for RSN v3
New Tests include
TestRSNPKIConfig
TestRSNVault
The new tests are just extending existing classes to be run
with random serial numbers enabled
The tests also include a new method to check params set in CS.cfg for both CA and
KRA, and another test to check Random Serial Number version while
running `ipa ca-find`
Added nightly definitions
Related Ticket: https://pagure.io/freeipa/issue/2016
Signed-off-by: Sumedh Sidhaye <ssidhaye@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
---
.../nightly_ipa-4-10_latest.yaml | 24 +++++++++
.../nightly_ipa-4-10_latest_selinux.yaml | 26 ++++++++++
.../nightly_ipa-4-10_previous.yaml | 24 +++++++++
.../test_random_serial_numbers.py | 51 ++++++++++++++++++-
ipatests/test_integration/test_vault.py | 4 +-
5 files changed, 127 insertions(+), 2 deletions(-)
diff --git a/ipatests/prci_definitions/nightly_ipa-4-10_latest.yaml b/ipatests/prci_definitions/nightly_ipa-4-10_latest.yaml
index 027b2a5b6c0b7ec3c3b5784ec4569661a06d4ed7..547320d258f51132266b56e9193533d2291c623c 100644
--- a/ipatests/prci_definitions/nightly_ipa-4-10_latest.yaml
+++ b/ipatests/prci_definitions/nightly_ipa-4-10_latest.yaml
@@ -1821,3 +1821,27 @@ jobs:
template: *ci-ipa-4-10-latest
timeout: 5400
topology: *master_1repl
+
+ fedora-latest-ipa-4-10/test_random_serial_numbers_TestRSNPKIConfig:
+ requires: [fedora-latest-ipa-4-10/build]
+ priority: 50
+ job:
+ class: RunPytest
+ args:
+ build_url: '{fedora-latest-ipa-4-10/build_url}'
+ test_suite: test_integration/test_random_serial_numbers.py::TestRSNPKIConfig
+ template: *ci-ipa-4-10-latest
+ timeout: 10800
+ topology: *master_3repl_1client
+
+ fedora-latest-ipa-4-10/test_random_serial_numbers_TestRSNVault:
+ requires: [fedora-latest-ipa-4-10/build]
+ priority: 50
+ job:
+ class: RunPytest
+ args:
+ build_url: '{fedora-latest-ipa-4-10/build_url}'
+ test_suite: test_integration/test_random_serial_numbers.py::TestRSNVault
+ template: *ci-ipa-4-10-latest
+ timeout: 10800
+ topology: *master_1repl
\ No newline at end of file
diff --git a/ipatests/prci_definitions/nightly_ipa-4-10_latest_selinux.yaml b/ipatests/prci_definitions/nightly_ipa-4-10_latest_selinux.yaml
index bcc17bef935666735bfb2c2e51209362a374b511..f6e5f1cff22de9db4df4577d1cd615499cf0fab3 100644
--- a/ipatests/prci_definitions/nightly_ipa-4-10_latest_selinux.yaml
+++ b/ipatests/prci_definitions/nightly_ipa-4-10_latest_selinux.yaml
@@ -1966,3 +1966,29 @@ jobs:
template: *ci-ipa-4-10-latest
timeout: 5400
topology: *master_1repl
+
+ fedora-latest-ipa-4-10/test_random_serial_numbers_TestRSNPKIConfig:
+ requires: [fedora-latest-ipa-4-10/build]
+ priority: 50
+ job:
+ class: RunPytest
+ args:
+ build_url: '{fedora-latest-ipa-4-10/build_url}'
+ selinux_enforcing: True
+ test_suite: test_integration/test_random_serial_numbers.py::TestRSNPKIConfig
+ template: *ci-ipa-4-10-latest
+ timeout: 10800
+ topology: *master_3repl_1client
+
+ fedora-latest-ipa-4-10/test_random_serial_numbers_TestRSNVault:
+ requires: [fedora-latest-ipa-4-10/build]
+ priority: 50
+ job:
+ class: RunPytest
+ args:
+ build_url: '{fedora-latest-ipa-4-10/build_url}'
+ selinux_enforcing: True
+ test_suite: test_integration/test_random_serial_numbers.py::TestRSNVault
+ template: *ci-ipa-4-10-latest
+ timeout: 10800
+ topology: *master_1repl
diff --git a/ipatests/prci_definitions/nightly_ipa-4-10_previous.yaml b/ipatests/prci_definitions/nightly_ipa-4-10_previous.yaml
index 37d38762e696a6394ef146a0e2b68bbc8ced515d..463f4b92fecc7fbc0be969de422352fb7baeb797 100644
--- a/ipatests/prci_definitions/nightly_ipa-4-10_previous.yaml
+++ b/ipatests/prci_definitions/nightly_ipa-4-10_previous.yaml
@@ -1821,3 +1821,27 @@ jobs:
template: *ci-ipa-4-10-previous
timeout: 5400
topology: *master_1repl
+
+ fedora-previous-ipa-4-10/test_random_serial_numbers_TestRSNPKIConfig:
+ requires: [fedora-previous-ipa-4-10/build]
+ priority: 50
+ job:
+ class: RunPytest
+ args:
+ build_url: '{fedora-previous-ipa-4-10/build_url}'
+ test_suite: test_integration/test_random_serial_numbers.py::TestRSNPKIConfig
+ template: *ci-ipa-4-10-previous
+ timeout: 10800
+ topology: *master_3repl_1client
+
+ fedora-previous-ipa-4-10/test_random_serial_numbers_TestRSNVault:
+ requires: [fedora-previous-ipa-4-10/build]
+ priority: 50
+ job:
+ class: RunPytest
+ args:
+ build_url: '{fedora-previous-ipa-4-10/build_url}'
+ test_suite: test_integration/test_random_serial_numbers.py::TestRSNVault
+ template: *ci-ipa-4-10-previous
+ timeout: 10800
+ topology: *master_1repl
diff --git a/ipatests/test_integration/test_random_serial_numbers.py b/ipatests/test_integration/test_random_serial_numbers.py
index c52cfa4ed50e2718791b0844d743fb240d26b365..ab58b1c622b010994ed93a17dd80cfd02095508d 100644
--- a/ipatests/test_integration/test_random_serial_numbers.py
+++ b/ipatests/test_integration/test_random_serial_numbers.py
@@ -4,12 +4,15 @@
import pytest
+from ipaplatform.paths import paths
+
+from ipatests.pytest_ipa.integration import tasks
from ipatests.test_integration.test_installation import (
TestInstallWithCA_DNS1,
TestInstallWithCA_KRA1,
)
from ipatests.test_integration.test_caless import TestServerCALessToExternalCA
-
+from ipatests.test_integration.test_vault import TestInstallKRA
from ipatests.test_integration.test_commands import TestIPACommand
@@ -26,6 +29,18 @@ def pki_supports_RSNv3(host):
return False
+def check_pki_config_params(host):
+ # Check CS.cfg
+ try:
+ cs_cfg = host.get_file_contents(paths.CA_CS_CFG_PATH)
+ kra_cfg = host.get_file_contents(paths.KRA_CS_CFG_PATH)
+ assert "dbs.cert.id.generator=random".encode() in cs_cfg
+ assert "dbs.request.id.generator=random".encode() in cs_cfg
+ assert "dbs.key.id.generator=random".encode() in kra_cfg
+ except IOError:
+ pytest.skip("PKI config not present.Skipping test")
+
+
class TestInstallWithCA_DNS1_RSN(TestInstallWithCA_DNS1):
random_serial = True
@@ -70,3 +85,37 @@ class TestServerCALessToExternalCA_RSN(TestServerCALessToExternalCA):
if not pki_supports_RSNv3(mh.master):
raise pytest.skip("RSNv3 not supported")
super(TestServerCALessToExternalCA_RSN, cls).uninstall(mh)
+
+
+class TestRSNPKIConfig(TestInstallWithCA_KRA1):
+ random_serial = True
+ num_replicas = 3
+
+ @classmethod
+ def install(cls, mh):
+ if not pki_supports_RSNv3(mh.master):
+ raise pytest.skip("RSNv3 not supported")
+ super(TestRSNPKIConfig, cls).install(mh)
+
+ def test_check_pki_config(self):
+ check_pki_config_params(self.master)
+ check_pki_config_params(self.replicas[0])
+ check_pki_config_params(self.replicas[1])
+
+ def test_check_rsn_version(self):
+ tasks.kinit_admin(self.master)
+ res = self.master.run_command(['ipa', 'ca-find'])
+ assert 'RSN Version: 3' in res.stdout_text
+ tasks.kinit_admin(self.replicas[0])
+ res = self.replicas[0].run_command(['ipa', 'ca-find'])
+ assert 'RSN Version: 3' in res.stdout_text
+
+
+class TestRSNVault(TestInstallKRA):
+ random_serial = True
+
+ @classmethod
+ def install(cls, mh):
+ if not pki_supports_RSNv3(mh.master):
+ raise pytest.skip("RSNv3 not supported")
+ super(TestRSNVault, cls).install(mh)
diff --git a/ipatests/test_integration/test_vault.py b/ipatests/test_integration/test_vault.py
index 548822d049070d6f9d42da772264eb24010fafda..6288e557f96cae60d031b44c49fbe830712eb7be 100644
--- a/ipatests/test_integration/test_vault.py
+++ b/ipatests/test_integration/test_vault.py
@@ -33,7 +33,9 @@ class TestInstallKRA(IntegrationTest):
@classmethod
def install(cls, mh):
- tasks.install_master(cls.master, setup_kra=True)
+ tasks.install_master(cls.master,
+ setup_kra=True,
+ random_serial=cls.random_serial)
# do not install KRA on replica, it is part of test
tasks.install_replica(cls.master, cls.replicas[0], setup_kra=False)
--
2.37.2

View File

@ -0,0 +1,43 @@
From d24b69981d94fce7b1e1aa4a5c1ab88a123f96b5 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Fri, 3 Feb 2023 10:04:31 -0500
Subject: [PATCH] tests: add wrapper around ACME RSNv3 test
This test is located outside of the TestACMEPrune because
it enables RSNv3 while the server installed by TestACME doesn't.
It still needs a wrapper to enforce a version of PKI that
supports pruning because that is checked first in the tool.
Re-ordering that wouldn't be a good user experience.
https://pagure.io/freeipa/issue/9322
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
ipatests/test_integration/test_acme.py | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/ipatests/test_integration/test_acme.py b/ipatests/test_integration/test_acme.py
index 93e785d8febd9fa8d7b3ef87ecb3f2eb42ac5da2..5ceba05976059de69414a79634d98045c3ab68bb 100644
--- a/ipatests/test_integration/test_acme.py
+++ b/ipatests/test_integration/test_acme.py
@@ -393,7 +393,14 @@ class TestACME(CALessBase):
def test_acme_pruning_no_random_serial(self):
"""This ACME install is configured without random serial
- numbers. Verify that we can't enable pruning on it."""
+ numbers. Verify that we can't enable pruning on it.
+
+ This test is located here because by default installs
+ don't enable RSNv3.
+ """
+ if (tasks.get_pki_version(self.master)
+ < tasks.parse_version('11.3.0')):
+ raise pytest.skip("Certificate pruning is not available")
self.master.run_command(['ipa-acme-manage', 'enable'])
result = self.master.run_command(
['ipa-acme-manage', 'pruning', '--enable'],
--
2.39.1

View File

@ -0,0 +1,68 @@
From 2857bc69957bde7e59fff1c66c5a83c7f560616b Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Tue, 31 Jan 2023 15:53:08 +0100
Subject: [PATCH] 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 <flo@redhat.com>
Reviewed-By: Francisco Trivino <ftrivino@redhat.com>
---
install/ui/test/data/i18n_messages.json | 2 +-
ipaclient/plugins/automember.py | 8 ++++++++
ipaserver/plugins/internal.py | 6 +++++-
3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/install/ui/test/data/i18n_messages.json b/install/ui/test/data/i18n_messages.json
index 49d288326d8cea192a16e93a274599805b0ea666..5b735487bf33805e8f0534d378d1497f05a11be8 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 df4a2e5a01744e0ff22c74180e13c2e7dc33fbaa..7108dc948753b9f6a4439842bd75e7c5e064bda6 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 5ffa7a281548a0658386f8740dbddd96fd0bc7d6..e1e920f8bb49dd8ba8f30b727111bb1316f6a918 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}?"),
--
2.39.1

View File

@ -1,35 +0,0 @@
From 2003eb6b3d4a27a5de5eaa79418f115dd99886cd Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
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 <flo@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
---
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 16be3760cb14bfeb1cc9a761400752071639dc7c..9d9aa1c4bfc99109c0cf1e6d1619ec1b38e20c02 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

View File

@ -0,0 +1,158 @@
From 20ff7c16022793c707f6c2b8fb38a801870bc0e2 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Wed, 8 Feb 2023 10:42:58 -0500
Subject: [PATCH] Fix setting values of 0 in ACME pruning
Replace comparisons of "if value" with "if value is not None"
in order to handle 0.
Add a short reference to the man page to indicat that a cert
or request retention time of 0 means remove at the next
execution.
Also indicate that the search time limit is in seconds.
Fixes: https://pagure.io/freeipa/issue/9325
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Francisco Trivino <ftrivino@redhat.com>
---
doc/designs/expired_certificate_pruning.md | 4 ++--
install/tools/man/ipa-acme-manage.1 | 8 +++----
ipaserver/install/ipa_acme_manage.py | 28 +++++++++++-----------
3 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/doc/designs/expired_certificate_pruning.md b/doc/designs/expired_certificate_pruning.md
index a23e452696ba2a150c4ad5a3e57360ae0a16a338..35ead7b00145b5df44caf542cba277f0e6e08b6a 100644
--- a/doc/designs/expired_certificate_pruning.md
+++ b/doc/designs/expired_certificate_pruning.md
@@ -67,11 +67,11 @@ There are four values each that can be managed for pruning certificates and requ
* expired cert/incomplete request time
* time unit
* LDAP search size limit
-* LDAP search time limit
+* LDAP search time limit (in seconds)
The first two configure when an expired certificate or incomplete request will be deleted. The unit can be one of: minute, hour, day, year. By default it is 30 days.
-The LDAP limits control how many entries are returned and how long the search can take. By default it is 1000 entries and unlimited time.
+The LDAP limits control how many entries are returned and how long the search can take. By default it is 1000 entries and unlimited time (0 == unlimited, unit is seconds).
### Configuration settings
diff --git a/install/tools/man/ipa-acme-manage.1 b/install/tools/man/ipa-acme-manage.1
index e6cec4e4a7fd460c514a72456a2dc9a2e3682ebd..b8383c14f482698d2bcc8b08f0c0bf5882c3c298 100644
--- a/install/tools/man/ipa-acme-manage.1
+++ b/install/tools/man/ipa-acme-manage.1
@@ -79,7 +79,7 @@ For example, "0 0 1 * *" schedules the job to run at 12:00am on the first
day of each month.
.TP
\fB\-\-certretention=CERTRETENTION\fR
-Certificate retention time. The default is 30.
+Certificate retention time. The default is 30. A value of 0 will remove expired certificates with no delay.
.TP
\fB\-\-certretentionunit=CERTRETENTIONUNIT\fR
Certificate retention units. Valid units are: minute, hour, day, year.
@@ -89,10 +89,10 @@ The default is days.
LDAP search size limit searching for expired certificates. The default is 1000. This is a client-side limit. There may be additional server-side limitations.
.TP
\fB\-\-certsearchtimelimit=CERTSEARCHTIMELIMIT\fR
-LDAP search time limit searching for expired certificates. The default is 0, no limit. This is a client-side limit. There may be additional server-side limitations.
+LDAP search time limit (seconds) searching for expired certificates. The default is 0, no limit. This is a client-side limit. There may be additional server-side limitations.
.TP
\fB\-\-requestretention=REQUESTRETENTION\fR
-Request retention time. The default is 30.
+Request retention time. The default is 30. A value of 0 will remove expired requests with no delay.
.TP
\fB\-\-requestretentionunit=REQUESTRETENTIONUNIT\fR
Request retention units. Valid units are: minute, hour, day, year.
@@ -102,7 +102,7 @@ The default is days.
LDAP search size limit searching for unfulfilled requests. The default is 1000. There may be additional server-side limitations.
.TP
\fB\-\-requestsearchtimelimit=REQUESTSEARCHTIMELIMIT\fR
-LDAP search time limit searching for unfulfilled requests. The default is 0, no limit. There may be additional server-side limitations.
+LDAP search time limit (seconds) searching for unfulfilled requests. The default is 0, no limit. There may be additional server-side limitations.
.TP
\fB\-\-config\-show\fR
Show the current pruning configuration
diff --git a/ipaserver/install/ipa_acme_manage.py b/ipaserver/install/ipa_acme_manage.py
index b7b2111d9edcec2580aa4a485d7a7340146ff065..e7c35ff6fb5b7a30ac9e2c0c18f8db805cf06ee9 100644
--- a/ipaserver/install/ipa_acme_manage.py
+++ b/ipaserver/install/ipa_acme_manage.py
@@ -207,14 +207,14 @@ class IPAACMEManage(AdminTool):
self.options.enable,
self.options.disable,
self.options.cron,
- self.options.certretention,
+ self.options.certretention is not None,
self.options.certretentionunit,
- self.options.requestretention,
+ self.options.requestretention is not None,
self.options.requestretentionunit,
- self.options.certsearchsizelimit,
- self.options.certsearchtimelimit,
- self.options.requestsearchsizelimit,
- self.options.requestsearchtimelimit,
+ self.options.certsearchsizelimit is not None,
+ self.options.certsearchtimelimit is not None,
+ self.options.requestsearchsizelimit is not None,
+ self.options.requestsearchtimelimit is not None,
]
)
and (self.options.config_show or self.options.run)
@@ -226,7 +226,7 @@ class IPAACMEManage(AdminTool):
elif self.options.cron:
if len(self.options.cron.split()) != 5:
self.option_parser.error("Invalid format for --cron")
- # dogtag does no validation when setting an option so
+ # dogtag does no validation when setting this option so
# do the minimum. The dogtag cron is limited compared to
# crontab(5).
opt = self.options.cron.split()
@@ -255,7 +255,7 @@ class IPAACMEManage(AdminTool):
'pki-server', command,
f'{prefix}.{directive}'
]
- if value:
+ if value is not None:
args.extend([str(value)])
logger.debug(args)
result = run(args, raiseonerr=False, capture_output=True,
@@ -350,28 +350,28 @@ class IPAACMEManage(AdminTool):
# pki-server ca-config-set can only set one option at a time so
# loop through all the options and set what is there.
- if self.options.certretention:
+ if self.options.certretention is not None:
ca_config_set('certRetentionTime',
self.options.certretention)
if self.options.certretentionunit:
ca_config_set('certRetentionUnit',
self.options.certretentionunit)
- if self.options.certsearchtimelimit:
+ if self.options.certsearchtimelimit is not None:
ca_config_set('certSearchTimeLimit',
self.options.certsearchtimelimit)
- if self.options.certsearchsizelimit:
+ if self.options.certsearchsizelimit is not None:
ca_config_set('certSearchSizeLimit',
self.options.certsearchsizelimit)
- if self.options.requestretention:
+ if self.options.requestretention is not None:
ca_config_set('requestRetentionTime',
self.options.requestretention)
if self.options.requestretentionunit:
ca_config_set('requestRetentionUnit',
self.options.requestretentionunit)
- if self.options.requestsearchsizelimit:
+ if self.options.requestsearchsizelimit is not None:
ca_config_set('requestSearchSizeLimit',
self.options.requestsearchsizelimit)
- if self.options.requestsearchtimelimit:
+ if self.options.requestsearchtimelimit is not None:
ca_config_set('requestSearchTimeLimit',
self.options.requestsearchtimelimit)
if self.options.cron:
--
2.39.1

View File

@ -1,82 +0,0 @@
From b6520bef2ef05dd87636d8b57e3247d451af81d8 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Tue, 14 Dec 2021 16:33:29 +0100
Subject: [PATCH] ipatests: Fix expected object classes
Because the sidgen plugin is a postop plugin, it is not
always triggered before the result of an ADD is returned
and the objectclasses of the user may / may not contain
ipantuserattrs.
Fix the expected object classes.
Related: https://pagure.io/freeipa/issue/9062
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-By: Stanislav Levin <slev@altlinux.org>
---
ipatests/test_xmlrpc/test_user_plugin.py | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py
index 74d78b0c6d75590640da1357da1f9f4570307878..c156a8793c5765df96029753f4a278e961d4e895 100644
--- a/ipatests/test_xmlrpc/test_user_plugin.py
+++ b/ipatests/test_xmlrpc/test_user_plugin.py
@@ -125,7 +125,9 @@ def user_npg(request, group):
del tracker.attrs['mepmanagedentry']
tracker.attrs.update(
description=[], memberof_group=[group.cn],
- objectclass=objectclasses.user_base + [u'ipantuserattrs'],
+ objectclass=fuzzy_set_optional_oc(
+ objectclasses.user_base, 'ipantuserattrs'
+ ),
)
return tracker.make_fixture(request)
@@ -139,7 +141,9 @@ def user_npg2(request, group):
del tracker.attrs['mepmanagedentry']
tracker.attrs.update(
gidnumber=[u'1000'], description=[], memberof_group=[group.cn],
- objectclass=objectclasses.user_base + [u'ipantuserattrs'],
+ objectclass=fuzzy_set_optional_oc(
+ objectclasses.user_base, 'ipantuserattrs'
+ ),
)
return tracker.make_fixture(request)
@@ -151,8 +155,9 @@ def user_radius(request, xmlrpc_setup):
sn=u'radiususer1',
ipatokenradiususername=u'radiususer')
tracker.track_create()
- tracker.attrs.update(
- objectclass=objectclasses.user + [u'ipatokenradiusproxyuser']
+ tracker.attrs.update(objectclass=fuzzy_set_optional_oc(
+ objectclasses.user + [u'ipatokenradiusproxyuser'],
+ 'ipantuserattrs'),
)
return tracker.make_fixture(request)
@@ -647,7 +652,8 @@ class TestCreate(XMLRPC_test):
testuser.attrs.update(gidnumber=[u'1000'])
testuser.attrs.update(
description=[],
- objectclass=objectclasses.user_base + [u'ipantuserattrs']
+ objectclass=fuzzy_set_optional_oc(
+ objectclasses.user_base, 'ipantuserattrs'),
)
command = testuser.make_create_command()
result = command()
@@ -865,7 +871,9 @@ class TestUserWithUPGDisabled(XMLRPC_test):
testuser.attrs.update(gidnumber=[u'1000'])
testuser.attrs.update(
description=[],
- objectclass=objectclasses.user_base + [u'ipantuserattrs'],
+ objectclass=fuzzy_set_optional_oc(
+ objectclasses.user_base, 'ipantuserattrs'
+ ),
)
command = testuser.make_create_command()
result = command()
--
2.37.2

View File

@ -0,0 +1,69 @@
From 4e0ad96fbd9f438c884eeeaa60c2fb0c910a2b61 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
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 <rcritten@redhat.com>
Reviewed-By: Francisco Trivino <ftrivino@redhat.com>
Reviewed-By: Stanislav Levin <slev@altlinux.org>
---
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 e2bc530ee8a8d7ade853652680c524ccd229205c..aaae5446856aba5e39ca9bb9c03decd434e4f71a 100644
--- a/ipaserver/dns_data_management.py
+++ b/ipaserver/dns_data_management.py
@@ -19,6 +19,7 @@ from dns import (
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 @@ class IPASystemRecords:
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 @@ class IPASystemRecords:
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 @@ class IPASystemRecords:
)
)
+ # 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
--
2.39.1

View File

@ -1,50 +0,0 @@
From 1aa39529cda4ab9620539dbad705cedd23c21b42 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
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 <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
---
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 4b9db34247c1446aec3f5bcce7dfa1bd8a2bd359..e26aedda976b19f3ba26593ba3b3c06c30506a21 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

View File

@ -1,74 +0,0 @@
From 45e6d49b94da78cd82eb016b3266a17a1359a087 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
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 <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
---
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 66929b921b197e27ede847fb6b10bf1e44c3464a..210bfc4950e6a7346dbdd6e29d1096b2f8750b1e 100644
--- a/API.txt
+++ b/API.txt
@@ -4076,7 +4076,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 4428aede2dcc7a2a0b6128bf7f58eb47e4a8e07d..f4ebffd5c8f06a53b6c4d5e48ff6eeafa240e3a4 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 8eee69c185b15be72870050ed247f252c72d1c66..fc785223bfe56269ad8b211e8f1c3ac9f4064c3c 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

View File

@ -0,0 +1,111 @@
From 0206369eec8530e96c66986c4ca501d8962193ce Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Mon, 30 Jan 2023 14:22:30 +0200
Subject: [PATCH] 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 <abokovoy@redhat.com>
Reviewed-By: Rafael Guterres Jeffman <rjeffman@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
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 a15050e2166f95c227d2e3c7d238e1ea2fe01235..476d1cb558a53420821ccfb1b794cb6bedce7794 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 : "<failed to display>");
+ 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;
--
2.39.1

View File

@ -0,0 +1,83 @@
From a6cb905de74da38d62f9c3bd7957018924282521 Mon Sep 17 00:00:00 2001
From: Anuja More <amore@redhat.com>
Date: Mon, 30 Jan 2023 19:27:49 +0530
Subject: [PATCH] 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 <amore@redhat.com>
Reviewed-By: Rafael Guterres Jeffman <rjeffman@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
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 c4b3b99ce1abbc16817b6530939fd9bae3f9500a..0d5b71cb0277a79eed7c34eb7e3d7eb6c09faa5e 100644
--- a/ipatests/test_integration/test_trust.py
+++ b/ipatests/test_integration/test_trust.py
@@ -527,6 +527,35 @@ class TestTrust(BaseTestTrust):
.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)
@@ -785,6 +814,23 @@ class TestTrust(BaseTestTrust):
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)
--
2.39.1

View File

@ -1,106 +0,0 @@
From de6f074538f6641fd9d84bed204a3d4d50eccbe5 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
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 <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
---
.../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 c7ec71d492b0ac0e7641d586b7e7fa7501743bc2..6fe91aa6c6310a69a7f0feb1ad62243945db67f9 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 dca44ce4369dfc11f83a412a1249bb045d46713f..4185f034313bd49ca68e86c620043af6ead5f6d6 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

View File

@ -1,62 +0,0 @@
From a0928fe164712303a7c24ee61500ac7326bd9e4a Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
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 <abokovoy@redhat.com>
Reviewed-By: Armando Neto <abiagion@redhat.com>
---
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

View File

@ -0,0 +1,36 @@
From c411c2e7b2e400829ffac250db81609ef3c56faa Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Tue, 29 Nov 2022 10:04:41 +0100
Subject: [PATCH] webui tests: fix assertion in test_subid.py
The test wants to check the error related to an
exception obtained inside a "with pytest.raises" instruction.
The object is an ExceptionInfo and offers a match method
to check the content of the string representation.
Use this match() method instead of str(excinfo) which now
returns
'<ExceptionInfo NoSuchElementException() tblen=10>'
Fixes: https://pagure.io/freeipa/issue/9282
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Mohammad Rizwan Yusuf <myusuf@redhat.com>
---
ipatests/test_webui/test_subid.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ipatests/test_webui/test_subid.py b/ipatests/test_webui/test_subid.py
index 104b5692da94437880e638c0b2bc8efd41bd969e..3aaf80ac885fea08d0bac7e2f46645fe207f2cb0 100644
--- a/ipatests/test_webui/test_subid.py
+++ b/ipatests/test_webui/test_subid.py
@@ -146,5 +146,5 @@ class test_subid(UI_driver):
with pytest.raises(NoSuchElementException) as excinfo:
self.delete_record(admin_uid, table_name="ipauniqueid")
# Ensure that the exception is really related to missing remove button
- msg = "Unable to locate element: .facet-controls button[name=remove]"
- assert msg in str(excinfo)
+ msg = r"Unable to locate element: .facet-controls button\[name=remove\]"
+ assert excinfo.match(msg)
--
2.39.1

View File

@ -1,475 +0,0 @@
From 3cbf2b25422100cc4105dfb09ee8c7bf87232198 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Mon, 22 Aug 2022 10:57:14 -0400
Subject: [PATCH] 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 <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
ipaclient/install/client.py | 377 +++++++++++++++++++-----------------
1 file changed, 196 insertions(+), 181 deletions(-)
diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py
index 920c517d4f2b5414d8d2af63d029949cb4f02dc6..93bc7400805dafffcb3909771f0458e5b7e4a764 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.')
--
2.38.1

View File

@ -0,0 +1,29 @@
From b5f2b0b1b213149b5bfe2653c9e40de98249dc73 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Tue, 10 Jan 2023 11:45:17 +0100
Subject: [PATCH] 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 <flo@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
---
ipatests/test_integration/test_smb.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/ipatests/test_integration/test_smb.py b/ipatests/test_integration/test_smb.py
index eb3981bddb7ca9f72a0d2cb6c46e5c73de8623ac..30f8d5901afbcda95f27cd966ac03d47205dbb26 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
--
2.39.1

View File

@ -0,0 +1,43 @@
From 36cba23f3f671886f5e7fa310c25a6e500c76e0b Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Mon, 16 Jan 2023 09:31:57 +0100
Subject: [PATCH] Tests: force key type in ACME tests
PKI can issue ACME certs only when the key type is rsa.
With version 2.0.0, certbot defaults to ecdsa key type,
and this causes test failures.
For now, force rsa when requesting an ACME certificate.
This change can be reverted when PKI fixes the issue
on their side (https://github.com/dogtagpki/pki/issues/4273)
Related: https://pagure.io/freeipa/issue/9298
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
ipatests/test_integration/test_acme.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/ipatests/test_integration/test_acme.py b/ipatests/test_integration/test_acme.py
index a30f2fc756783c0a5c28ecf32c1e40f422c47a19..15d7543cfb0fa0fcb921166f7cd8f13d0535a41d 100644
--- a/ipatests/test_integration/test_acme.py
+++ b/ipatests/test_integration/test_acme.py
@@ -131,6 +131,7 @@ def certbot_standalone_cert(host, acme_server):
'certonly',
'--domain', host.hostname,
'--standalone',
+ '--key-type', 'rsa',
]
)
@@ -305,6 +306,7 @@ class TestACME(CALessBase):
'--manual-public-ip-logging-ok',
'--manual-auth-hook', CERTBOT_DNS_IPA_SCRIPT,
'--manual-cleanup-hook', CERTBOT_DNS_IPA_SCRIPT,
+ '--key-type', 'rsa',
])
##############
--
2.39.1

View File

@ -1,129 +0,0 @@
From ba962632cd008edd057f61e7e6fadbf464ff94f2 Mon Sep 17 00:00:00 2001
From: Francisco Trivino <ftrivino@redhat.com>
Date: Tue, 4 Oct 2022 17:26:51 +0200
Subject: [PATCH] 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 <ftrivino@redhat.com>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
API.txt | 4 ++--
VERSION.m4 | 4 ++--
ipaclient/plugins/vault.py | 7 ++++---
ipaserver/plugins/vault.py | 4 ++--
4 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/API.txt b/API.txt
index 814124f600111e46c117a0c925e33a27a19b38e0..062a6c756babea6b091c5aaec7d0eaa908b41911 100644
--- a/API.txt
+++ b/API.txt
@@ -6667,7 +6667,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=[<type 'unicode'>, <type 'NoneType'>])
output: PrimaryKey('value')
@@ -6767,7 +6767,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=[<type 'unicode'>, <type 'NoneType'>])
output: PrimaryKey('value')
diff --git a/VERSION.m4 b/VERSION.m4
index 0f02d48979e4af3ad737e377545c4951d5dece02..d628c69a09a43b01aad4ac1bd3a6912bef27a7fe 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 Random Serial Numbers v3
-define(IPA_API_VERSION_MINOR, 249)
+# 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 115171c7768d44251c17d0bcdac9c37b3a25db99..d4c84eb6bfb4cc119c599d494171b0a2417ce0ba 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 4d40f66c6a793a831e91c5fe25c8b5277cbd1972..574c83a9aaa64b6a4774400ea7af25343b445c03 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,
),
)
--
2.38.1

View File

@ -0,0 +1,36 @@
From ff31b0c40cc5e046f839b98b80bd16bb649205ac Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Mon, 30 Jan 2023 11:54:36 -0500
Subject: [PATCH] tests: Add ipa_ca_name checking to DNS system records
freeipa-healthcheck 0.12 includes a SUCCESS message if the
ipa-ca records are as expected so a user will know they
were checked. For that version and beyond test that it
is included.
Related: https://pagure.io/freeipa/issue/9291
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
ipatests/test_integration/test_ipahealthcheck.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/ipatests/test_integration/test_ipahealthcheck.py b/ipatests/test_integration/test_ipahealthcheck.py
index 49a5779307ef05617fe9ae200f7149d120977355..94b0db0b7869e722955e232e1dddb26a2dc3d41e 100644
--- a/ipatests/test_integration/test_ipahealthcheck.py
+++ b/ipatests/test_integration/test_ipahealthcheck.py
@@ -810,7 +810,9 @@ class TestIpaHealthCheck(IntegrationTest):
+ [str(ip) for ip in resolve_ip_addresses_nss(h.external_hostname)]
]
SYSTEM_RECORDS.append(f'"{self.master.domain.realm.upper()}"')
-
+ version = tasks.get_healthcheck_version(self.master)
+ if parse_version(version) >= parse_version("0.12"):
+ SYSTEM_RECORDS.append('ipa_ca_check')
returncode, data = run_healthcheck(
self.master,
--
2.39.1

View File

@ -0,0 +1,53 @@
From 6ca119686aadfa72c0474f72758b63cd671952d4 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Mon, 30 Jan 2023 12:00:03 -0500
Subject: [PATCH] tests: Add new ipa-ca error messages to
IPADNSSystemRecordsCheck
freeipa-healthcheck changed some messages related to ipa-ca
DNS record validation in IPADNSSystemRecordsCheck. Include support
for it and retain backwards compatibility.
Fixes: https://pagure.io/freeipa/issue/9291
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
.../test_integration/test_ipahealthcheck.py | 21 +++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/ipatests/test_integration/test_ipahealthcheck.py b/ipatests/test_integration/test_ipahealthcheck.py
index 94b0db0b7869e722955e232e1dddb26a2dc3d41e..47f64f2cb36904ef61211423de7cf33d21a199c3 100644
--- a/ipatests/test_integration/test_ipahealthcheck.py
+++ b/ipatests/test_integration/test_ipahealthcheck.py
@@ -1614,12 +1614,21 @@ class TestIpaHealthCheckWithoutDNS(IntegrationTest):
Test checks the result of IPADNSSystemRecordsCheck
when ipa-server is configured without DNS.
"""
- expected_msgs = {
- "Expected SRV record missing",
- "Got {count} ipa-ca A records, expected {expected}",
- "Got {count} ipa-ca AAAA records, expected {expected}",
- "Expected URI record missing",
- }
+ version = tasks.get_healthcheck_version(self.master)
+ if (parse_version(version) < parse_version('0.12')):
+ expected_msgs = {
+ "Expected SRV record missing",
+ "Got {count} ipa-ca A records, expected {expected}",
+ "Got {count} ipa-ca AAAA records, expected {expected}",
+ "Expected URI record missing",
+ }
+ else:
+ expected_msgs = {
+ "Expected SRV record missing",
+ "Unexpected ipa-ca address {ipaddr}",
+ "expected ipa-ca to contain {ipaddr} for {server}",
+ "Expected URI record missing",
+ }
tasks.install_packages(self.master, HEALTHCHECK_PKG)
returncode, data = run_healthcheck(
--
2.39.1

View File

@ -0,0 +1,445 @@
From 0f77b359e241fc4055fb8d785e18f96338451ebf Mon Sep 17 00:00:00 2001
From: Mohammad Rizwan <myusuf@redhat.com>
Date: Mon, 6 Feb 2023 15:31:27 +0530
Subject: [PATCH] ipatests: tests for certificate pruning
1. Test to prune the expired certificate by manual run
2. Test to prune expired certificate by cron job
3. Test to prune expired certificate with retention unit option
4. Test to prune expired certificate with search size limit option
5. Test to check config-show command shows set param
6. Test prune command shows proper status after disabling the pruning
related: https://pagure.io/freeipa/issue/9294
Signed-off-by: Mohammad Rizwan <myusuf@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
ipatests/test_integration/test_acme.py | 306 +++++++++++++++++++++----
1 file changed, 260 insertions(+), 46 deletions(-)
diff --git a/ipatests/test_integration/test_acme.py b/ipatests/test_integration/test_acme.py
index 5ceba05976059de69414a79634d98045c3ab68bb..1334be52f4530dd8b2a4207744146cd0eb5477a3 100644
--- a/ipatests/test_integration/test_acme.py
+++ b/ipatests/test_integration/test_acme.py
@@ -122,21 +122,23 @@ def certbot_register(host, acme_server):
)
-def certbot_standalone_cert(host, acme_server):
+def certbot_standalone_cert(host, acme_server, no_of_cert=1):
"""method to issue a certbot's certonly standalone cert"""
# Get a cert from ACME service using HTTP challenge and Certbot's
# standalone HTTP server mode
host.run_command(['systemctl', 'stop', 'httpd'])
- host.run_command(
- [
- 'certbot',
- '--server', acme_server,
- 'certonly',
- '--domain', host.hostname,
- '--standalone',
- '--key-type', 'rsa',
- ]
- )
+ for _i in range(0, no_of_cert):
+ host.run_command(
+ [
+ 'certbot',
+ '--server', acme_server,
+ 'certonly',
+ '--domain', host.hostname,
+ '--standalone',
+ '--key-type', 'rsa',
+ '--force-renewal'
+ ]
+ )
class TestACME(CALessBase):
@@ -573,43 +575,41 @@ class TestACMEwithExternalCA(TestACME):
tasks.install_replica(cls.master, cls.replicas[0])
-class TestACMERenew(IntegrationTest):
-
- num_clients = 1
+@pytest.fixture
+def issue_and_expire_acme_cert():
+ """Fixture to expire cert by moving date past expiry of acme cert"""
+ hosts = []
- @classmethod
- def install(cls, mh):
-
- # install packages before client install in case of IPA DNS problems
- cls.acme_server = prepare_acme_client(cls.master, cls.clients[0])
+ def _issue_and_expire_acme_cert(
+ master, client,
+ acme_server_url, no_of_cert=1
+ ):
- tasks.install_master(cls.master, setup_dns=True)
- tasks.install_client(cls.master, cls.clients[0])
+ hosts.append(master)
+ hosts.append(client)
- @pytest.fixture
- def issue_and_expire_cert(self):
- """Fixture to expire cert by moving date past expiry of acme cert"""
# enable the ACME service on master
- self.master.run_command(['ipa-acme-manage', 'enable'])
+ master.run_command(['ipa-acme-manage', 'enable'])
# register the account with certbot
- certbot_register(self.clients[0], self.acme_server)
+ certbot_register(client, acme_server_url)
# request a standalone acme cert
- certbot_standalone_cert(self.clients[0], self.acme_server)
+ certbot_standalone_cert(client, acme_server_url, no_of_cert)
# move system date to expire acme cert
- for host in self.clients[0], self.master:
+ for host in hosts:
tasks.kdestroy_all(host)
tasks.move_date(host, 'stop', '+90days')
+ time.sleep(10)
tasks.get_kdcinfo(host)
# Note raiseonerr=False:
# the assert is located after kdcinfo retrieval.
- result = host.run_command(
+ result = master.run_command(
"KRB5_TRACE=/dev/stdout kinit admin",
stdin_text='{0}\n{0}\n{0}\n'.format(
- self.clients[0].config.admin_password
+ master.config.admin_password
),
raiseonerr=False
)
@@ -618,16 +618,28 @@ class TestACMERenew(IntegrationTest):
tasks.get_kdcinfo(host)
assert result.returncode == 0
- yield
+ yield _issue_and_expire_acme_cert
- # move back date
- for host in self.clients[0], self.master:
- tasks.kdestroy_all(host)
- tasks.move_date(host, 'start', '-90days')
- tasks.kinit_admin(host)
+ # move back date
+ for host in hosts:
+ tasks.move_date(host, 'start', '-90days')
+
+
+class TestACMERenew(IntegrationTest):
+
+ num_clients = 1
+
+ @classmethod
+ def install(cls, mh):
+
+ # install packages before client install in case of IPA DNS problems
+ cls.acme_server = prepare_acme_client(cls.master, cls.clients[0])
+
+ tasks.install_master(cls.master, setup_dns=True)
+ tasks.install_client(cls.master, cls.clients[0])
@pytest.mark.skipif(skip_certbot_tests, reason='certbot not available')
- def test_renew(self, issue_and_expire_cert):
+ def test_renew(self, issue_and_expire_acme_cert):
"""Test if ACME renews the issued cert with cerbot
This test is to check if ACME certificate renews upon
@@ -635,6 +647,8 @@ class TestACMERenew(IntegrationTest):
related: https://pagure.io/freeipa/issue/4751
"""
+ issue_and_expire_acme_cert(
+ self.master, self.clients[0], self.acme_server)
data = self.clients[0].get_file_contents(
f'/etc/letsencrypt/live/{self.clients[0].hostname}/cert.pem'
)
@@ -656,6 +670,7 @@ class TestACMEPrune(IntegrationTest):
"""Validate that ipa-acme-manage configures dogtag for pruning"""
random_serial = True
+ num_clients = 1
@classmethod
def install(cls, mh):
@@ -663,6 +678,8 @@ class TestACMEPrune(IntegrationTest):
raise pytest.skip("RNSv3 not supported")
tasks.install_master(cls.master, setup_dns=True,
random_serial=True)
+ cls.acme_server = prepare_acme_client(cls.master, cls.clients[0])
+ tasks.install_client(cls.master, cls.clients[0])
@classmethod
def uninstall(cls, mh):
@@ -718,7 +735,7 @@ class TestACMEPrune(IntegrationTest):
['ipa-acme-manage', 'pruning',
'--requestretention=60',
'--requestretentionunit=minute',
- '--requestresearchsizelimit=2000',
+ '--requestsearchsizelimit=2000',
'--requestsearchtimelimit=5',]
)
cs_cfg = self.master.get_file_contents(paths.CA_CS_CFG_PATH)
@@ -741,7 +758,7 @@ class TestACMEPrune(IntegrationTest):
self.master.run_command(
['ipa-acme-manage', 'pruning',
- '--cron="0 23 1 * *',]
+ '--cron=0 23 1 * *',]
)
cs_cfg = self.master.get_file_contents(paths.CA_CS_CFG_PATH)
assert (
@@ -760,7 +777,7 @@ class TestACMEPrune(IntegrationTest):
'--enable', '--disable'],
raiseonerr=False
)
- assert result.returncode == 1
+ assert result.returncode == 2
assert "Cannot both enable and disable" in result.stderr_text
for cmd in ('--config-show', '--run'):
@@ -769,20 +786,20 @@ class TestACMEPrune(IntegrationTest):
cmd, '--enable'],
raiseonerr=False
)
- assert result.returncode == 1
+ assert result.returncode == 2
assert "Cannot change and show config" in result.stderr_text
result = self.master.run_command(
['ipa-acme-manage', 'pruning',
- '--cron="* *"'],
+ '--cron=* *'],
raiseonerr=False
)
- assert result.returncode == 1
- assert "Invalid format format --cron" in result.stderr_text
+ assert result.returncode == 2
+ assert "Invalid format for --cron" in result.stderr_text
result = self.master.run_command(
['ipa-acme-manage', 'pruning',
- '--cron="100 * * * *"'],
+ '--cron=100 * * * *'],
raiseonerr=False
)
assert result.returncode == 1
@@ -790,8 +807,205 @@ class TestACMEPrune(IntegrationTest):
result = self.master.run_command(
['ipa-acme-manage', 'pruning',
- '--cron="10 1-5 * * *"'],
+ '--cron=10 1-5 * * *'],
raiseonerr=False
)
assert result.returncode == 1
assert "1-5 ranges are not supported" in result.stderr_text
+
+ def test_prune_cert_manual(self, issue_and_expire_acme_cert):
+ """Test to prune expired certificate by manual run"""
+ if (tasks.get_pki_version(self.master)
+ < tasks.parse_version('11.3.0')):
+ raise pytest.skip("Certificate pruning is not available")
+
+ issue_and_expire_acme_cert(
+ self.master, self.clients[0], self.acme_server)
+
+ # check that the certificate issued for the client
+ result = self.master.run_command(
+ ['ipa', 'cert-find', '--subject', self.clients[0].hostname]
+ )
+ assert f'CN={self.clients[0].hostname}' in result.stdout_text
+
+ # run prune command manually
+ self.master.run_command(['ipa-acme-manage', 'pruning', '--enable'])
+ self.master.run_command(['ipactl', 'restart'])
+ self.master.run_command(['ipa-acme-manage', 'pruning', '--run'])
+ # wait for cert to get prune
+ time.sleep(50)
+
+ # check if client cert is removed
+ result = self.master.run_command(
+ ['ipa', 'cert-find', '--subject', self.clients[0].hostname],
+ raiseonerr=False
+ )
+ assert f'CN={self.clients[0].hostname}' not in result.stdout_text
+
+ def test_prune_cert_cron(self, issue_and_expire_acme_cert):
+ """Test to prune expired certificate by cron job"""
+ if (tasks.get_pki_version(self.master)
+ < tasks.parse_version('11.3.0')):
+ raise pytest.skip("Certificate pruning is not available")
+
+ issue_and_expire_acme_cert(
+ self.master, self.clients[0], self.acme_server)
+
+ # check that the certificate issued for the client
+ result = self.master.run_command(
+ ['ipa', 'cert-find', '--subject', self.clients[0].hostname]
+ )
+ assert f'CN={self.clients[0].hostname}' in result.stdout_text
+
+ # enable pruning
+ self.master.run_command(['ipa-acme-manage', 'pruning', '--enable'])
+
+ # cron would be set to run the next minute
+ cron_minute = self.master.run_command(
+ [
+ "python3",
+ "-c",
+ (
+ "from datetime import datetime; "
+ "print(int(datetime.now().strftime('%M')) + 5)"
+ ),
+ ]
+ ).stdout_text.strip()
+ self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ f'--cron={cron_minute} * * * *']
+ )
+ self.master.run_command(['ipactl', 'restart'])
+ # wait for 5 minutes to cron to execute and 20 sec for just in case
+ time.sleep(320)
+
+ # check if client cert is removed
+ result = self.master.run_command(
+ ['ipa', 'cert-find', '--subject', self.clients[0].hostname],
+ raiseonerr=False
+ )
+ assert f'CN={self.clients[0].hostname}' not in result.stdout_text
+
+ def test_prune_cert_retention_unit(self, issue_and_expire_acme_cert):
+ """Test to prune expired certificate with retention unit option"""
+ if (tasks.get_pki_version(self.master)
+ < tasks.parse_version('11.3.0')):
+ raise pytest.skip("Certificate pruning is not available")
+ issue_and_expire_acme_cert(
+ self.master, self.clients[0], self.acme_server)
+
+ # check that the certificate issued for the client
+ result = self.master.run_command(
+ ['ipa', 'cert-find', '--subject', self.clients[0].hostname]
+ )
+ assert f'CN={self.clients[0].hostname}' in result.stdout_text
+
+ # enable pruning
+ self.master.run_command(['ipa-acme-manage', 'pruning', '--enable'])
+
+ # certretention set to 5 min
+ self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ '--certretention=5', '--certretentionunit=minute']
+ )
+ self.master.run_command(['ipactl', 'restart'])
+
+ # wait for 5 min and check if expired cert is removed
+ time.sleep(310)
+ self.master.run_command(['ipa-acme-manage', 'pruning', '--run'])
+ result = self.master.run_command(
+ ['ipa', 'cert-find', '--subject', self.clients[0].hostname],
+ raiseonerr=False
+ )
+ assert f'CN={self.clients[0].hostname}' not in result.stdout_text
+
+ def test_prune_cert_search_size_limit(self, issue_and_expire_acme_cert):
+ """Test to prune expired certificate with search size limit option"""
+ if (tasks.get_pki_version(self.master)
+ < tasks.parse_version('11.3.0')):
+ raise pytest.skip("Certificate pruning is not available")
+ no_of_cert = 10
+ search_size_limit = 5
+ issue_and_expire_acme_cert(
+ self.master, self.clients[0], self.acme_server, no_of_cert)
+
+ # check that the certificate issued for the client
+ result = self.master.run_command(
+ ['ipa', 'cert-find', '--subject', self.clients[0].hostname]
+ )
+ assert f'CN={self.clients[0].hostname}' in result.stdout_text
+ assert f'Number of entries returned {no_of_cert}'
+
+ # enable pruning
+ self.master.run_command(['ipa-acme-manage', 'pruning', '--enable'])
+
+ # certretention set to 5 min
+ self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ f'--certsearchsizelimit={search_size_limit}',
+ '--certsearchtimelimit=100']
+ )
+ self.master.run_command(['ipactl', 'restart'])
+
+ # prune the certificates
+ self.master.run_command(['ipa-acme-manage', 'pruning', '--run'])
+
+ # check if 5 expired cert is removed
+ result = self.master.run_command(
+ ['ipa', 'cert-find', '--subject', self.clients[0].hostname]
+ )
+ assert f'Number of entries returned {no_of_cert - search_size_limit}'
+
+ def test_prune_config_show(self, issue_and_expire_acme_cert):
+ """Test to check config-show command shows set param"""
+ if (tasks.get_pki_version(self.master)
+ < tasks.parse_version('11.3.0')):
+ raise pytest.skip("Certificate pruning is not available")
+
+ self.master.run_command(['ipa-acme-manage', 'pruning', '--enable'])
+ self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ '--cron=0 0 1 * *']
+ )
+ self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ '--certretention=30', '--certretentionunit=day']
+ )
+ self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ '--certsearchsizelimit=1000', '--certsearchtimelimit=0']
+ )
+ self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ '--requestretention=30', '--requestretentionunit=day']
+ )
+ self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ '--requestsearchsizelimit=1000', '--requestsearchtimelimit=0']
+ )
+ result = self.master.run_command(
+ ['ipa-acme-manage', 'pruning', '--config-show']
+ )
+ assert 'Status: enabled' in result.stdout_text
+ assert 'Certificate Retention Time: 30' in result.stdout_text
+ assert 'Certificate Retention Unit: day' in result.stdout_text
+ assert 'Certificate Search Size Limit: 1000' in result.stdout_text
+ assert 'Certificate Search Time Limit: 100' in result.stdout_text
+ assert 'Request Retention Time: 30' in result.stdout_text
+ assert 'Request Retention Unit: day' in result.stdout_text
+ assert 'Request Search Size Limit' in result.stdout_text
+ assert 'Request Search Time Limit: 100' in result.stdout_text
+ assert 'cron Schedule: 0 0 1 * *' in result.stdout_text
+
+ def test_prune_disable(self, issue_and_expire_acme_cert):
+ """Test prune command throw error after disabling the pruning"""
+ if (tasks.get_pki_version(self.master)
+ < tasks.parse_version('11.3.0')):
+ raise pytest.skip("Certificate pruning is not available")
+
+ self.master.run_command(['ipa-acme-manage', 'pruning', '--disable'])
+ result = self.master.run_command(
+ ['ipa-acme-manage', 'pruning',
+ '--cron=0 0 1 * *']
+ )
+ assert 'Status: disabled' in result.stdout_text
--
2.39.1

View File

@ -0,0 +1,65 @@
From 88b9be29036a3580a8bccd31986fc30faa9852df Mon Sep 17 00:00:00 2001
From: mbhalodi <mbhalodi@redhat.com>
Date: Tue, 14 Feb 2023 15:04:58 +0530
Subject: [PATCH] ipatests: ensure that ipa automember-rebuild prints a warning
ipa automember-rebuild now prints a warning about CPU usage.
Ensure that the warning is properly displayed.
Related: https://pagure.io/freeipa/issue/9320
Signed-off-by: mbhalodi <mbhalodi@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
ipatests/test_integration/test_automember.py | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/ipatests/test_integration/test_automember.py b/ipatests/test_integration/test_automember.py
index f013964140714db046a1aa6a92409244b2137727..7acd0d7bf895fec970f2bda8b54f4496280525b6 100644
--- a/ipatests/test_integration/test_automember.py
+++ b/ipatests/test_integration/test_automember.py
@@ -10,6 +10,9 @@ from ipapython.dn import DN
from ipatests.pytest_ipa.integration import tasks
from ipatests.test_integration.base import IntegrationTest
+msg = ('IMPORTANT: In case of a high number of users, hosts or '
+ 'groups, the operation may require high CPU usage.')
+
class TestAutounmembership(IntegrationTest):
"""Tests for autounmembership feature.
@@ -206,11 +209,13 @@ class TestAutounmembership(IntegrationTest):
assert self.is_user_member_of_group(user2, group1)
# Running automember-build so that user is part of correct group
- self.master.run_command(['ipa', 'automember-rebuild',
- '--users=%s' % user2])
+ result = self.master.run_command(['ipa', 'automember-rebuild',
+ '--users=%s' % user2])
assert self.is_user_member_of_group(user2, group2)
assert not self.is_user_member_of_group(user2, group1)
+ assert msg in result.stdout_text
+
finally:
# testcase cleanup
self.remove_user_automember(user2, raiseonerr=False)
@@ -240,12 +245,14 @@ class TestAutounmembership(IntegrationTest):
assert self.is_host_member_of_hostgroup(host2, hostgroup1)
# Running the automember-build so host is part of correct hostgroup
- self.master.run_command(
+ result = self.master.run_command(
['ipa', 'automember-rebuild', '--hosts=%s' % host2]
)
assert self.is_host_member_of_hostgroup(host2, hostgroup2)
assert not self.is_host_member_of_hostgroup(host2, hostgroup1)
+ assert msg in result.stdout_text
+
finally:
# testcase cleanup
self.remove_host_automember(host2, raiseonerr=False)
--
2.39.1

View File

@ -0,0 +1,74 @@
From e76b219c21d53b6bccce4ea3d18e2b61ac835e1f Mon Sep 17 00:00:00 2001
From: Mohammad Rizwan <myusuf@redhat.com>
Date: Mon, 20 Feb 2023 15:33:09 +0530
Subject: [PATCH] ipatests: fix tests in TestACMEPrune
When cron_minute + 5 > 59, cron job throwing error for it.
i.e 58 + 5 = 63 which is not acceptable value for cron minute.
Second fix is related to mismatch of confing setting and corresponding
assert.
Third fix is related to extending time by 60 minutes to properly
expire the certs.
related: https://pagure.io/freeipa/issue/9294
Signed-off-by: Mohammad Rizwan <myusuf@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
ipatests/test_integration/test_acme.py | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/ipatests/test_integration/test_acme.py b/ipatests/test_integration/test_acme.py
index 1334be52f4530dd8b2a4207744146cd0eb5477a3..49b173060f88d4b8e876d8e3461a935938518b44 100644
--- a/ipatests/test_integration/test_acme.py
+++ b/ipatests/test_integration/test_acme.py
@@ -600,7 +600,7 @@ def issue_and_expire_acme_cert():
# move system date to expire acme cert
for host in hosts:
tasks.kdestroy_all(host)
- tasks.move_date(host, 'stop', '+90days')
+ tasks.move_date(host, 'stop', '+90days+60minutes')
time.sleep(10)
tasks.get_kdcinfo(host)
@@ -622,7 +622,7 @@ def issue_and_expire_acme_cert():
# move back date
for host in hosts:
- tasks.move_date(host, 'start', '-90days')
+ tasks.move_date(host, 'start', '-90days-60minutes')
class TestACMERenew(IntegrationTest):
@@ -866,8 +866,9 @@ class TestACMEPrune(IntegrationTest):
"python3",
"-c",
(
- "from datetime import datetime; "
- "print(int(datetime.now().strftime('%M')) + 5)"
+ "from datetime import datetime, timedelta; "
+ "print(int((datetime.now() + "
+ "timedelta(minutes=5)).strftime('%M')))"
),
]
).stdout_text.strip()
@@ -990,11 +991,11 @@ class TestACMEPrune(IntegrationTest):
assert 'Certificate Retention Time: 30' in result.stdout_text
assert 'Certificate Retention Unit: day' in result.stdout_text
assert 'Certificate Search Size Limit: 1000' in result.stdout_text
- assert 'Certificate Search Time Limit: 100' in result.stdout_text
+ assert 'Certificate Search Time Limit: 0' in result.stdout_text
assert 'Request Retention Time: 30' in result.stdout_text
assert 'Request Retention Unit: day' in result.stdout_text
- assert 'Request Search Size Limit' in result.stdout_text
- assert 'Request Search Time Limit: 100' in result.stdout_text
+ assert 'Request Search Size Limit: 1000' in result.stdout_text
+ assert 'Request Search Time Limit: 0' in result.stdout_text
assert 'cron Schedule: 0 0 1 * *' in result.stdout_text
def test_prune_disable(self, issue_and_expire_acme_cert):
--
2.39.1

View File

@ -1,16 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEE11Z2TU1+KXxtrRFyaYdvcqbi008FAmK8aYIACgkQaYdvcqbi
00/mYQ/9GsTlD3aiAVvkTn+PLngLdsg3zFSDXUUI/I4ylOeoubzYmdWrX2yWJfvk
soVcxtHeLkrI/uLo44iiZkxYILxMY56dPzoUn6I46VQFppdoOzwlvdYhlOXYtvtB
yYIZhMdCsTkCORMlZ/RR8qNH8iZ1Zjzd4sf6CMWDdxK6ruAfPzaKAMm4EMa1+Rv7
67OfSJKqfNksfeKNndYyNki1FmZo7ukKqcA5/lE+ZaN3/yg6IMydqJVD462OJizF
aHyYZDEaUQv3Or9d8V5G/qJpUz6wCjvzLGvNp3nn4goyX2RG1yY6AX6W8P5/FGiN
A5emCV2LmufWE02CGHZ/9i88BIRqh0laPYJianEw/4iJa3BVYDjnlCTWxjDqVfv/
WBlEnZm/bQkHJITEe6hIwmnHJIFPrhuPxsaBIRUNU1oLTIoU+VFnPRyGGeFuKPSX
girFx1ip3roB6ChoXhYprS1eJ8CjP61ffjT+GLXl9b8OyqFmbxLCMRp19uFt96L1
DHWZv9ytfcwoZW7zzKlCwcGcLsui4PCmriSS8uaGUNvouBfeshHU4OgilwJnjQMP
kPvqagQCF7xe1ZoOdgoKgYvhXI+jABrZ0LVQoj4QMHGjCxkdFmhNNM37xtHogae9
NwfSWqa9UZO+LHy4tNiHrv9W0WnDoPjLFrod2yxIfhh/reYs3GU=
=Zzx6
-----END PGP SIGNATURE-----

View File

@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEE11Z2TU1+KXxtrRFyaYdvcqbi008FAmN/lzsACgkQaYdvcqbi
00+f7w//a5Y4tgTD2A52fQdihv/Q2ZZqhPlSt8rP7bTLtGSjvANHpuF2u0FcjmtB
tADL4zljBGGMGONGt1qMF3d0BkAXhyVp8YNIBcL+abEhgeKL++3egOrI/8iyl4FB
Sr8Gvr1T4AJXjz+yZ/SsPNKerqFrJwi3flavZ7Bk1c2W2V3rJubSAvK9XwO7Cyxs
4afYpLAiknPh999q3zt7NyviivBTYXirif2T45Lelln9sQaB1ksqDA7oYYAfhV0B
wmUJMTtDoaMAcsLT29aC8wGSB5dttI5GmrF60gnbq/t5Tr+7x9ch8VYE60qkynU9
n1WcouuIwvcwfPpYSONak0vFrnMV2USNQj5OnzlKXl1HnHsSqoaQWRUA6bbBPjdb
xQLdQRrZiYtjG5YcwuZyg8TRP2ph1aY3yL2gAR1ZI13yJeNV0pwU+IwouJDiVPvS
dwiG8en1jUxYCeXFKjPX3A8/2ei+LvLTVY65qZKT+BsXyE2CymmUx7P20lFN5Ksb
RN+g37mJI8CwqmlemdTZiF+wJnlswS9SOS5zxhpVRiJHAV1sfxu66515c9+n890A
Hlm9sZn9UBQN5nLwuak8jaOr73E+d8uieXsSCA4wTtXKQSJs67fNY6ldeUmNximc
fq6Yh+lDau14rDlPZUkXx0Jd/oPEWDrtnJzfHECeoRn3KoNzezU=
=pxPY
-----END PGP SIGNATURE-----

View File

@ -66,33 +66,34 @@
%if 0%{?rhel} %if 0%{?rhel}
%global package_name ipa %global package_name ipa
%global alt_name freeipa %global alt_name freeipa
%global krb5_version 1.19.1-15 %global krb5_version 1.20.1-1
%global krb5_kdb_version 8.0 %global krb5_kdb_version 9.0
# 0.7.16: https://github.com/drkjam/netaddr/issues/71 # 0.7.16: https://github.com/drkjam/netaddr/issues/71
%global python_netaddr_version 0.7.19 %global python_netaddr_version 0.7.19
# Require 4.7.0 which brings Python 3 bindings %global samba_version 4.17.4-101
%global samba_version 4.15.2-2
%global selinux_policy_version 3.14.3-52
%global slapi_nis_version 0.56.4 %global slapi_nis_version 0.56.4
%global python_ldap_version 3.1.0-1 %global python_ldap_version 3.1.0-1
%if 0%{?rhel} < 9 %if 0%{?rhel} < 9
# Bug 1929067 - PKI instance creation failed with new 389-ds-base build # Bug 1929067 - PKI instance creation failed with new 389-ds-base build
%global ds_version 1.4.3.16-12 %global ds_version 1.4.3.16-12
%global selinux_policy_version 3.14.3-107
%else %else
# DNA interval enabled # DNA interval enabled
%global ds_version 2.0.5-1 %global ds_version 2.0.5-1
%global selinux_policy_version 38.1.1-1
%endif %endif
# Fix for TLS 1.3 PHA, RHBZ#1775158 # Fix for TLS 1.3 PHA, RHBZ#1775158
%global httpd_version 2.4.37-21 %global httpd_version 2.4.37-21
%global bind_version 9.11.20-6 %global bind_version 9.11.20-6
# Fix for https://github.com/SSSD/sssd/issues/6331
%global sssd_version 2.8.0
%else %else
# Fedora # Fedora
%global package_name freeipa %global package_name freeipa
%global alt_name ipa %global alt_name ipa
# Fix for CVE-2020-28196
%global krb5_version 1.18.2-29
# 0.7.16: https://github.com/drkjam/netaddr/issues/71 # 0.7.16: https://github.com/drkjam/netaddr/issues/71
%global python_netaddr_version 0.7.16 %global python_netaddr_version 0.7.16
# Require 4.7.0 which brings Python 3 bindings # Require 4.7.0 which brings Python 3 bindings
@ -100,10 +101,23 @@
%global samba_version 2:4.12.10 %global samba_version 2:4.12.10
# 3.14.5-45 or later includes a number of interfaces fixes for IPA interface # 3.14.5-45 or later includes a number of interfaces fixes for IPA interface
# 36.16-1 fixes BZ#2115691
%if 0%{?fedora} < 36
%global selinux_policy_version 3.14.5-45 %global selinux_policy_version 3.14.5-45
%else
%global selinux_policy_version 36.16-1
%endif
%global slapi_nis_version 0.56.5 %global slapi_nis_version 0.56.5
%if 0%{?fedora} < 38
# Fix for CVE-2020-28196
%global krb5_version 1.18.2-29
%global krb5_kdb_version 8.0 %global krb5_kdb_version 8.0
%else
# Fix for CVE-2020-28196
%global krb5_version 1.20.1-3
%global krb5_kdb_version 9.0
%endif
# fix for segfault in python3-ldap, https://pagure.io/freeipa/issue/7324 # fix for segfault in python3-ldap, https://pagure.io/freeipa/issue/7324
%global python_ldap_version 3.1.0-1 %global python_ldap_version 3.1.0-1
@ -119,11 +133,25 @@
# Fix for TLS 1.3 PHA, RHBZ#1775146 # Fix for TLS 1.3 PHA, RHBZ#1775146
%global httpd_version 2.4.41-9 %global httpd_version 2.4.41-9
# Fix for RHBZ#2117342
%if 0%{?fedora} < 37
%global bind_version 9.11.24-1 %global bind_version 9.11.24-1
%else
%global bind_version 32:9.18.7-1
%endif
# Don't use Fedora's Python dependency generator on Fedora 30/rawhide yet. # Don't use Fedora's Python dependency generator on Fedora 30/rawhide yet.
# Some packages don't provide new dist aliases. # Some packages don't provide new dist aliases.
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Python/ # https://docs.fedoraproject.org/en-US/packaging-guidelines/Python/
%{?python_disable_dependency_generator} %{?python_disable_dependency_generator}
%if 0%{?fedora} < 37
# F35+, adds IdP integration
%global sssd_version 2.7.0
%else
# Fix for https://github.com/SSSD/sssd/issues/6331
%global sssd_version 2.8.0
%endif
# Fedora # Fedora
%endif %endif
@ -150,9 +178,6 @@
# RHEL 8.2+, F32+ has 3.58 # RHEL 8.2+, F32+ has 3.58
%global nss_version 3.44.0-4 %global nss_version 3.44.0-4
# RHEL 8.7+, F35+, adds IdP integration
%global sssd_version 2.7.0
%define krb5_base_version %(LC_ALL=C /usr/bin/pkgconf --modversion krb5 | grep -Eo '^[^.]+\.[^.]+' || echo %krb5_version) %define krb5_base_version %(LC_ALL=C /usr/bin/pkgconf --modversion krb5 | grep -Eo '^[^.]+\.[^.]+' || echo %krb5_version)
%global kdcproxy_version 0.4-3 %global kdcproxy_version 0.4-3
@ -185,7 +210,7 @@
# Work-around fact that RPM SPEC parser does not accept # Work-around fact that RPM SPEC parser does not accept
# "Version: @VERSION@" in freeipa.spec.in used for Autoconf string replacement # "Version: @VERSION@" in freeipa.spec.in used for Autoconf string replacement
%define IPA_VERSION 4.10.0 %define IPA_VERSION 4.10.1
# Release candidate version -- uncomment with one percent for RC versions # Release candidate version -- uncomment with one percent for RC versions
#%%global rc_version %%nil #%%global rc_version %%nil
%define AT_SIGN @ %define AT_SIGN @
@ -198,7 +223,7 @@
Name: %{package_name} Name: %{package_name}
Version: %{IPA_VERSION} Version: %{IPA_VERSION}
Release: 8%{?rc_version:.%rc_version}%{?dist} Release: 6%{?rc_version:.%rc_version}%{?dist}
Summary: The Identity, Policy and Audit system Summary: The Identity, Policy and Audit system
License: GPLv3+ License: GPLv3+
@ -217,32 +242,38 @@ Source1: https://releases.pagure.org/freeipa/freeipa-%{version}%{?rc_vers
# RHEL spec file only: START # RHEL spec file only: START
%if %{NON_DEVELOPER_BUILD} %if %{NON_DEVELOPER_BUILD}
%if 0%{?rhel} >= 8 %if 0%{?rhel} == 8
Patch0001: 0001-Only-calculate-LDAP-password-grace-when-the-password.patch Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch
Patch0002: 0002-webui-Do-not-allow-empty-pagination-size.patch Patch1002: 1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch
Patch0003: 0003-ipatests-add-nightly-definitions-for-ipa-4-10-branch.patch %endif
Patch0004: 0004-Added-a-check-while-removing-cert_dir-.-The-teardown.patch %if 0%{?rhel} == 9
Patch0005: 0005-ipatests-healthcheck-test-if-system-is-FIPS-enabled.patch Patch0001: 0001-updates-fix-memberManager-ACI-to-allow-managers-from.patch
Patch0006: 0006-Disabling-gracelimit-does-not-prevent-LDAP-binds.patch Patch0002: 0002-Spec-file-ipa-client-depends-on-krb5-pkinit-openssl.patch
Patch0007: 0007-ipatests-ipa-client-install-subid-adds-entry-in-nssw.patch Patch0003: 0003-server-install-remove-error-log-about-missing-bkup-f.patch
Patch0008: 0008-webui-Allow-grace-login-limit.patch Patch0004: 0004-ipa-tests-Add-LANG-before-kinit-command-to-fix-issue.patch
Patch0009: 0009-Additional-tests-for-RSN-v3.patch Patch0005: 0005-trust-add-handle-missing-msSFU30MaxGidNumber.patch
Patch0010: 0010-check_repl_update-in-progress-is-a-boolean.patch Patch0006: 0006-doc-Design-for-certificate-pruning.patch
Patch0011: 0011-ipatests-Fix-expected-object-classes.patch Patch0007: 0007-ipa-acme-manage-add-certificate-request-pruning-mana.patch
Patch0012: 0012-doc-Update-LDAP-grace-period-design-with-default-val.patch Patch0008: 0008-doc-add-the-run-command-for-manual-job-execution.patch
Patch0013: 0013-Set-default-gracelimit-on-group-password-policies-to.patch Patch0009: 0009-tests-add-wrapper-around-ACME-RSNv3-test.patch
Patch0014: 0014-Set-default-on-group-pwpolicy-with-no-grace-limit-in.patch Patch0010: 0010-automember-rebuild-add-a-notice-about-high-CPU-usage.patch
Patch0015: 0015-fix-canonicalization-issue-in-Web-UI.patch Patch0011: 0011-Fix-setting-values-of-0-in-ACME-pruning.patch
Patch0016: 0016-Defer-creating-the-final-krb5.conf-on-clients.patch Patch0012: 0012-Wipe-the-ipa-ca-DNS-record-when-updating-system-reco.patch
Patch0017: 0017-Vault-fix-interoperability-issues-with-older-RHEL-sy.patch Patch0013: 0013-ipa-kdb-PAC-consistency-checker-needs-to-handle-chil.patch
Patch0014: 0014-Add-test-for-SSH-with-GSSAPI-auth.patch
Patch0015: 0015-webui-tests-fix-assertion-in-test_subid.py.patch
Patch0016: 0016-ipatests-mark-test_smb-as-xfail.patch
Patch0017: 0017-Tests-force-key-type-in-ACME-tests.patch
Patch0018: 0018-tests-Add-ipa_ca_name-checking-to-DNS-system-records.patch
Patch0019: 0019-tests-Add-new-ipa-ca-error-messages-to-IPADNSSystemR.patch
Patch0020: 0020-ipatests-tests-for-certificate-pruning.patch
Patch0021: 0021-ipatests-ensure-that-ipa-automember-rebuild-prints-a.patch
Patch0022: 0022-ipatests-fix-tests-in-TestACMEPrune.patch
Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch
%endif %endif
%endif %endif
# RHEL spec file only: END # RHEL spec file only: END
# For the timestamp trick in patch application
BuildRequires: diffstat
BuildRequires: openldap-devel BuildRequires: openldap-devel
# For KDB DAL version, make explicit dependency so that increase of version # For KDB DAL version, make explicit dependency so that increase of version
# will cause the build to fail due to unsatisfied dependencies. # will cause the build to fail due to unsatisfied dependencies.
@ -379,7 +410,6 @@ BuildRequires: python3-libsss_nss_idmap
BuildRequires: python3-lxml BuildRequires: python3-lxml
BuildRequires: python3-netaddr >= %{python_netaddr_version} BuildRequires: python3-netaddr >= %{python_netaddr_version}
BuildRequires: python3-netifaces BuildRequires: python3-netifaces
BuildRequires: python3-paste
BuildRequires: python3-pki >= %{pki_version} BuildRequires: python3-pki >= %{pki_version}
BuildRequires: python3-polib BuildRequires: python3-polib
BuildRequires: python3-pyasn1 BuildRequires: python3-pyasn1
@ -439,7 +469,6 @@ Requires: nss-tools >= %{nss_version}
Requires(post): krb5-server >= %{krb5_version} Requires(post): krb5-server >= %{krb5_version}
Requires(post): krb5-server >= %{krb5_base_version} Requires(post): krb5-server >= %{krb5_base_version}
Requires: krb5-kdb-version = %{krb5_kdb_version} Requires: krb5-kdb-version = %{krb5_kdb_version}
Requires: krb5-pkinit-openssl >= %{krb5_version}
Requires: cyrus-sasl-gssapi%{?_isa} Requires: cyrus-sasl-gssapi%{?_isa}
Requires: chrony Requires: chrony
Requires: httpd >= %{httpd_version} Requires: httpd >= %{httpd_version}
@ -665,6 +694,8 @@ Requires: python3-sssdconfig >= %{sssd_version}
Requires: cyrus-sasl-gssapi%{?_isa} Requires: cyrus-sasl-gssapi%{?_isa}
Requires: chrony Requires: chrony
Requires: krb5-workstation >= %{krb5_version} Requires: krb5-workstation >= %{krb5_version}
# support pkinit with client install
Requires: krb5-pkinit-openssl >= %{krb5_version}
# authselect: sssd profile with-subid # authselect: sssd profile with-subid
%if 0%{?fedora} >= 36 %if 0%{?fedora} >= 36
Requires: authselect >= 1.4.0 Requires: authselect >= 1.4.0
@ -965,22 +996,7 @@ Custom SELinux policy module for FreeIPA
%prep %prep
# Update timestamps on the files touched by a patch, to avoid non-equal %autosetup -n freeipa-%{version}%{?rc_version} -N -p1
# .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
# To allow proper application patches to the stripped po files, strip originals # To allow proper application patches to the stripped po files, strip originals
pushd po pushd po
@ -990,10 +1006,7 @@ for i in *.po ; do
done done
popd popd
for p in %patches ; do %autopatch -p1
%__patch -p1 -i $p
UpdateTimestamps -p1 $p
done
%build %build
# PATH is workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1005235 # PATH is workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1005235
@ -1738,14 +1751,46 @@ fi
%if %{with selinux} %if %{with selinux}
%files selinux %files selinux
%{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}.pp.* %{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}.pp.*
%ghost %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename} %ghost %verify(not md5 size mode mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename}
# with selinux # with selinux
%endif %endif
%changelog %changelog
* Fri Dec 2 2022 Florence Blanc-Renaud <flo@redhat.com> - 4.10.0-8 * Wed Feb 22 2023 Florence Blanc-Renaud <flo@redhat.com> - 4.10.1-6
- Resolves: rhbz#2149274 vault interoperability with older RHEL systems is broken [rhel-9.1.0.z] - Resolves: rhbz#2169632 Backport latest test fixes in python3-ipatests
- Resolves: rhbz#2150270 ipa-client-install does not maintain server affinity during installation [rhel-9.1.0.z]
* Mon Feb 13 2023 Florence Blanc-Renaud <flo@redhat.com> - 4.10.1-5
- Resolves: rhbz#2162656 Passwordless (GSSAPI) SSH not working for subdomain
- Resolves: rhbz#2166326 Removing the last DNS type for ipa-ca does not work
- Resolves: rhbz#2167473 RFE - Add a warning note about possible performance impact of the Auto Member rebuild task
- Resolves: rhbz#2168244 requestsearchtimelimit=0 doesn't seems to be work with ipa-acme-manage pruning command
* Mon Feb 06 2023 Florence Blanc-Renaud <flo@redhat.com> - 4.10.1-4
- Resolves: rhbz#2161284 'ERROR Could not remove /tmp/tmpbkw6hawo.ipabkp' can be seen prior to 'ipa-client-install' command was successful
- Resolves: rhbz#2164403 ipa-trust-add with --range-type=ipa-ad-trust-posix fails while creating an ID range
- Resolves: rhbz#2162677 RFE: Implement support for PKI certificate and request pruning
- Resolves: rhbz#2167312 - Backport latest test fixes in python3-ipatests
* Wed Dec 21 2022 Alexander Bokovoy <abokovoy@redhat.com> - 4.10.1-3
- Rebuild against krb5 1.20.1 ABI
- Resolves: rhbz#2155425
* Fri Dec 9 2022 Florence Blanc-Renaud <flo@redhat.com> - 4.10.1-2
- Resolves: rhbz#2148887 MemberManager with groups fails
- Resolves: rhbz#2150335 idm:client is missing dependency on krb5-pkinit
* Fri Nov 25 2022 Florence Blanc-Renaud <flo@redhat.com> - 4.10.1-1
- Resolves: rhbz#2141315 [Rebase] Rebase ipa to latest 4.10.x release for RHEL 9.2
- Resolves: rhbz#2094673 ipa-client-install should just use system wide CA store and do not specify TLS_CACERT in ldap.conf
- Resolves: rhbz#2117167 After leapp upgrade on ipa-client ipa-server package installation failed. (`REQ_FULL_WITH_MEMBERS` returns object from wrong domain)
- Resolves: rhbz#2127833 Password Policy Grace login limit allows invalid maximum value
- Resolves: rhbz#2143224 [RFE] add certificate support to ipa-client instead of one time password
- Resolves: rhbz#2144736 vault interoperability with older RHEL systems is broken
- Resolves: rhbz#2148258 ipa-client-install does not maintain server affinity during installation
- Resolves: rhbz#2148379 Add warning for empty targetattr when creating ACI with RBAC
- Resolves: rhbz#2148380 OTP token sync always returns OK even with random numbers
- Resolves: rhbz#2148381 Deprecated feature idnssoaserial in IdM appears when creating reverse dns zones
- Resolves: rhbz#2148382 Introduction of URI records for kerberos breaks location functionality
* Tue Oct 25 2022 Rafael Jeffman <rjeffman@redhat.com> - 4.10.0-7 * Tue Oct 25 2022 Rafael Jeffman <rjeffman@redhat.com> - 4.10.0-7
- Resolves: rhbz#2124547 Attempt to log in as "root" user with admin's password in Web UI does not properly fail - Resolves: rhbz#2124547 Attempt to log in as "root" user with admin's password in Web UI does not properly fail