Import rpm: d75e1e2ac69c17dcc10c7ade830baf8eabf9c5db

This commit is contained in:
James Antill 2023-02-20 01:58:05 -05:00
commit 335402d108
26 changed files with 10998 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
SOURCES/freeipa-4.9.11.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

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,69 @@
From 0d44e959e5bbe822b51137a8e7cf48fa25533805 Mon Sep 17 00:00:00 2001
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
Date: Fri, 10 Dec 2021 12:15:36 -0300
Subject: [PATCH] Revert "freeipa.spec: depend on bind-dnssec-utils"
This reverts commit f89d59b6e18b54967682f6a37ce92ae67ab3fcda.
---
freeipa.spec.in | 4 +---
ipaplatform/base/paths.py | 2 +-
ipaplatform/fedora/paths.py | 1 +
ipaserver/dnssec/bindmgr.py | 1 -
4 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/freeipa.spec.in b/freeipa.spec.in
index 8f5c370e5..e20edb7bc 100755
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -576,11 +576,9 @@ Requires: %{name}-server = %{version}-%{release}
Requires: bind-dyndb-ldap >= 11.2-2
Requires: bind >= %{bind_version}
Requires: bind-utils >= %{bind_version}
-# bind-dnssec-utils is required by the OpenDNSSec integration
-# https://pagure.io/freeipa/issue/9026
-Requires: bind-dnssec-utils >= %{bind_version}
%if %{with bind_pkcs11}
Requires: bind-pkcs11 >= %{bind_version}
+Requires: bind-pkcs11-utils >= %{bind_version}
%else
Requires: softhsm >= %{softhsm_version}
Requires: openssl-pkcs11 >= %{openssl_pkcs11_version}
diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
index 7d21367ec..42a47f1df 100644
--- a/ipaplatform/base/paths.py
+++ b/ipaplatform/base/paths.py
@@ -259,7 +259,6 @@ class BasePathNamespace:
IPA_PKI_RETRIEVE_KEY = "/usr/libexec/ipa/ipa-pki-retrieve-key"
IPA_HTTPD_PASSWD_READER = "/usr/libexec/ipa/ipa-httpd-pwdreader"
IPA_PKI_WAIT_RUNNING = "/usr/libexec/ipa/ipa-pki-wait-running"
- DNSSEC_KEYFROMLABEL = "/usr/sbin/dnssec-keyfromlabel"
+ DNSSEC_KEYFROMLABEL = "/usr/sbin/dnssec-keyfromlabel-pkcs11"
- DNSSEC_KEYFROMLABEL_9_17 = "/usr/bin/dnssec-keyfromlabel"
GETSEBOOL = "/usr/sbin/getsebool"
GROUPADD = "/usr/sbin/groupadd"
diff --git a/ipaplatform/fedora/paths.py b/ipaplatform/fedora/paths.py
index 4e993c063..92a948966 100644
--- a/ipaplatform/fedora/paths.py
+++ b/ipaplatform/fedora/paths.py
@@ -36,6 +36,7 @@ class FedoraPathNamespace(RedHatPathNamespace):
NAMED_CRYPTO_POLICY_FILE = "/etc/crypto-policies/back-ends/bind.config"
if HAS_NFS_CONF:
SYSCONFIG_NFS = '/etc/nfs.conf'
+ DNSSEC_KEYFROMLABEL = "/usr/sbin/dnssec-keyfromlabel"
paths = FedoraPathNamespace()
diff --git a/ipaserver/dnssec/bindmgr.py b/ipaserver/dnssec/bindmgr.py
index 0c79cc03d..a15c0e601 100644
--- a/ipaserver/dnssec/bindmgr.py
+++ b/ipaserver/dnssec/bindmgr.py
@@ -127,7 +127,6 @@ class BINDMgr:
)
cmd = [
paths.DNSSEC_KEYFROMLABEL,
- '-E', 'pkcs11',
'-K', workdir,
'-a', attrs['idnsSecAlgorithm'][0],
'-l', uri
--
2.31.1

View File

@ -0,0 +1,60 @@
From 7807bcc55b4927fc327830d2237200772d2e1106 Mon Sep 17 00:00:00 2001
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
Date: Fri, 17 Jun 2022 15:40:04 -0300
Subject: [PATCH] webui IdP: Remove arrow notation due to uglify-js limitation.
uglify-js 2.x series do not support ECMAScript 6 arrow notation ('=>')
for callback definition.
This patch changes the arrow definition callbacks for regular anonymous
function definitions.
---
install/ui/src/freeipa/idp.js | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/install/ui/src/freeipa/idp.js b/install/ui/src/freeipa/idp.js
index ada09c075..be3c4f0e6 100644
--- a/install/ui/src/freeipa/idp.js
+++ b/install/ui/src/freeipa/idp.js
@@ -227,7 +227,7 @@ IPA.add_idp_policy = function() {
// For custom template we show custom fields
// and mark all of them required and passed to the RPC
// If show_custom is false, the opposite happens
- custom_fields.forEach(fname => {
+ custom_fields.forEach(function(fname) {
widget_f = that.container.fields.get_field(fname);
widget_f.set_required(show_custom);
widget_f.set_enabled(show_custom);
@@ -235,7 +235,7 @@ IPA.add_idp_policy = function() {
});
// For template fields we show them if custom aren't shown
- template_fields.forEach(fname => {
+ template_fields.forEach(function(fname) {
widget_f = that.container.fields.get_field(fname);
widget_f.set_enabled(!show_custom);
widget_f.widget.set_visible(!show_custom);
@@ -252,7 +252,7 @@ IPA.add_idp_policy = function() {
var value = prov_f.get_value()[0];
// First, clear template fields from the previous provider choice
- template_fields.forEach(fname => {
+ template_fields.forEach(function(fname) {
widget_f = that.container.fields.get_field(fname);
widget_f.widget.set_visible(false);
widget_f.set_required(false);
@@ -260,9 +260,9 @@ IPA.add_idp_policy = function() {
});
// Second, enable and get required template-specific fields
- idp.templates.forEach(idp_v => {
+ idp.templates.forEach(function(idp_v) {
if (idp_v['value'] == value) {
- idp_v['fields'].forEach(fname => {
+ idp_v['fields'].forEach(function(fname) {
widget_f = that.container.fields.get_field(fname);
widget_f.set_required(true);
widget_f.set_enabled(true);
--
2.36.1

View File

@ -0,0 +1,114 @@
From 9a33838407f244e481523fe643bc0626874e8b1a Mon Sep 17 00:00:00 2001
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
Date: Mon, 19 Dec 2022 14:57:03 -0300
Subject: [PATCH] Revert "DNSResolver: Fix use of nameservers with ports"
This reverts commit 5e2e4664aec641886923c2bec61ce25b96edb62a.
---
ipapython/dnsutil.py | 41 -------------------------
ipatests/test_ipapython/test_dnsutil.py | 40 ------------------------
2 files changed, 81 deletions(-)
diff --git a/ipapython/dnsutil.py b/ipapython/dnsutil.py
index 58de365ab..4baeaf8cc 100644
--- a/ipapython/dnsutil.py
+++ b/ipapython/dnsutil.py
@@ -144,47 +144,6 @@ class DNSResolver(dns.resolver.Resolver):
nameservers.remove(ipv4_loopback)
self.nameservers = nameservers
- @dns.resolver.Resolver.nameservers.setter
- def nameservers(self, nameservers):
- """
- *nameservers*, a ``list`` of nameservers with optional ports:
- "SERVER_IP port PORT_NUMBER".
-
- Overloads dns.resolver.Resolver.nameservers setter to split off ports
- into nameserver_ports after setting nameservers successfully with the
- setter in dns.resolver.Resolver.
- """
- # Get nameserver_ports if it is already set
- if hasattr(self, "nameserver_ports"):
- nameserver_ports = self.nameserver_ports
- else:
- nameserver_ports = {}
-
- # Check nameserver items in list and split out converted port number
- # into nameserver_ports: { nameserver: port }
- if isinstance(nameservers, list):
- _nameservers = []
- for nameserver in nameservers:
- splits = nameserver.split()
- if len(splits) == 3 and splits[1] == "port":
- nameserver = splits[0]
- try:
- port = int(splits[2])
- if port < 0 or port > 65535:
- raise ValueError()
- except ValueError:
- raise ValueError(
- "invalid nameserver: %s is not a valid port" %
- splits[2])
- nameserver_ports[nameserver] = port
- _nameservers.append(nameserver)
- nameservers = _nameservers
-
- # Call dns.resolver.Resolver.nameservers setter
- dns.resolver.Resolver.nameservers.__set__(self, nameservers)
- # Set nameserver_ports after successfull call to setter
- self.nameserver_ports = nameserver_ports
-
class DNSZoneAlreadyExists(dns.exception.DNSException):
supp_kwargs = {'zone', 'ns'}
diff --git a/ipatests/test_ipapython/test_dnsutil.py b/ipatests/test_ipapython/test_dnsutil.py
index 09463c69d..5e7a46197 100644
--- a/ipatests/test_ipapython/test_dnsutil.py
+++ b/ipatests/test_ipapython/test_dnsutil.py
@@ -101,43 +101,3 @@ class TestSortURI:
assert dnsutil.sort_prio_weight([h3, h2, h1]) == [h1, h2, h3]
assert dnsutil.sort_prio_weight([h3, h3, h3]) == [h3]
assert dnsutil.sort_prio_weight([h2, h2, h1, h1]) == [h1, h2]
-
-
-class TestDNSResolver:
- def test_nameservers(self):
- res = dnsutil.DNSResolver()
- res.nameservers = ["4.4.4.4", "8.8.8.8"]
- assert res.nameservers == ["4.4.4.4", "8.8.8.8"]
-
- def test_nameservers_with_ports(self):
- res = dnsutil.DNSResolver()
- res.nameservers = ["4.4.4.4 port 53", "8.8.8.8 port 8053"]
- assert res.nameservers == ["4.4.4.4", "8.8.8.8"]
- assert res.nameserver_ports == {"4.4.4.4": 53, "8.8.8.8": 8053}
-
- res.nameservers = ["4.4.4.4 port 53", "8.8.8.8 port 8053"]
- assert res.nameservers == ["4.4.4.4", "8.8.8.8"]
- assert res.nameserver_ports == {"4.4.4.4": 53, "8.8.8.8": 8053}
-
- def test_nameservers_with_bad_ports(self):
- res = dnsutil.DNSResolver()
- try:
- res.nameservers = ["4.4.4.4 port a"]
- except ValueError:
- pass
- else:
- pytest.fail("No fail on bad port a")
-
- try:
- res.nameservers = ["4.4.4.4 port -1"]
- except ValueError:
- pass
- else:
- pytest.fail("No fail on bad port -1")
-
- try:
- res.nameservers = ["4.4.4.4 port 65536"]
- except ValueError:
- pass
- else:
- pytest.fail("No fail on bad port 65536")
--
2.38.1

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}

5213
ipa.spec Normal file

File diff suppressed because it is too large Load Diff

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 @@
SHA1 (freeipa-4.9.11.tar.gz) = 4ef188d43f5f2a09e214dd2bae68595a5977bb61