Compare commits

...

No commits in common. "c8-stream-DL1" and "stream-idm-client-rhel-8.9.0" have entirely different histories.

41 changed files with 5348 additions and 1863 deletions

3
.gitignore vendored
View File

@ -1 +1,2 @@
SOURCES/freeipa-4.9.12.tar.gz
SOURCES/freeipa-4.9.11.tar.gz
/freeipa-4.9.11.tar.gz

View File

@ -1 +0,0 @@
ea6c8a209748b4ad8d07da556f705a366b3dd6c1 SOURCES/freeipa-4.9.12.tar.gz

View File

@ -0,0 +1,41 @@
From 651e28c1fb6b86ad1fbd4ea98644e00b7042499c Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Dec 02 2022 12:21:22 +0000
Subject: updates: fix memberManager ACI to allow managers from a specified group
The original implementation of the member manager added support for both
user and group managers but left out upgrade scenario. This means when
upgrading existing installation a manager whose rights defined by the
group membership would not be able to add group members until the ACI is
fixed.
Remove old ACI and add a full one during upgrade step.
Fixes: https://pagure.io/freeipa/issue/9286
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
diff --git a/install/updates/20-aci.update b/install/updates/20-aci.update
index a168bb9..4a7ba13 100644
--- a/install/updates/20-aci.update
+++ b/install/updates/20-aci.update
@@ -141,11 +141,13 @@ add:aci:(targetattr = "usercertificate")(version 3.0;acl "selfservice:Users can
# Allow member managers to modify members of user groups
dn: cn=groups,cn=accounts,$SUFFIX
-add:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaUserGroup)")(version 3.0; acl "Allow member managers to modify members of user groups"; allow (write) userattr = "memberManager#USERDN";)
+remove:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaUserGroup)")(version 3.0; acl "Allow member managers to modify members of user groups"; allow (write) userattr = "memberManager#USERDN";)
+add:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaUserGroup)")(version 3.0; acl "Allow member managers to modify members of user groups"; allow (write) userattr = "memberManager#USERDN" or userattr = "memberManager#GROUPDN";)
# Allow member managers to modify members of host groups
dn: cn=hostgroups,cn=accounts,$SUFFIX
-add:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaHostGroup)")(version 3.0; acl "Allow member managers to modify members of host groups"; allow (write) userattr = "memberManager#USERDN";)
+remove:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaHostGroup)")(version 3.0; acl "Allow member managers to modify members of host groups"; allow (write) userattr = "memberManager#USERDN";)
+add:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaHostGroup)")(version 3.0; acl "Allow member managers to modify members of host groups"; allow (write) userattr = "memberManager#USERDN" or userattr = "memberManager#GROUPDN";)
# Hosts can add and delete their own services
dn: cn=services,cn=accounts,$SUFFIX

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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -4,20 +4,20 @@ Date: Mon, 19 Dec 2022 14:57:03 -0300
Subject: [PATCH] Revert "DNSResolver: Fix use of nameservers with ports"
This reverts commit 5e2e4664aec641886923c2bec61ce25b96edb62a.
---
ipapython/dnsutil.py | 41 -------------------------
ipatests/test_ipapython/test_dnsutil.py | 40 ------------------------
2 files changed, 81 deletions(-)
diff --git a/ipapython/dnsutil.py b/ipapython/dnsutil.py
index 58de365ab..4baeaf8cc 100644
--- a/ipapython/dnsutil.py 2023-05-19 05:12:52.471239297 -0300
+++ b/ipapython/dnsutil.py 2023-05-24 12:20:13.588867053 -0300
@@ -145,55 +145,6 @@
--- a/ipapython/dnsutil.py
+++ b/ipapython/dnsutil.py
@@ -144,47 +144,6 @@ class DNSResolver(dns.resolver.Resolver):
nameservers.remove(ipv4_loopback)
self.nameservers = nameservers
- @property
- def nameservers(self):
- return self._nameservers
-
- @nameservers.setter
- @dns.resolver.Resolver.nameservers.setter
- def nameservers(self, nameservers):
- """
- *nameservers*, a ``list`` of nameservers with optional ports:
@ -54,11 +54,7 @@ index 58de365ab..4baeaf8cc 100644
- nameservers = _nameservers
-
- # Call dns.resolver.Resolver.nameservers setter
- if hasattr(dns.resolver.Resolver, "nameservers"):
- dns.resolver.Resolver.nameservers.__set__(self, nameservers)
- else:
- # old dnspython (<2) doesn't have 'nameservers' property
- self._nameservers = nameservers
- dns.resolver.Resolver.nameservers.__set__(self, nameservers)
- # Set nameserver_ports after successfull call to setter
- self.nameserver_ports = nameserver_ports
-
@ -66,29 +62,23 @@ index 58de365ab..4baeaf8cc 100644
class DNSZoneAlreadyExists(dns.exception.DNSException):
supp_kwargs = {'zone', 'ns'}
diff --git a/ipatests/test_ipapython/test_dnsutil.py b/ipatests/test_ipapython/test_dnsutil.py
index 9070d89ad..5e7a46197 100644
index 09463c69d..5e7a46197 100644
--- a/ipatests/test_ipapython/test_dnsutil.py
+++ b/ipatests/test_ipapython/test_dnsutil.py
@@ -101,48 +101,3 @@ class TestSortURI:
@@ -101,43 +101,3 @@ class TestSortURI:
assert dnsutil.sort_prio_weight([h3, h2, h1]) == [h1, h2, h3]
assert dnsutil.sort_prio_weight([h3, h3, h3]) == [h3]
assert dnsutil.sort_prio_weight([h2, h2, h1, h1]) == [h1, h2]
-
-
-class TestDNSResolver:
- @pytest.fixture(name="res")
- def resolver(self):
- """Resolver that doesn't read /etc/resolv.conf
-
- /etc/resolv.conf is not mandatory on systems
- """
- return dnsutil.DNSResolver(configure=False)
-
- def test_nameservers(self, res):
- def test_nameservers(self):
- res = dnsutil.DNSResolver()
- res.nameservers = ["4.4.4.4", "8.8.8.8"]
- assert res.nameservers == ["4.4.4.4", "8.8.8.8"]
-
- def test_nameservers_with_ports(self, res):
- def test_nameservers_with_ports(self):
- res = dnsutil.DNSResolver()
- res.nameservers = ["4.4.4.4 port 53", "8.8.8.8 port 8053"]
- assert res.nameservers == ["4.4.4.4", "8.8.8.8"]
- assert res.nameserver_ports == {"4.4.4.4": 53, "8.8.8.8": 8053}
@ -97,7 +87,8 @@ index 9070d89ad..5e7a46197 100644
- assert res.nameservers == ["4.4.4.4", "8.8.8.8"]
- assert res.nameserver_ports == {"4.4.4.4": 53, "8.8.8.8": 8053}
-
- def test_nameservers_with_bad_ports(self, res):
- def test_nameservers_with_bad_ports(self):
- res = dnsutil.DNSResolver()
- try:
- res.nameservers = ["4.4.4.4 port a"]
- except ValueError:
@ -118,3 +109,6 @@ index 9070d89ad..5e7a46197 100644
- pass
- else:
- pytest.fail("No fail on bad port 65536")
--
2.38.1

View File

@ -1,261 +0,0 @@
From f42a106e84c1fd609350da2540289ce945a7ecbd Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Thu, 11 May 2023 10:53:58 +0200
Subject: [PATCH] user or group name: explain the supported format
The commands ipa user-add or ipa group-add validate the
format of the user/group name and display the following
message when it does not conform to the expectations:
invalid 'login': may only include letters, numbers, _, -, . and $
The format is more complex, for instance '1234567' is an invalid
user name but the failure is inconsistent with the error message.
Modify the error message to point to ipa help user/group and add
more details in the help message.
Same change for idoverrideuser and idoverridegroup:
The user/group name must follow these rules:
- cannot contain only numbers
- must start with a letter, a number, _ or .
- may contain letters, numbers, _, ., or -
- may end with a letter, a number, _, ., - or $
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2150217
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rafael Guterres Jeffman <rjeffman@redhat.com>
Reviewed-By: Alexander Bokovoy <abbra@users.noreply.github.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
ipalib/constants.py | 5 +++++
ipaserver/plugins/baseuser.py | 2 +-
ipaserver/plugins/group.py | 10 ++++++++--
ipaserver/plugins/idviews.py | 5 +++--
ipaserver/plugins/stageuser.py | 6 ++++++
ipaserver/plugins/user.py | 6 ++++++
ipatests/test_xmlrpc/test_group_plugin.py | 5 +++--
ipatests/test_xmlrpc/test_stageuser_plugin.py | 3 ++-
ipatests/test_xmlrpc/test_user_plugin.py | 7 ++++---
9 files changed, 38 insertions(+), 11 deletions(-)
diff --git a/ipalib/constants.py b/ipalib/constants.py
index 4b759a573..104419bc2 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -319,6 +319,11 @@ MAXHOSTFQDNLEN = 253
PATTERN_GROUPUSER_NAME = (
'(?!^[0-9]+$)^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*[a-zA-Z0-9_.$-]?$'
)
+ERRMSG_GROUPUSER_NAME = (
+ 'may only include letters, numbers, _, -, . and $'
+ ', refer to \'ipa help {}\' for complete format '
+ 'description'
+)
# Kerberos Anonymous principal name
ANON_USER = 'WELLKNOWN/ANONYMOUS'
diff --git a/ipaserver/plugins/baseuser.py b/ipaserver/plugins/baseuser.py
index 684a65242..bae6c54ff 100644
--- a/ipaserver/plugins/baseuser.py
+++ b/ipaserver/plugins/baseuser.py
@@ -211,7 +211,7 @@ class baseuser(LDAPObject):
takes_params = (
Str('uid',
pattern=constants.PATTERN_GROUPUSER_NAME,
- pattern_errmsg='may only include letters, numbers, _, -, . and $',
+ pattern_errmsg=constants.ERRMSG_GROUPUSER_NAME.format('user'),
maxlength=255,
cli_name='login',
label=_('User login'),
diff --git a/ipaserver/plugins/group.py b/ipaserver/plugins/group.py
index afdad93c1..0333ed622 100644
--- a/ipaserver/plugins/group.py
+++ b/ipaserver/plugins/group.py
@@ -24,7 +24,7 @@ import logging
from ipalib import api
from ipalib import Int, Str, Flag
-from ipalib.constants import PATTERN_GROUPUSER_NAME
+from ipalib.constants import PATTERN_GROUPUSER_NAME, ERRMSG_GROUPUSER_NAME
from ipalib.plugable import Registry
from .baseldap import (
add_external_post_callback,
@@ -70,6 +70,12 @@ converted to non-POSIX groups.
Every group must have a description.
+The group name must follow these rules:
+- cannot contain only numbers
+- must start with a letter, a number, _ or .
+- may contain letters, numbers, _, ., or -
+- may end with a letter, a number, _, ., - or $
+
POSIX groups must have a Group ID (GID) number. Changing a GID is
supported but can have an impact on your file permissions. It is not necessary
to supply a GID when creating a group. IPA will generate one automatically
@@ -330,7 +336,7 @@ class group(LDAPObject):
takes_params = (
Str('cn',
pattern=PATTERN_GROUPUSER_NAME,
- pattern_errmsg='may only include letters, numbers, _, -, . and $',
+ pattern_errmsg=ERRMSG_GROUPUSER_NAME.format('group'),
maxlength=255,
cli_name='group_name',
label=_('Group name'),
diff --git a/ipaserver/plugins/idviews.py b/ipaserver/plugins/idviews.py
index 4f4b3a2f7..6a16884cf 100644
--- a/ipaserver/plugins/idviews.py
+++ b/ipaserver/plugins/idviews.py
@@ -37,6 +37,7 @@ from ipalib.constants import (
IPA_ANCHOR_PREFIX,
SID_ANCHOR_PREFIX,
PATTERN_GROUPUSER_NAME,
+ ERRMSG_GROUPUSER_NAME
)
from ipalib.plugable import Registry
from ipalib.util import (normalize_sshpubkey, validate_sshpubkey,
@@ -1025,7 +1026,7 @@ class idoverrideuser(baseidoverride):
takes_params = baseidoverride.takes_params + (
Str('uid?',
pattern=PATTERN_GROUPUSER_NAME,
- pattern_errmsg='may only include letters, numbers, _, -, . and $',
+ pattern_errmsg=ERRMSG_GROUPUSER_NAME.format('user'),
maxlength=255,
cli_name='login',
label=_('User login'),
@@ -1128,7 +1129,7 @@ class idoverridegroup(baseidoverride):
takes_params = baseidoverride.takes_params + (
Str('cn?',
pattern=PATTERN_GROUPUSER_NAME,
- pattern_errmsg='may only include letters, numbers, _, -, . and $',
+ pattern_errmsg=ERRMSG_GROUPUSER_NAME.format('group'),
maxlength=255,
cli_name='group_name',
label=_('Group name'),
diff --git a/ipaserver/plugins/stageuser.py b/ipaserver/plugins/stageuser.py
index 760dff7ab..51438a83a 100644
--- a/ipaserver/plugins/stageuser.py
+++ b/ipaserver/plugins/stageuser.py
@@ -94,6 +94,12 @@ usernames that start with a digit or usernames that exceed a certain length
may cause problems for some UNIX systems.
Use 'ipa config-mod' to change the username format allowed by IPA tools.
+The user name must follow these rules:
+- cannot contain only numbers
+- must start with a letter, a number, _ or .
+- may contain letters, numbers, _, ., or -
+- may end with a letter, a number, _, ., - or $
+
EXAMPLES:
diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py
index fa8a67d3d..643b44f14 100644
--- a/ipaserver/plugins/user.py
+++ b/ipaserver/plugins/user.py
@@ -88,6 +88,12 @@ usernames that start with a digit or usernames that exceed a certain length
may cause problems for some UNIX systems.
Use 'ipa config-mod' to change the username format allowed by IPA tools.
+The user name must follow these rules:
+- cannot contain only numbers
+- must start with a letter, a number, _ or .
+- may contain letters, numbers, _, ., or -
+- may end with a letter, a number, _, ., - or $
+
Disabling a user account prevents that user from obtaining new Kerberos
credentials. It does not invalidate any credentials that have already
been issued.
diff --git a/ipatests/test_xmlrpc/test_group_plugin.py b/ipatests/test_xmlrpc/test_group_plugin.py
index f9a0e2cfe..27bc21fbc 100644
--- a/ipatests/test_xmlrpc/test_group_plugin.py
+++ b/ipatests/test_xmlrpc/test_group_plugin.py
@@ -25,6 +25,7 @@ Test the `ipaserver/plugins/group.py` module.
import pytest
from ipalib import errors
+from ipalib.constants import ERRMSG_GROUPUSER_NAME
from ipatests.test_xmlrpc import objectclasses
from ipatests.test_xmlrpc.xmlrpc_test import (
fuzzy_digits, fuzzy_uuid, fuzzy_set_ci,
@@ -169,7 +170,7 @@ class TestGroup(XMLRPC_test):
)
with raises_exact(errors.ValidationError(
name='group_name',
- error=u'may only include letters, numbers, _, -, . and $')):
+ error=ERRMSG_GROUPUSER_NAME.format('group'))):
command()
def test_create_with_name_starting_with_numeric(self):
@@ -188,7 +189,7 @@ class TestGroup(XMLRPC_test):
)
with raises_exact(errors.ValidationError(
name='group_name',
- error=u'may only include letters, numbers, _, -, . and $',
+ error=ERRMSG_GROUPUSER_NAME.format('group'),
)):
testgroup.create()
diff --git a/ipatests/test_xmlrpc/test_stageuser_plugin.py b/ipatests/test_xmlrpc/test_stageuser_plugin.py
index fd146876c..bd877aa94 100644
--- a/ipatests/test_xmlrpc/test_stageuser_plugin.py
+++ b/ipatests/test_xmlrpc/test_stageuser_plugin.py
@@ -12,6 +12,7 @@ import six
from collections import OrderedDict
from ipalib import api, errors
+from ipalib.constants import ERRMSG_GROUPUSER_NAME
from ipaplatform.constants import constants as platformconstants
from ipatests.test_xmlrpc.xmlrpc_test import XMLRPC_test, raises_exact
@@ -357,7 +358,7 @@ class TestCreateInvalidAttributes(XMLRPC_test):
command = invalid.make_create_command()
with raises_exact(errors.ValidationError(
name='login',
- error=u"may only include letters, numbers, _, -, . and $")):
+ error=ERRMSG_GROUPUSER_NAME.format('user'))):
command()
def test_create_long_uid(self):
diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py
index c156a8793..eadfe6a65 100644
--- a/ipatests/test_xmlrpc/test_user_plugin.py
+++ b/ipatests/test_xmlrpc/test_user_plugin.py
@@ -31,6 +31,7 @@ import ldap
import re
from ipalib import api, errors
+from ipalib.constants import ERRMSG_GROUPUSER_NAME
from ipaplatform.constants import constants as platformconstants
from ipapython import ipautil
from ipatests.test_xmlrpc import objectclasses
@@ -502,7 +503,7 @@ class TestUpdate(XMLRPC_test):
)
with raises_exact(errors.ValidationError(
name='rename',
- error=u'may only include letters, numbers, _, -, . and $')):
+ error=ERRMSG_GROUPUSER_NAME.format('user'))):
command()
def test_add_radius_username(self, user):
@@ -556,7 +557,7 @@ class TestCreate(XMLRPC_test):
command = testuser.make_create_command()
with raises_exact(errors.ValidationError(
name=u'login',
- error=u'may only include letters, numbers, _, -, . and $')):
+ error=ERRMSG_GROUPUSER_NAME.format('user'))):
command()
def test_create_with_too_long_login(self):
@@ -730,7 +731,7 @@ class TestCreate(XMLRPC_test):
)
with raises_exact(errors.ValidationError(
name=u'login',
- error=u'may only include letters, numbers, _, -, . and $',
+ error=ERRMSG_GROUPUSER_NAME.format('user'),
)):
testuser.create()
--
2.40.1

View File

@ -1,242 +0,0 @@
From 9fe30f21c987bdccf80ef5f6d645fdc59b393bdb Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Jun 16 2023 19:09:52 +0000
Subject: Revert "Use the OpenSSL certificate parser in cert-find"
This reverts commit 191880bc9f77c3e8a3cecc82e6eea33ab5ad03e4.
The problem isn't with python-cryptography, it is with the
IPACertificate class which does way more work on a certificate
than is necessary in cert-find.
Related: https://pagure.io/freeipa/issue/9331
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
---
diff --git a/freeipa.spec.in b/freeipa.spec.in
index f3380b4..2b18963 100755
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -390,7 +390,6 @@ BuildRequires: python3-pylint
BuildRequires: python3-pytest-multihost
BuildRequires: python3-pytest-sourceorder
BuildRequires: python3-qrcode-core >= 5.0.0
-BuildRequires: python3-pyOpenSSL
BuildRequires: python3-samba
BuildRequires: python3-six
BuildRequires: python3-sss
@@ -862,7 +861,6 @@ Requires: python3-netifaces >= 0.10.4
Requires: python3-pyasn1 >= 0.3.2-2
Requires: python3-pyasn1-modules >= 0.3.2-2
Requires: python3-pyusb
-Requires: python3-pyOpenSSL
Requires: python3-qrcode-core >= 5.0.0
Requires: python3-requests
Requires: python3-six
diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py
index cec3d93..88c6b62 100644
--- a/ipaserver/plugins/cert.py
+++ b/ipaserver/plugins/cert.py
@@ -30,7 +30,6 @@ import cryptography.x509
from cryptography.hazmat.primitives import hashes, serialization
from dns import resolver, reversename
import six
-import sys
from ipalib import Command, Str, Int, Flag, StrEnum
from ipalib import api
@@ -1623,19 +1622,7 @@ class cert_find(Search, CertMethod):
)
def _get_cert_key(self, cert):
- # for cert-find with a certificate value
- if isinstance(cert, x509.IPACertificate):
- return (DN(cert.issuer), cert.serial_number)
-
- issuer = []
- for oid, value in cert.get_issuer().get_components():
- issuer.append(
- '{}={}'.format(oid.decode('utf-8'), value.decode('utf-8'))
- )
- issuer = ','.join(issuer)
- # Use this to flip from OpenSSL reverse to X500 ordering
- issuer = DN(issuer).x500_text()
- return (DN(issuer), cert.get_serial_number())
+ return (DN(cert.issuer), cert.serial_number)
def _cert_search(self, pkey_only, **options):
result = collections.OrderedDict()
@@ -1755,11 +1742,6 @@ class cert_find(Search, CertMethod):
return result, False, complete
def _ldap_search(self, all, pkey_only, no_members, **options):
- # defer import of the OpenSSL module to not affect the requests
- # module which will use pyopenssl if this is available.
- if sys.modules.get('OpenSSL.SSL', False) is None:
- del sys.modules["OpenSSL.SSL"]
- import OpenSSL.crypto
ldap = self.api.Backend.ldap2
filters = []
@@ -1818,14 +1800,12 @@ class cert_find(Search, CertMethod):
ca_enabled = getattr(context, 'ca_enabled')
for entry in entries:
for attr in ('usercertificate', 'usercertificate;binary'):
- for der in entry.raw.get(attr, []):
- cert = OpenSSL.crypto.load_certificate(
- OpenSSL.crypto.FILETYPE_ASN1, der)
+ for cert in entry.get(attr, []):
cert_key = self._get_cert_key(cert)
try:
obj = result[cert_key]
except KeyError:
- obj = {'serial_number': cert.get_serial_number()}
+ obj = {'serial_number': cert.serial_number}
if not pkey_only and (all or not ca_enabled):
# Retrieving certificate details is now deferred
# until after all certificates are collected.
From 3b1dbcdba2994bf57908f530913998e9ab888e4c Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Jun 16 2023 19:09:52 +0000
Subject: Revert "cert_find: fix call with --all"
This reverts commit 1f30cc65276a532e7288217f216b72a2b0628c8f.
The problem isn't with python-cryptography, it is with the
IPACertificate class which does way more work on a certificate
than is necessary in cert-find.
Related: https://pagure.io/freeipa/issue/9331
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
---
diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py
index 88c6b62..ba37525 100644
--- a/ipaserver/plugins/cert.py
+++ b/ipaserver/plugins/cert.py
@@ -1812,7 +1812,6 @@ class cert_find(Search, CertMethod):
# For the case of CA-less we need to keep
# the certificate because getting it again later
# would require unnecessary LDAP searches.
- cert = cert.to_cryptography()
obj['certificate'] = (
base64.b64encode(
cert.public_bytes(x509.Encoding.DER))
From d00fd3398c32beb2c3e72f4878c87f9d2c0e833d Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Jun 16 2023 19:09:52 +0000
Subject: Use the python-cryptography parser directly in cert-find
cert-find is a rather complex beast because it not only
looks for certificates in the optional CA but within the
IPA LDAP database as well. It has a process to deduplicate
the certificates since any PKI issued certificates will
also be associated with an IPA record.
In order to obtain the data to deduplicate the certificates
the cert from LDAP must be parser for issuer and serial number.
ipaldap has automation to determine the datatype of an
attribute and will use the ipalib.x509 IPACertificate class to
decode a certificate automatically if you access
entry['usercertificate'].
The downside is that this is comparatively slow. Here is the
parse time in microseconds:
cryptography 0.0081
OpenSSL.crypto 0.2271
ipalib.x509 2.6814
Since only issuer and subject are required there is no need to
make the expensive IPACertificate call.
The IPACertificate parsing time is fine if you're parsing one
certificate but if the LDAP search returns a lot of certificates,
say in the thousands, then those microseconds add up quickly.
In testing it took ~17 seconds to parse 5k certificates (excluding
transmission overhead, etc).
cert-find when there are a lot of certificates has been
historically slow. It isn't related to the CA which returns
large sets (well, 5k anyway) in a second or two. It was the
LDAP comparision adding tens of seconds to the runtime.
When searching with the default sizelimit of 100 the time is
~10s without this patch. With it the time is 1.5s.
CLI times from before and after searching for all certs:
original:
-------------------------------
Number of entries returned 5038
-------------------------------
real 0m15.507s
user 0m0.828s
sys 0m0.241s
using cryptography:
real 0m4.037s
user 0m0.816s
sys 0m0.193s
Fixes: https://pagure.io/freeipa/issue/9331
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
---
diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py
index ba37525..619be83 100644
--- a/ipaserver/plugins/cert.py
+++ b/ipaserver/plugins/cert.py
@@ -1800,7 +1800,8 @@ class cert_find(Search, CertMethod):
ca_enabled = getattr(context, 'ca_enabled')
for entry in entries:
for attr in ('usercertificate', 'usercertificate;binary'):
- for cert in entry.get(attr, []):
+ for der in entry.raw.get(attr, []):
+ cert = cryptography.x509.load_der_x509_certificate(der)
cert_key = self._get_cert_key(cert)
try:
obj = result[cert_key]
diff --git a/ipatests/test_xmlrpc/test_cert_plugin.py b/ipatests/test_xmlrpc/test_cert_plugin.py
index 433cebc..583c67f 100644
--- a/ipatests/test_xmlrpc/test_cert_plugin.py
+++ b/ipatests/test_xmlrpc/test_cert_plugin.py
@@ -254,6 +254,16 @@ class test_cert(BaseCert):
result = _emails_are_valid(email_addrs, [])
assert not result
+ def test_00012_cert_find_all(self):
+ """
+ Test that cert-find --all returns successfully.
+
+ We don't know how many we'll get but there should be at least 10
+ by default.
+ """
+ res = api.Command['cert_find'](all=True)
+ assert 'count' in res and res['count'] >= 10
+
def test_99999_cleanup(self):
"""
Clean up cert test data
@@ -283,7 +293,7 @@ class test_cert_find(XMLRPC_test):
short = api.env.host.split('.', maxsplit=1)[0]
- def test_0001_find_all(self):
+ def test_0001_find_all_certs(self):
"""
Search for all certificates.

View File

@ -1,87 +0,0 @@
From 86c1426b2d376a390e87b074d3e10d85fa124abf Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Jun 21 2023 17:02:48 +0000
Subject: Upgrade: add PKI drop-in file if missing
During the installation of IPA server, the installer adds a drop-in
file in /etc/systemd/system/pki-tomcatd@pki-tomcat.service.d/ipa.conf
that ensures the CA is reachable before the start command returns.
If the file is missing (for instance because the server was installed
with an old version before this drop-in was created), the upgrade
should add the file.
Fixes: https://pagure.io/freeipa/issue/9381
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index dd22ac2..e4dc7ae 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -1737,6 +1737,10 @@ def upgrade_configuration():
os.path.join(paths.USR_SHARE_IPA_DIR,
"ipa-kdc-proxy.conf.template"))
if ca.is_configured():
+ # Ensure that the drop-in file is present
+ if not os.path.isfile(paths.SYSTEMD_PKI_TOMCAT_IPA_CONF):
+ ca.add_ipa_wait()
+
# Handle upgrade of AJP connector configuration
rewrite = ca.secure_ajp_connector()
if ca.ajp_secret:
From 356ec5cbfe0876686239f938bdf54892dc30571e Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Jun 21 2023 17:02:48 +0000
Subject: Integration test: add a test for upgrade and PKI drop-in file
Add an upgrade test with the following scenario:
- remove PKI drop-in file (to simulate an upgrade from an old
version)
- remove caECServerCertWithSCT profile from LDAP
- launch the ipa-server-upgrade command
- check that the upgrade added the file
Related: https://pagure.io/freeipa/issue/9381
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
diff --git a/ipatests/test_integration/test_upgrade.py b/ipatests/test_integration/test_upgrade.py
index 9203503..182e3b5 100644
--- a/ipatests/test_integration/test_upgrade.py
+++ b/ipatests/test_integration/test_upgrade.py
@@ -455,3 +455,25 @@ class TestUpgrade(IntegrationTest):
assert 'tXTRecord' in location_krb_rec
assert len(location_krb_rec['tXTRecord']) == 1
assert location_krb_rec['tXTRecord'][0] == f'"{realm}"'
+
+ def test_pki_dropin_file(self):
+ """Test that upgrade adds the drop-in file if missing
+
+ Test for ticket 9381
+ Simulate an update from a version that didn't provide
+ /etc/systemd/system/pki-tomcatd@pki-tomcat.service.d/ipa.conf,
+ remove one of the certificate profiles from LDAP and check that upgrade
+ completes successfully and adds the missing file.
+ When the drop-in file is missing, the upgrade tries to login to
+ PKI in order to migrate the profile and fails because PKI failed to
+ start.
+ """
+ self.master.run_command(["rm", "-f", paths.SYSTEMD_PKI_TOMCAT_IPA_CONF])
+ ldif = textwrap.dedent("""
+ dn: cn=caECServerCertWithSCT,ou=certificateProfiles,ou=ca,o=ipaca
+ changetype: delete
+ """)
+ tasks.ldapmodify_dm(self.master, ldif)
+ self.master.run_command(['ipa-server-upgrade'])
+ assert self.master.transport.file_exists(
+ paths.SYSTEMD_PKI_TOMCAT_IPA_CONF)

View File

@ -1,233 +0,0 @@
From d29b47512a39ada02fb371521994576cd9815a6c Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Mon, 19 Jun 2023 10:36:29 +0200
Subject: [PATCH] Upgrade: fix replica agreement
The upgrade checks the replication agreements to ensure that
some attributes are excluded from replication. The agreements
are stored in entries like
cn=serverToreplica,cn=replica,cn=_suffix_,cn=mapping tree,cn=config
but those entries are managed by the replication topology plugin
and should not be updated directly. The consequence is that the update
of the attributes fails and ipa-server-update prints an error message:
Error caught updating nsDS5ReplicatedAttributeList: Server is unwilling
to perform: Entry and attributes are managed by topology plugin.No direct
modifications allowed.
Error caught updating nsDS5ReplicatedAttributeListTotal: Server is
unwilling to perform: Entry and attributes are managed by topology
plugin.No direct modifications allowed.
The upgrade continues but the replication is not excluding
passwordgraceusertime.
Instead of editing the agreements, perform the modifications on
the topology segments.
Fixes: https://pagure.io/freeipa/issue/9385
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
.../install/plugins/fix_replica_agreements.py | 80 +++++++++----------
1 file changed, 38 insertions(+), 42 deletions(-)
diff --git a/ipaserver/install/plugins/fix_replica_agreements.py b/ipaserver/install/plugins/fix_replica_agreements.py
index c0cdd3eb1..d963753d0 100644
--- a/ipaserver/install/plugins/fix_replica_agreements.py
+++ b/ipaserver/install/plugins/fix_replica_agreements.py
@@ -22,6 +22,7 @@ import logging
from ipaserver.install import replication
from ipalib import Registry
from ipalib import Updater
+from ipalib import errors
logger = logging.getLogger(__name__)
@@ -41,35 +42,42 @@ class update_replica_attribute_lists(Updater):
def execute(self, **options):
# We need an LDAPClient connection to the backend
logger.debug("Start replication agreement exclude list update task")
- conn = self.api.Backend.ldap2
- repl = replication.ReplicationManager(self.api.env.realm,
- self.api.env.host,
- None, conn=conn)
-
- # We need to update only IPA replica agreements, not winsync
- ipa_replicas = repl.find_ipa_replication_agreements()
-
- logger.debug("Found %d agreement(s)", len(ipa_replicas))
-
- for replica in ipa_replicas:
- for desc in replica.get('description', []):
- logger.debug('%s', desc)
-
- self._update_attr(repl, replica,
- 'nsDS5ReplicatedAttributeList',
- replication.EXCLUDES, template=EXCLUDE_TEMPLATE)
- self._update_attr(repl, replica,
- 'nsDS5ReplicatedAttributeListTotal',
- replication.TOTAL_EXCLUDES, template=EXCLUDE_TEMPLATE)
- self._update_attr(repl, replica,
- 'nsds5ReplicaStripAttrs', replication.STRIP_ATTRS)
+ # Find suffixes
+ suffixes = self.api.Command.topologysuffix_find()['result']
+ for suffix in suffixes:
+ suffix_name = suffix['cn'][0]
+ # Find segments
+ sgmts = self.api.Command.topologysegment_find(
+ suffix_name, all=True)['result']
+ for segment in sgmts:
+ updates = {}
+ updates = self._update_attr(
+ segment, updates,
+ 'nsds5replicatedattributelist',
+ replication.EXCLUDES, template=EXCLUDE_TEMPLATE)
+ updates = self._update_attr(
+ segment, updates,
+ 'nsds5replicatedattributelisttotal',
+ replication.TOTAL_EXCLUDES, template=EXCLUDE_TEMPLATE)
+ updates = self._update_attr(
+ segment, updates,
+ 'nsds5replicastripattrs', replication.STRIP_ATTRS)
+ if updates:
+ try:
+ self.api.Command.topologysegment_mod(
+ suffix_name, segment['cn'][0],
+ **updates)
+ except errors.EmptyModlist:
+ # No update done
+ logger.debug("No update required for the segment %s",
+ segment['cn'][0])
logger.debug("Done updating agreements")
return False, [] # No restart, no updates
- def _update_attr(self, repl, replica, attribute, values, template='%s'):
+ def _update_attr(self, segment, updates, attribute, values, template='%s'):
"""Add or update an attribute of a replication agreement
If the attribute doesn't already exist, it is added and set to
@@ -77,27 +85,21 @@ class update_replica_attribute_lists(Updater):
If the attribute does exist, `values` missing from it are just
appended to the end, also space-separated.
- :param repl: Replication manager
- :param replica: Replica agreement
+ :param: updates: dict containing the updates
+ :param segment: dict containing segment information
:param attribute: Attribute to add or update
:param values: List of values the attribute should hold
:param template: Template to use when adding attribute
"""
- attrlist = replica.single_value.get(attribute)
+ attrlist = segment.get(attribute)
if attrlist is None:
logger.debug("Adding %s", attribute)
# Need to add it altogether
- replica[attribute] = [template % " ".join(values)]
-
- try:
- repl.conn.update_entry(replica)
- logger.debug("Updated")
- except Exception as e:
- logger.error("Error caught updating replica: %s", str(e))
+ updates[attribute] = template % " ".join(values)
else:
- attrlist_normalized = attrlist.lower().split()
+ attrlist_normalized = attrlist[0].lower().split()
missing = [a for a in values
if a.lower() not in attrlist_normalized]
@@ -105,14 +107,8 @@ class update_replica_attribute_lists(Updater):
logger.debug("%s needs updating (missing: %s)", attribute,
', '.join(missing))
- replica[attribute] = [
- '%s %s' % (attrlist, ' '.join(missing))]
+ updates[attribute] = '%s %s' % (attrlist[0], ' '.join(missing))
- try:
- repl.conn.update_entry(replica)
- logger.debug("Updated %s", attribute)
- except Exception as e:
- logger.error("Error caught updating %s: %s",
- attribute, str(e))
else:
logger.debug("%s: No update necessary", attribute)
+ return updates
--
2.41.0
From 93d97b59600c15e5028ee39b0e98450544165158 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Mon, 19 Jun 2023 10:36:59 +0200
Subject: [PATCH] Integration tests: add a test to ipa-server-upgrade
Add an integration test ensuring that the upgrade
properly updates the attributes to be excluded from
replication.
Related: https://pagure.io/freeipa/issue/9385
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
.../test_simple_replication.py | 30 +++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/ipatests/test_integration/test_simple_replication.py b/ipatests/test_integration/test_simple_replication.py
index 17092a499..d1e65ef7c 100644
--- a/ipatests/test_integration/test_simple_replication.py
+++ b/ipatests/test_integration/test_simple_replication.py
@@ -23,8 +23,10 @@ import pytest
from ipaplatform.paths import paths
from ipapython.dn import DN
+from ipaserver.install.replication import EXCLUDES
from ipatests.pytest_ipa.integration import tasks
from ipatests.test_integration.base import IntegrationTest
+from ipatests.test_integration.test_topology import find_segment
def check_replication(source_host, dest_host, login):
@@ -104,6 +106,34 @@ class TestSimpleReplication(IntegrationTest):
[paths.IPA_CUSTODIA_CHECK, self.master.hostname]
)
+ def test_fix_agreements(self):
+ """Test that upgrade fixes the list of attributes excluded from repl
+
+ Test for ticket 9385
+ """
+ # Prepare the server by removing some values from
+ # from the nsDS5ReplicatedAttributeList
+ segment = find_segment(self.master, self.replicas[0], "domain")
+ self.master.run_command([
+ "ipa", "topologysegment-mod", "domain", segment,
+ "--replattrs",
+ "(objectclass=*) $ EXCLUDE memberof idnssoaserial entryusn"])
+ # Run the upgrade
+ result = self.master.run_command(["ipa-server-upgrade"])
+ # Ensure that the upgrade updated the attribute without error
+ errmsg = "Error caught updating nsDS5ReplicatedAttributeList"
+ assert errmsg not in result.stdout_text
+ # Check the updated value
+ suffix = DN(self.master.domain.basedn)
+ dn = DN(('cn', str(suffix)), ('cn', 'mapping tree'), ('cn', 'config'))
+ result = tasks.ldapsearch_dm(self.master, str(dn),
+ ["nsDS5ReplicatedAttributeList"])
+ output = result.stdout_text.lower()
+
+ template = 'nsDS5ReplicatedAttributeList: (objectclass=*) $ EXCLUDE %s'
+ expected_value = template % " ".join(EXCLUDES)
+ assert expected_value.lower() in output
+
def test_replica_removal(self):
"""Test replica removal"""
result = self.master.run_command(['ipa-replica-manage', 'list'])
--
2.41.0

View File

@ -1,52 +0,0 @@
From a7e167154b889f75463ccc9cd91a75c1afb22da9 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Jun 28 2023 19:43:16 +0000
Subject: OTP: fix data type to avoid endianness issue
When 389-ds process an OTP authentication, the ipa-pwd-extop
plugin reads a buffer to extract the authentication type.
The type is stored in an int but the data is a ber_tag_t.
On big endian machines the type cast does not cause any issue
but on s390x the buffer that should return 128 is seen as 0.
As a consequence, the plugin considers that the method is not
LDAP_AUTH_SIMPLE and exits early, without processing the OTP.
The fix is simple and consists in using the right type
(ber_tag_t is an unsigned long).
Fixes: https://pagure.io/freeipa/issue/9402
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
index 9375941..4562652 100644
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
@@ -1433,7 +1433,7 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
Slapi_DN *target_sdn = NULL;
Slapi_DN *sdn = NULL;
const char *dn = NULL;
- int method = 0;
+ ber_tag_t method = 0;
bool syncreq;
bool otpreq;
int ret = 0;
@@ -1454,8 +1454,10 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
}
/* We're only interested in simple authentication. */
- if (method != LDAP_AUTH_SIMPLE || credentials->bv_len == 0)
+ if (method != LDAP_AUTH_SIMPLE || credentials->bv_len == 0) {
+ LOG("Not handled (not simple bind or NULL dn/credentials)\n");
return 0;
+ }
/* Retrieve the user's entry. */
sdn = slapi_sdn_dup(target_sdn);

View File

@ -1,173 +0,0 @@
From 7a94acca6a9efb546f1cf59f63fcb89f98944ea5 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Thu, 25 May 2023 08:16:33 +0200
Subject: [PATCH] ACME tests: fix issue_and_expire_acme_cert method
The fixture issue_and_expire_acme_cert is changing the date
on master and client. It also resets the admin password as
it gets expired after the date change.
Currently the code is resetting the password by performing
kinit on the client, which leaves the master with an expired
ticket in its cache. Reset the password on the master instead
in order to have a valid ticket for the next operations.
Fixes: https://pagure.io/freeipa/issue/9383
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Mohammad Rizwan <myusuf@redhat.com>
---
ipatests/test_integration/test_acme.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/ipatests/test_integration/test_acme.py b/ipatests/test_integration/test_acme.py
index c73f441fc..c69e810da 100644
--- a/ipatests/test_integration/test_acme.py
+++ b/ipatests/test_integration/test_acme.py
@@ -583,20 +583,20 @@ class TestACMERenew(IntegrationTest):
tasks.kdestroy_all(host)
tasks.move_date(host, 'stop', '+90days')
- tasks.get_kdcinfo(host)
+ tasks.get_kdcinfo(self.master)
# Note raiseonerr=False:
# the assert is located after kdcinfo retrieval.
# run kinit command repeatedly until sssd gets settle
# after date change
tasks.run_repeatedly(
- host, "KRB5_TRACE=/dev/stdout kinit admin",
+ self.master, "KRB5_TRACE=/dev/stdout kinit admin",
stdin_text='{0}\n{0}\n{0}\n'.format(
- self.clients[0].config.admin_password
+ self.master.config.admin_password
)
)
# Retrieve kdc.$REALM after the password change, just in case SSSD
# domain status flipped to online during the password change.
- tasks.get_kdcinfo(host)
+ tasks.get_kdcinfo(self.master)
yield
--
2.41.0
From 998bafee86a870ad1ea4d6bccf12f0fae64c398c Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Wed, 31 May 2023 11:50:14 +0200
Subject: [PATCH] ipatest: remove xfail from test_smb
test_smb is now successful because the windows server version
has been updated to windows-server-2022 with
- KB5012170
- KB5025230
- KB5022507
- servicing stack 10.0.20348.1663
in freeipa-pr-ci commit 3ba4151.
Remove the xfail.
Fixes: https://pagure.io/freeipa/issue/9124
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Mohammad Rizwan <myusuf@redhat.com>
---
ipatests/test_integration/test_smb.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/ipatests/test_integration/test_smb.py b/ipatests/test_integration/test_smb.py
index 30f8d5901..eb3981bdd 100644
--- a/ipatests/test_integration/test_smb.py
+++ b/ipatests/test_integration/test_smb.py
@@ -349,7 +349,6 @@ 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.41.0
From 1b51fa4cb07380d1102891233e85a7940f804c72 Mon Sep 17 00:00:00 2001
From: Anuja More <amore@redhat.com>
Date: Thu, 11 May 2023 12:50:10 +0530
Subject: [PATCH] ipatests: Check that SSSD_PUBCONF_KRB5_INCLUDE_D_DIR is not
included in krb5.conf
SSSD already provides a config snippet which includes
SSSD_PUBCONF_KRB5_INCLUDE_D_DIR, and having both breaks Java.
Test checks that krb5.conf does not include
SSSD_PUBCONF_KRB5_INCLUDE_D_DIR.
Related: https://pagure.io/freeipa/issue/9267
Signed-off-by: Anuja More <amore@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
.../test_integration/test_installation_client.py | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/ipatests/test_integration/test_installation_client.py b/ipatests/test_integration/test_installation_client.py
index 014b0f6ab..56e1593bf 100644
--- a/ipatests/test_integration/test_installation_client.py
+++ b/ipatests/test_integration/test_installation_client.py
@@ -76,6 +76,21 @@ class TestInstallClient(IntegrationTest):
result = self.clients[0].run_command(['cat', '/etc/ssh/ssh_config'])
assert 'HostKeyAlgorithms' not in result.stdout_text
+ def test_client_install_with_krb5(self):
+ """Test that SSSD_PUBCONF_KRB5_INCLUDE_D_DIR is not added in krb5.conf
+
+ SSSD already provides a config snippet which includes
+ SSSD_PUBCONF_KRB5_INCLUDE_D_DIR, and having both breaks Java.
+ Test checks that krb5.conf does not include
+ SSSD_PUBCONF_KRB5_INCLUDE_D_DIR.
+
+ related: https://pagure.io/freeipa/issue/9267
+ """
+ krb5_cfg = self.master.get_file_contents(paths.KRB5_CONF)
+ assert 'includedir {dir}'.format(
+ dir=paths.SSSD_PUBCONF_KRB5_INCLUDE_D_DIR
+ ).encode() not in krb5_cfg
+
class TestClientInstallBind(IntegrationTest):
"""
--
2.41.0
From f599e2d67bad5945e4dcf99fdd584f01f1e20d1e Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Tue, 6 Jun 2023 09:04:48 +0200
Subject: [PATCH] webuitests: close notification which hides Add button
The webui test test_service.py::test_service::test_arbitrary_certificates
randomly fails.
The test is creating a new service then navigates to the Service page
and clicks on the Add Certificate button.
The notification area may still be present and hide the button, with
the message "Service successfully added".
Close all notifications before navigating to the Service page.
Fixes: https://pagure.io/freeipa/issue/9389
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Michal Polovka <mpolovka@redhat.com>
---
ipatests/test_webui/test_service.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/ipatests/test_webui/test_service.py b/ipatests/test_webui/test_service.py
index f1d9a9d62..e2976d73a 100644
--- a/ipatests/test_webui/test_service.py
+++ b/ipatests/test_webui/test_service.py
@@ -296,6 +296,7 @@ class test_service(sevice_tasks):
cert_widget_sel = "div.certificate-widget"
self.add_record(ENTITY, data)
+ self.close_notifications()
self.navigate_to_record(pkey)
# check whether certificate section is present
--
2.41.0

View File

@ -1,85 +0,0 @@
From b5793c854035a122ed4c66f917cc427e5024e46a Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Aug 02 2023 11:52:30 +0000
Subject: ipa-kdb: fix error handling of is_master_host()
Adding proper error handling to the is_master_host() function to allow
it to make the difference between the absence of a master host object
and a connection failure. This will keep the krb5kdc daemon from
continuing to run with a NULL LDAP context.
Fixes: https://pagure.io/freeipa/issue/9422
Signed-off-by: Julien Rische <jrische@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
---
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
index 8da7543..83cb991 100644
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
@@ -401,27 +401,29 @@ static krb5_error_code ipadb_add_asserted_identity(struct ipadb_context *ipactx,
return 0;
}
-static bool is_master_host(struct ipadb_context *ipactx, const char *fqdn)
+static krb5_error_code
+is_master_host(struct ipadb_context *ipactx, const char *fqdn, bool *result)
{
- int ret;
+ int err;
char *master_host_base = NULL;
- LDAPMessage *result = NULL;
- krb5_error_code err;
+ LDAPMessage *ldap_res = NULL;
- ret = asprintf(&master_host_base, "cn=%s,cn=masters,cn=ipa,cn=etc,%s",
+ err = asprintf(&master_host_base, "cn=%s,cn=masters,cn=ipa,cn=etc,%s",
fqdn, ipactx->base);
- if (ret == -1) {
- return false;
- }
+ if (err == -1)
+ return ENOMEM;
+
err = ipadb_simple_search(ipactx, master_host_base, LDAP_SCOPE_BASE,
- NULL, NULL, &result);
+ NULL, NULL, &ldap_res);
free(master_host_base);
- ldap_msgfree(result);
- if (err == 0) {
- return true;
- }
+ ldap_msgfree(ldap_res);
+ if (err != KRB5_KDB_NOENTRY && err != 0)
+ return err;
+
+ if (result)
+ *result = err != KRB5_KDB_NOENTRY;
- return false;
+ return 0;
}
static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
@@ -692,9 +694,14 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
if ((is_host || is_service)) {
/* it is either host or service, so get the hostname first */
char *sep = strchr(info3->base.account_name.string, '/');
- bool is_master = is_master_host(
- ipactx,
- sep ? sep + 1 : info3->base.account_name.string);
+ bool is_master;
+
+ ret = is_master_host(ipactx,
+ sep ? sep + 1 : info3->base.account_name.string,
+ &is_master);
+ if (ret)
+ return ret;
+
if (is_master) {
/* Well known RID of domain controllers group */
if (info3->base.rid == 0) {

View File

@ -1,39 +0,0 @@
From f68468718c1e01df4a9180e17d7e24d961850e19 Mon Sep 17 00:00:00 2001
From: Mohammad Rizwan <myusuf@redhat.com>
Date: Wed, 14 Jun 2023 17:32:02 +0530
Subject: [PATCH] ipatests: enable firewall rule for http service on acme
client
when system hardning done i.e in case of STIG, sometimes http challanges
can't be validated by CA if port 80 is not open. This fix enable it to facilitate
the communication.
Signed-off-by: Mohammad Rizwan <myusuf@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
---
ipatests/test_integration/test_acme.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/ipatests/test_integration/test_acme.py b/ipatests/test_integration/test_acme.py
index c69e810da70..414fae8d751 100644
--- a/ipatests/test_integration/test_acme.py
+++ b/ipatests/test_integration/test_acme.py
@@ -10,6 +10,7 @@
from ipalib.constants import IPA_CA_RECORD
from ipatests.test_integration.base import IntegrationTest
+from ipatests.pytest_ipa.integration.firewall import Firewall
from ipatests.pytest_ipa.integration import tasks
from ipatests.test_integration.test_caless import CALessBase, ipa_certs_cleanup
from ipaplatform.osinfo import osinfo
@@ -82,6 +83,9 @@ def prepare_acme_client(master, client):
acme_host = f'{IPA_CA_RECORD}.{master.domain.name}'
acme_server = f'https://{acme_host}/acme/directory'
+ # enable firewall rule on client
+ Firewall(client).enable_services(["http", "https"])
+
# install acme client packages
if not skip_certbot_tests:
tasks.install_packages(client, ['certbot'])

View File

@ -1,193 +0,0 @@
From 99aa03413421cf2839e89e10ca279ec19233dd01 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Jul 20 2023 08:23:36 +0000
Subject: User plugin: improve error related to non existing idp
The user and stageuser commands return the following error
when the user is created/updated with a non existing idp:
$ ipa user-add testuser --first test --last user --idp dummy
ipa: ERROR: no such entry
The error is not descriptive enough and has been modified to
display instead:
$ ipa user-add testuser --first test --last user --idp dummy
ipa: ERROR: External IdP configuration dummy not found
Fixes: https://pagure.io/freeipa/issue/9416
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
diff --git a/ipaserver/plugins/baseuser.py b/ipaserver/plugins/baseuser.py
index 73b76d3..ba5f9b7 100644
--- a/ipaserver/plugins/baseuser.py
+++ b/ipaserver/plugins/baseuser.py
@@ -708,7 +708,11 @@ class baseuser_mod(LDAPUpdate):
if 'ipaidpuser' not in obj_classes:
entry_attrs['objectclass'].append('ipaidpuser')
- answer = self.api.Object['idp'].get_dn_if_exists(cl)
+ try:
+ answer = self.api.Object['idp'].get_dn_if_exists(cl)
+ except errors.NotFound:
+ reason = "External IdP configuration {} not found"
+ raise errors.NotFound(reason=_(reason).format(cl))
entry_attrs['ipaidpconfiglink'] = answer
# Note: we could have used the method add_missing_object_class
diff --git a/ipaserver/plugins/stageuser.py b/ipaserver/plugins/stageuser.py
index 51438a8..852e51b 100644
--- a/ipaserver/plugins/stageuser.py
+++ b/ipaserver/plugins/stageuser.py
@@ -404,7 +404,11 @@ class stageuser_add(baseuser_add):
if 'ipaidpuser' not in entry_attrs['objectclass']:
entry_attrs['objectclass'].append('ipaidpuser')
- answer = self.api.Object['idp'].get_dn_if_exists(cl)
+ try:
+ answer = self.api.Object['idp'].get_dn_if_exists(cl)
+ except errors.NotFound:
+ reason = "External IdP configuration {} not found"
+ raise errors.NotFound(reason=_(reason).format(cl))
entry_attrs['ipaidpconfiglink'] = answer
self.pre_common_callback(ldap, dn, entry_attrs, attrs_list, *keys,
diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py
index 643b44f..a337e1f 100644
--- a/ipaserver/plugins/user.py
+++ b/ipaserver/plugins/user.py
@@ -638,7 +638,11 @@ class user_add(baseuser_add):
if 'ipaidpuser' not in entry_attrs['objectclass']:
entry_attrs['objectclass'].append('ipaidpuser')
- answer = self.api.Object['idp'].get_dn_if_exists(rcl)
+ try:
+ answer = self.api.Object['idp'].get_dn_if_exists(rcl)
+ except errors.NotFound:
+ reason = "External IdP configuration {} not found"
+ raise errors.NotFound(reason=_(reason).format(rcl))
entry_attrs['ipaidpconfiglink'] = answer
self.pre_common_callback(ldap, dn, entry_attrs, attrs_list, *keys,
From dbcbe9a39c99008c6858bab53e2807b7bf01ba65 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Jul 20 2023 08:23:36 +0000
Subject: xmlrpc tests: add a test for user plugin with non-existing idp
Add new tests checking the error returned for
ipa user-add ... --idp nonexistingidp
ipa user-mod ... --idp nonexistingidp
ipa stageuser-add ... --idp nonexistingidp
ipa stageuser-mod ... --idp nonexistingidp
The expected error message is:
ipa: ERROR: External IdP configuration nonexistingidp not found
Related: https://pagure.io/freeipa/issue/9416
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
diff --git a/ipatests/test_xmlrpc/test_stageuser_plugin.py b/ipatests/test_xmlrpc/test_stageuser_plugin.py
index 394015f..9ae5561 100644
--- a/ipatests/test_xmlrpc/test_stageuser_plugin.py
+++ b/ipatests/test_xmlrpc/test_stageuser_plugin.py
@@ -39,6 +39,8 @@ gid = u'456'
invalidrealm1 = u'suser1@NOTFOUND.ORG'
invalidrealm2 = u'suser1@BAD@NOTFOUND.ORG'
+nonexistentidp = 'IdPDoesNotExist'
+
invaliduser1 = u'+tuser1'
invaliduser2 = u'tuser1234567890123456789012345678901234567890'
invaliduser3 = u'1234'
@@ -431,6 +433,15 @@ class TestCreateInvalidAttributes(XMLRPC_test):
invalidrealm2))):
command()
+ def test_create_invalid_idp(self, stageduser):
+ stageduser.ensure_missing()
+ command = stageduser.make_create_command(
+ options={u'ipaidpconfiglink': nonexistentidp})
+ with raises_exact(errors.NotFound(
+ reason="External IdP configuration {} not found".format(
+ nonexistentidp))):
+ command()
+
@pytest.mark.tier1
class TestUpdateInvalidAttributes(XMLRPC_test):
@@ -466,6 +477,15 @@ class TestUpdateInvalidAttributes(XMLRPC_test):
message=u'invalid \'gidnumber\': must be at least 1')):
command()
+ def test_update_invalididp(self, stageduser):
+ stageduser.ensure_exists()
+ command = stageduser.make_update_command(
+ updates={u'ipaidpconfiglink': nonexistentidp})
+ with raises_exact(errors.NotFound(
+ reason="External IdP configuration {} not found".format(
+ nonexistentidp))):
+ command()
+
@pytest.mark.tier1
class TestActive(XMLRPC_test):
diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py
index 8ac19a4..baa2867 100644
--- a/ipatests/test_xmlrpc/test_user_plugin.py
+++ b/ipatests/test_xmlrpc/test_user_plugin.py
@@ -86,6 +86,8 @@ expired_expiration_string = "1991-12-07T19:54:13Z"
# Date in ISO format (2013-12-10T12:00:00)
isodate_re = re.compile(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$')
+nonexistentidp = 'IdPDoesNotExist'
+
@pytest.fixture(scope='class')
def user_min(request, xmlrpc_setup):
@@ -542,6 +544,18 @@ class TestUpdate(XMLRPC_test):
command()
user.delete()
+ def test_update_invalid_idp(self, user):
+ """ Test user-mod --idp with a non-existent idp """
+ user.ensure_exists()
+ command = user.make_update_command(
+ updates=dict(ipaidpconfiglink=nonexistentidp)
+ )
+ with raises_exact(errors.NotFound(
+ reason="External IdP configuration {} not found".format(
+ nonexistentidp)
+ )):
+ command()
+
@pytest.mark.tier1
class TestCreate(XMLRPC_test):
@@ -770,6 +784,17 @@ class TestCreate(XMLRPC_test):
user_radius.check_create(result)
user_radius.delete()
+ def test_create_with_invalididp(self):
+ testuser = UserTracker(
+ name='idpuser', givenname='idp', sn='user',
+ ipaidpconfiglink=nonexistentidp
+ )
+ with raises_exact(errors.NotFound(
+ reason="External IdP configuration {} not found".format(
+ nonexistentidp)
+ )):
+ testuser.create()
+
@pytest.mark.tier1
class TestUserWithGroup(XMLRPC_test):

View File

@ -1,169 +0,0 @@
From f215d3f45396fa29bdd69f56096b50842df14908 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Aug 01 2023 22:03:03 +0000
Subject: Prevent the admin user from being deleted
admin is required for trust operations
Note that testing for removing the last member is now
irrelevant because admin must always exist so the test
for it was removed, but the code check remains. It is done
after the protected member check.
Fixes: https://pagure.io/freeipa/issue/8878
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
---
diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py
index a337e1f..6f5e349 100644
--- a/ipaserver/plugins/user.py
+++ b/ipaserver/plugins/user.py
@@ -138,14 +138,23 @@ MEMBEROF_ADMINS = "(memberOf={})".format(
)
NOT_MEMBEROF_ADMINS = '(!{})'.format(MEMBEROF_ADMINS)
+PROTECTED_USERS = ('admin',)
def check_protected_member(user, protected_group_name=u'admins'):
'''
- Ensure the last enabled member of a protected group cannot be deleted or
- disabled by raising LastMemberError.
+ Ensure admin and the last enabled member of a protected group cannot
+ be deleted or disabled by raising ProtectedEntryError or
+ LastMemberError as appropriate.
'''
+ if user in PROTECTED_USERS:
+ raise errors.ProtectedEntryError(
+ label=_("user"),
+ key=user,
+ reason=_("privileged user"),
+ )
+
# Get all users in the protected group
result = api.Command.user_find(in_group=protected_group_name)
@@ -868,6 +877,12 @@ class user_mod(baseuser_mod):
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
dn, oc = self.obj.get_either_dn(*keys, **options)
+ if options.get('rename') and keys[-1] in PROTECTED_USERS:
+ raise errors.ProtectedEntryError(
+ label=_("user"),
+ key=keys[-1],
+ reason=_("privileged user"),
+ )
if 'objectclass' not in entry_attrs and 'rename' not in options:
entry_attrs.update({'objectclass': oc})
self.pre_common_callback(ldap, dn, entry_attrs, attrs_list, *keys,
diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py
index baa2867..df105a2 100644
--- a/ipatests/test_xmlrpc/test_user_plugin.py
+++ b/ipatests/test_xmlrpc/test_user_plugin.py
@@ -978,22 +978,32 @@ class TestManagers(XMLRPC_test):
@pytest.mark.tier1
class TestAdmins(XMLRPC_test):
- def test_remove_original_admin(self):
- """ Try to remove the only admin """
+ def test_delete_admin(self):
+ """ Try to delete the protected admin user """
tracker = Tracker()
- command = tracker.make_command('user_del', [admin1])
+ command = tracker.make_command('user_del', admin1)
- with raises_exact(errors.LastMemberError(
- key=admin1, label=u'group', container=admin_group)):
+ with raises_exact(errors.ProtectedEntryError(label=u'user',
+ key=admin1, reason='privileged user')):
+ command()
+
+ def test_rename_admin(self):
+ """ Try to rename the admin user """
+ tracker = Tracker()
+ command = tracker.make_command('user_mod', admin1,
+ **dict(rename=u'newadmin'))
+
+ with raises_exact(errors.ProtectedEntryError(label=u'user',
+ key=admin1, reason='privileged user')):
command()
def test_disable_original_admin(self):
- """ Try to disable the only admin """
+ """ Try to disable the original admin """
tracker = Tracker()
command = tracker.make_command('user_disable', admin1)
- with raises_exact(errors.LastMemberError(
- key=admin1, label=u'group', container=admin_group)):
+ with raises_exact(errors.ProtectedEntryError(label=u'user',
+ key=admin1, reason='privileged user')):
command()
def test_create_admin2(self, admin2):
@@ -1011,21 +1021,11 @@ class TestAdmins(XMLRPC_test):
admin2.disable()
tracker = Tracker()
- with raises_exact(errors.LastMemberError(
- key=admin1, label=u'group', container=admin_group)):
+ with raises_exact(errors.ProtectedEntryError(label=u'user',
+ key=admin1, reason='privileged user')):
tracker.run_command('user_disable', admin1)
- with raises_exact(errors.LastMemberError(
- key=admin1, label=u'group', container=admin_group)):
- tracker.run_command('user_del', admin1)
admin2.delete()
- with raises_exact(errors.LastMemberError(
- key=admin1, label=u'group', container=admin_group)):
- tracker.run_command('user_disable', admin1)
- with raises_exact(errors.LastMemberError(
- key=admin1, label=u'group', container=admin_group)):
- tracker.run_command('user_del', admin1)
-
@pytest.mark.tier1
class TestPreferredLanguages(XMLRPC_test):
From 7d62d84bdd3c2acd2f4bf70bb5fabf14c72e8ee7 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Aug 08 2023 14:50:32 +0000
Subject: ipatests: update expected webui msg for admin deletion
The deletion of the admin is now forbidden (even if it is
not the last member of the admins group) and the error
message has changed from "admin cannot be deleted or
disabled because it is the last member of group admins"
to " user admin cannot be deleted/modified: privileged user".
Update the expected message in the webui test.
Related: https://pagure.io/freeipa/issue/8878
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
---
diff --git a/ipatests/test_webui/test_user.py b/ipatests/test_webui/test_user.py
index 8d44fbd..a8a92d0 100644
--- a/ipatests/test_webui/test_user.py
+++ b/ipatests/test_webui/test_user.py
@@ -50,8 +50,7 @@ INV_FIRSTNAME = ("invalid 'first': Leading and trailing spaces are "
FIELD_REQ = 'Required field'
ERR_INCLUDE = 'may only include letters, numbers, _, -, . and $'
ERR_MISMATCH = 'Passwords must match'
-ERR_ADMIN_DEL = ('admin cannot be deleted or disabled because it is the last '
- 'member of group admins')
+ERR_ADMIN_DEL = ('user admin cannot be deleted/modified: privileged user')
USR_EXIST = 'user with name "{}" already exists'
ENTRY_EXIST = 'This entry already exists'
ACTIVE_ERR = 'active user with name "{}" already exists'

View File

@ -1,114 +0,0 @@
From 9438ce9207445e4ad4a9c7bdf0c9e569cabac571 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Aug 01 2023 06:07:06 +0000
Subject: Fix memory leak in the OTP last token plugin
Three memory leaks are addressed:
1. String values retrieved from the pblock need to be manually
freed.
2. The list of objectclasses retreived from the pblock need to be
freed.
3. Internal search results need to be freed.
Fixes: https://pagure.io/freeipa/issue/9403
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Rafael Guterres Jeffman <rjeffman@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
---
diff --git a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
index b7a2ba7..11106b2 100644
--- a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
+++ b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
@@ -54,7 +54,7 @@ void *ipa_otp_lasttoken_plugin_id;
static bool entry_is_token(Slapi_Entry *entry)
{
- char **ocls;
+ char **ocls = NULL;
ocls = slapi_entry_attr_get_charray(entry, SLAPI_ATTR_OBJECTCLASS);
for (size_t i = 0; ocls != NULL && ocls[i] != NULL; i++) {
@@ -64,6 +64,7 @@ static bool entry_is_token(Slapi_Entry *entry)
}
}
+ slapi_ch_array_free(ocls);
return false;
}
@@ -138,7 +139,8 @@ static bool is_pwd_enabled(const char *user_dn)
static bool is_allowed(Slapi_PBlock *pb, Slapi_Entry *entry)
{
Slapi_DN *target_sdn = NULL;
- const char *bind_dn;
+ char *bind_dn;
+ bool rv = false;
/* Ignore internal operations. */
if (slapi_op_internal(pb))
@@ -147,23 +149,35 @@ static bool is_allowed(Slapi_PBlock *pb, Slapi_Entry *entry)
/* Load parameters. */
(void) slapi_pblock_get(pb, SLAPI_TARGET_SDN, &target_sdn);
(void) slapi_pblock_get(pb, SLAPI_CONN_DN, &bind_dn);
- if (target_sdn == NULL || bind_dn == NULL) {
- LOG_FATAL("Missing parameters!\n");
- return false;
+ if (bind_dn == NULL) {
+ LOG_FATAL("bind_dn parameter missing!\n");
+ goto done;
+ }
+ if (target_sdn == NULL) {
+ LOG_FATAL("target_sdn parameter missing!\n");
+ goto done;
}
if (entry != NULL
? !entry_is_token(entry)
- : !sdn_in_otp_container(target_sdn))
- return true;
+ : !sdn_in_otp_container(target_sdn)) {
+ rv = true;
+ goto done;
+ }
- if (!sdn_is_only_enabled_token(target_sdn, bind_dn))
- return true;
+ if (!sdn_is_only_enabled_token(target_sdn, bind_dn)) {
+ rv = true;
+ goto done;
+ }
- if (is_pwd_enabled(bind_dn))
- return true;
+ if (is_pwd_enabled(bind_dn)) {
+ rv = true;
+ goto done;
+ }
- return false;
+done:
+ slapi_ch_free_string(&bind_dn);
+ return rv;
}
static inline int send_error(Slapi_PBlock *pb, int rc, const char *errstr)
diff --git a/daemons/ipa-slapi-plugins/libotp/otp_token.c b/daemons/ipa-slapi-plugins/libotp/otp_token.c
index a3cbfb0..4be4ede 100644
--- a/daemons/ipa-slapi-plugins/libotp/otp_token.c
+++ b/daemons/ipa-slapi-plugins/libotp/otp_token.c
@@ -398,6 +398,7 @@ static struct otp_token **find(const struct otp_config *cfg, const char *user_dn
}
error:
+ slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
return tokens;
}

View File

@ -1,58 +0,0 @@
From fdaad3a45f5674876fd3f6cc7ad1e916ebfc7080 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Aug 14 2023 13:02:20 +0000
Subject: ipatests: fix test_topology
The test TestTopologyOptions::test_add_remove_segment is
randomly failing downstream. Test scenario:
- create a line topology master <-> repl1 <-> repl2
- create user on master
- wait for repl success on master
- check that the user is seen on repl2
The test waits for replication to complete on the master but
it should also wait for the replication to complete on repl1
before checking the user presence on repl2.
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Anuja More <amore@redhat.com>
---
diff --git a/ipatests/test_integration/test_topology.py b/ipatests/test_integration/test_topology.py
index 8a240fa..618c9d5 100644
--- a/ipatests/test_integration/test_topology.py
+++ b/ipatests/test_integration/test_topology.py
@@ -124,6 +124,9 @@ class TestTopologyOptions(IntegrationTest):
self.replicas[0],
self.replicas[1])
assert err == "", err
+ # At this point we have replicas[1] <-> master <-> replicas[0]
+ # ^--------------------------^
+
# Make sure the new segment is shown by `ipa topologysegment-find`
result1 = self.master.run_command(['ipa', 'topologysegment-find',
DOMAIN_SUFFIX_NAME]).stdout_text
@@ -137,9 +140,12 @@ class TestTopologyOptions(IntegrationTest):
deleteme = find_segment(self.master, self.replicas[1])
returncode, error = tasks.destroy_segment(self.master, deleteme)
assert returncode == 0, error
+ # At this point we have master <-> replicas[0] <-> replicas[1]
+
# Wait till replication ends and make sure replica1 does not have
# segment that was deleted on master
master_ldap = self.master.ldap_connect()
+ repl_ldap = self.replicas[0].ldap_connect()
tasks.wait_for_replication(master_ldap)
result3 = self.replicas[0].run_command(['ipa', 'topologysegment-find',
DOMAIN_SUFFIX_NAME]).stdout_text
@@ -150,6 +156,7 @@ class TestTopologyOptions(IntegrationTest):
'--first', 'test',
'--last', 'user'])
tasks.wait_for_replication(master_ldap)
+ tasks.wait_for_replication(repl_ldap)
result4 = self.replicas[1].run_command(['ipa', 'user-find'])
assert('someuser' in result4.stdout_text), 'User not found: someuser'
# We end up having a line topology: master <-> replica1 <-> replica2

View File

@ -1,40 +0,0 @@
From f38eefd9f7e54470de7c707782114b17aac8762a Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Aug 16 2023 15:25:34 +0000
Subject: Installer: activate nss and pam services in sssd.conf
If there is already a sssd.conf file before the installer is
executed, the nss and pam services may not be enabled by the
installer. This happens for instance if the machine is hardened
for STIG and sssd.conf does not define services=... in the
[sssd] section.
The consequence is that trust cannot be established with an AD
domain.
The installer must enable nss and pam services even if there is
a pre-existing sssd.conf file.
Fixes: https://pagure.io/freeipa/issue/9427
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
---
diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py
index ef29a2c..07d62a7 100644
--- a/ipaclient/install/client.py
+++ b/ipaclient/install/client.py
@@ -969,6 +969,9 @@ def configure_sssd_conf(
nss_service.set_option('memcache_timeout', 600)
sssdconfig.save_service(nss_service)
+ sssd_enable_service(sssdconfig, 'nss')
+ sssd_enable_service(sssdconfig, 'pam')
+
domain.set_option('ipa_domain', cli_domain)
domain.set_option('ipa_hostname', client_hostname)
if cli_domain.lower() != cli_realm.lower():

View File

@ -1,16 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEE11Z2TU1+KXxtrRFyaYdvcqbi008FAmRnL+gACgkQaYdvcqbi
00/1Gg/8CFABojXZyUkQnWeaHdrFeHeE+DW2qTs9Wr/TQwF67fYkh7lj3p+WqMlD
kMMNAfLn4wUnJNDMv64QlE6RAz71KetQlQt+mZQVT9M0nDepLhBw86qmNbJj611J
+2B79hzNLT8tmOf9NyLRJbFp3QebSPELX9hycPj1Ovd1tr/61tcwcNzE6ZLrX5vb
IPkCT2bo+6MceIsR50tTRxxK6J9jFYX73PjHJ5Ix7ssDf4vg2OBRTwUdLeZAkWlA
q+0bPPp+F3PWLhnSs+vIs5plHUI/hcGCt9pTvw/d6jUUxuwZadGGbRZSyDN7aj2Q
zEXeZsCtOSk5cx65lWHl+7TTyVvCoemeZPZ92EiCtVJfiuK3/6a/WFWanBZoO0E3
N0p6HUcvIRPrEj0nQwH2vr0zkfSPA4g30k+Q9qeP3ArN+i+5OFfuiwiqk1AIJ2rv
ERhBRryOaNeiVpYghMQdtacWP/qQunfH6VdhA61Q089/lhomGeSytQI+fV4TXOhV
ldV7dftaWpQT3QYWSsKzoiHpyjIwOA8dBvQF2YDX7LNmeO/hj4ToFp00CVCWdb0j
MHs2X9p42kkhw2oZOf3GNyNvpybxUv59ER4YDEHbj8+iZyVjiqfcp71373DqpieW
iGjB3Wc0gO3cdYk3Mdl0SgkD7k0U9iwwh7qJeqqUYT3gKf9mqbY=
=dT0o
-----END PGP SIGNATURE-----

16
freeipa-4.9.11.tar.gz.asc Normal file
View File

@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEE11Z2TU1+KXxtrRFyaYdvcqbi008FAmOA8kcACgkQaYdvcqbi
00887g/9GTvueJCypiuTqxKsbkTbWamOyH3W+AqtHw9Ff+wM/hnkSloGizhQ4EZZ
4Zs1e6bfM1pGXT7DXU9WbiYtcVtUhY5l9SnT9moCMaG1z4aB7z9UCxsqsSCuy3bG
KQq6AO2z4DaqHiz6ez3QXi+MUCNnPziWmS3bLdDCrTK0PNxqiMPIotlXMgVFgDL7
go/TAUvUL27zH4ELvG4parSGEKVEqe//RzXklOwGrInyj/4u42x7lUdO2ugOolCI
wNod8v+NWQWVgxNyhfTjP5VBZzO9wkGx4xruF2cAjVdjnIUGcG0FR3hI/bpi7Lyv
EmIozbQMK92MLel63E7Z/d5Jxfmuw/n1t5NrgSth+9hhWnBEpiaKkD2zAmUATqHf
+y4mbrtajmjzewEnfUnQfCvSLDPyTpnQKkRY8hUvk7u/J+/ZFWMQl9RdGNw3M0Zr
WrsqkKLK/n5IOHYHb/lBRaUidssKjQYFIvyNfHDP/lu6iiyLOpi5MIdk9BakO5wc
oDMk3w9xY7tPPmoesW40BThnAdOR9U4aad8zVvOxhMfzAYRwu95HGQoHnk7/rNut
IfzMZVjVTLQ8gyApcBlWzu/buiOoEXTKaMyzs0S9RMptknj5Xf0CGRz3bVrZRfJd
umyhD6/rNk3eZW/yEIv3IqFev0h1txTBPSTlczYUIz6uc7nx82E=
=8YVm
-----END PGP SIGNATURE-----

3247
freeipa.spec Normal file

File diff suppressed because it is too large Load Diff

7
gating.yaml Normal file
View File

@ -0,0 +1,7 @@
# recipients: abokovoy, frenaud, kaleem, ftrivino
--- !Policy
product_versions:
- rhel-9
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: idm-ci.brew-build.tier1.functional}

View File

@ -64,7 +64,7 @@
%if 0%{?rhel}
%global package_name ipa
%global alt_name freeipa
%global krb5_version 1.18.2-25
%global krb5_version 1.18.2-2
%global krb5_kdb_version 8.0
# 0.7.16: https://github.com/drkjam/netaddr/issues/71
%global python_netaddr_version 0.7.19
@ -176,7 +176,7 @@
# Work-around fact that RPM SPEC parser does not accept
# "Version: @VERSION@" in freeipa.spec.in used for Autoconf string replacement
%define IPA_VERSION 4.9.12
%define IPA_VERSION 4.9.11
# Release candidate version -- uncomment with one percent for RC versions
#%%global rc_version %%nil
%define AT_SIGN @
@ -189,7 +189,7 @@
Name: %{package_name}
Version: %{IPA_VERSION}
Release: 8%{?rc_version:.%rc_version}%{?dist}
Release: 3%{?rc_version:.%rc_version}%{?dist}
Summary: The Identity, Policy and Audit system
License: GPLv3+
@ -209,19 +209,7 @@ Source1: https://releases.pagure.org/freeipa/freeipa-%{version}%{?rc_vers
# RHEL spec file only: START
%if %{NON_DEVELOPER_BUILD}
%if 0%{?rhel} >= 8
Patch0001: 0001-user-or-group-name-explain-the-supported-format_rhbz#2150217.patch
Patch0002: 0002-Use-the-python-cryptography-parser-directly-in-cert-find_rhbz#2164349.patch
Patch0003: 0003-Upgrade-add-PKI-drop-in-file-if-missing_rhbz#2215336.patch
Patch0004: 0004-Upgrade-fix-replica-agreement_rhbz#2216551.patch
Patch0005: 0005-OTP-fix-data-type-to-avoid-endianness-issue_rhbz#2218293.patch
Patch0006: 0006-Backport-test-updates-8-9-release_rhbz#2218847.patch
Patch0007: 0007-ipa-kdb-fix-error-handling-of-is_master_host_rhbz#2214638.patch
Patch0008: 0008-ipatests-enable-firewall-rule-for-http-service-on-acme-client_rhbz#2230256.patch
Patch0009: 0009-User-plugin-improve-error-related-to-non-existing-idp_rhbz#2224572.patch
Patch0010: 0010-Prevent-admin-user-from-being-deleted_rhbz#1921181.patch
Patch0011: 0011-Fix-memory-leak-in-the-OTP-last-token-plugin_rhbz#2227783.patch
Patch0012: 0012-ipatests-fix-test_topology_rhbz#2232351.patch
Patch0013: 0013-Installer-activate-nss-and-pam-services-in-sssd.conf_rhbz#2216532.patch
Patch0001: 0001-updates-fix-memberManager-ACI-to-allow-managers-from-a-specified-group_rhbz#2056009.patch
Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch
Patch1002: 1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch
Patch1003: 1003-webui-IdP-Remove-arrow-notation-due-to-uglify-js-lim.patch
@ -679,7 +667,6 @@ Requires: jansson
%endif
Requires: sssd-ipa >= %{sssd_version}
Requires: sssd-idp >= %{sssd_version}
Requires: sssd-krb5 >= %{sssd_version}
Requires: certmonger >= %{certmonger_version}
Requires: nss-tools >= %{nss_version}
Requires: bind-utils
@ -1240,8 +1227,10 @@ if [ $1 -gt 1 ] ; then
test -f '/var/lib/ipa-client/sysrestore/sysrestore.index' && restore=$(wc -l '/var/lib/ipa-client/sysrestore/sysrestore.index' | awk '{print $1}')
if [ -f '/etc/sssd/sssd.conf' -a $restore -ge 2 ]; then
if grep -E -q '/var/lib/sss/pubconf/krb5.include.d/' /etc/krb5.conf 2>/dev/null ; then
sed -i '\;includedir /var/lib/sss/pubconf/krb5.include.d;d' /etc/krb5.conf
if ! grep -E -q '/var/lib/sss/pubconf/krb5.include.d/' /etc/krb5.conf 2>/dev/null ; then
echo "includedir /var/lib/sss/pubconf/krb5.include.d/" > /etc/krb5.conf.ipanew
cat /etc/krb5.conf >> /etc/krb5.conf.ipanew
mv -Z /etc/krb5.conf.ipanew /etc/krb5.conf
fi
fi
@ -1736,60 +1725,6 @@ fi
%endif
%changelog
* Thu Aug 31 2023 Rafael Jeffman <rjeffman@redhat.com> - 4.9.12-8
- Require krb5 release 1.18.2-25 or later
Resolves: RHBZ#2234711
* Wed Aug 16 2023 Rafael Jeffman <rjeffman@redhat.com> - 4.9.12-7
- ipatests: fix test_topology
Resolves: RHBZ#2232351
- Installer: activate nss and pam services in sssd.conf
Resolves: RHBZ#2216532
* Thu Aug 10 2023 Rafael Jeffman <rjeffman@redhat.com> - 4.9.12-6
- ipa-kdb: fix error handling of is_master_host()
Resolves: RHBZ#2214638
- ipatests: enable firewall rule for http service on acme client
Resolves: RHBZ#2230256
- User plugin: improve error related to non existing idp
Resolves: RHBZ#2224572
- Prevent admin user from being deleted
Resolves: RHBZ#1821181
- Fix memory leak in the OTP last token plugin
Resolves: RHBZ#2227783
* Mon Jul 17 2023 Rafael Jeffman <rjeffman@redhat.com> - 4.9.12-5
- Upgrade: fix replica agreement, fix backported patch
Related: RHBZ#2216551
* Fri Jun 30 2023 Rafael Jeffman <rjeffman@redhat.com> - 4.9.12-4
- kdb: Use-krb5_pac_full_sign_compat() when available
Resolves: RHBZ#2176406
- OTP: fix-data-type-to-avoid-endianness-issue
Resolves: RHBZ#2218293
- Upgrade: fix replica agreement
Resolves: RHBZ#2216551
- Upgrade: add PKI drop-in file if missing
Resolves: RHBZ#2215336
- Use the python-cryptography parser directly in cert-find
Resolves: RHBZ#2164349
- Backport test updates
Resolves: RHBZ#221884
* Wed Jun 21 2023 Julien Rische <jrische@redhat.com> - 4.9.12-3
- Rely on sssd-krb5 to include SSSD-generated krb5 configuration
Resolves: RHBZ#2214563
* Thu May 25 2023 Rafael Jeffman <rjeffman@redhat.com> - 4.9.12-2
- Use the OpenSSL certificate parser in cert-find
Resolves: RHBZ#2209947
* Wed May 24 2023 Rafael Jeffman <rjeffman@redhat.com> - 4.9.12-1
- Rebase ipa to 4.9.12
Resolves: RHBZ#2196425
- user or group name: explain the supported format
Resolves: RHBZ#2150217
* Mon Dec 19 2022 Rafael Jeffman <rjeffman@redhat.com> - 4.9.11-3
- Revert DNSResolver Fix use of nameservers with ports.
Related: RHBZ#2141316

9
rpminspect.yaml Normal file
View File

@ -0,0 +1,9 @@
---
specname:
match: suffix
runpath:
allowed_paths:
- /usr/lib64/samba
annocheck:
- hardened: --ignore-unknown --verbose --skip-run-path

1
sources Normal file
View File

@ -0,0 +1 @@
SHA512 (freeipa-4.9.11.tar.gz) = cab799850faa30b6e6799d8f0a25dac3e4941c269a9bf0da86d998f1ecb5f4d0f5c84059dae6e88f8f17f24642015eb6fe29fcb281067b70b5e44644572b0b80