ipa-4.12.2-17

- Resolves: RHEL-95010 [RFE] Give warning when adding user with UID out of any ID range
- Resolves: RHEL-93890 Include latest fixes in python3-ipatests package
- Resolves: RHEL-93887 ipa idrange-add --help should be more clear about required options
- Resolves: RHEL-93483 Unable to modify IPA config; --ipaconfigstring="" causes internal error
- Resolves: RHEL-88834 kdb: ipadb_get_connection() succeeds but returns null LDAP context
- Resolves: RHEL-68800 ipa-migrate with LDIF file from backup of remote server, fails with error 'change collided with another change'
This commit is contained in:
Florence Blanc-Renaud 2025-06-04 18:44:50 +02:00
parent 5d25373c66
commit 76fd9fb78f
15 changed files with 1351 additions and 1 deletions

View File

@ -0,0 +1,66 @@
From 5f632d9d7813f89d498cfb21c8472ff3cac2538a Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Tue, 29 Apr 2025 13:55:23 -0400
Subject: [PATCH] ipa-migrate - remove replication state information
Remove replication state information (happens when LDIFs are used).
State information is written like:
attribute;adcsn=<CSN>
But we also support ";binary" which should not be removed so special
handling is needed in that case.
Signed-off-by: Mark Reynolds <mareynol@redhat.com>
Fixes: https://pagure.io/freeipa/issue/9776
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
ipaserver/install/ipa_migrate.py | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/ipaserver/install/ipa_migrate.py b/ipaserver/install/ipa_migrate.py
index 95ef0ac5adc830d04a6bb3a899b20aae86a77072..8ef0071f5c2edc1ce6cba780ac9a7d74122ea79d 100644
--- a/ipaserver/install/ipa_migrate.py
+++ b/ipaserver/install/ipa_migrate.py
@@ -202,6 +202,14 @@ def decode_attr_vals(entry_attrs):
decoded_attrs = {}
for attr in entry_attrs:
vals = ensure_list_str(entry_attrs[attr])
+ # Remove replication state data, but don't remove ";binary"
+ # e.g. userCertififccate;binary;adcsn=<CSN>
+ parts = attr.split(";")
+ if len(parts) > 1 and not attr.endswith(";binary"):
+ if parts[1] == "binary":
+ attr = parts[0] + ";binary"
+ else:
+ attr = parts[0]
decoded_attrs[attr] = vals
return decoded_attrs
@@ -269,19 +277,19 @@ class LDIFParser(ldif.LDIFParser):
if self.mc is None:
return
+ entry_attrs = decode_attr_vals(entry)
if self.get_realm:
# Get the realm from krb container
if DN(("cn", "kerberos"), self.mc.remote_suffix) in DN(dn):
# check objectclass krbrealmcontainer
oc_attr = 'objectClass'
- if 'objectclass' in entry:
+ if 'objectclass' in entry_attrs:
oc_attr = 'objectclass'
- if 'krbrealmcontainer' in ensure_list_str(entry[oc_attr]):
- self.mc.remote_realm = ensure_str(entry['cn'][0])
+ if 'krbrealmcontainer' in entry_attrs[oc_attr]:
+ self.mc.remote_realm = ensure_str(entry_attrs['cn'][0])
self.mc.log_debug("Found remote realm from ldif: "
f"{self.mc.remote_realm}")
else:
- entry_attrs = decode_attr_vals(entry)
self.mc.process_db_entry(entry_dn=dn, entry_attrs=entry_attrs)
--
2.49.0

View File

@ -0,0 +1,32 @@
From 4e23fa92f1a07565618d49ed27b54d33618bba73 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Tue, 29 Apr 2025 14:00:51 -0400
Subject: [PATCH] ipa-migrate - do not process AD entgries in staging mode
Only migrate AD entries in production mode due to schema conflicts
created when removing certain AD attributes (e.g.
ipantsecurityidentifier)
SIgned-off-by: Mark Reynolds <mreynolds@redhat.com>
relates: https://pagure.io/freeipa/issue/9776
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
ipaserver/install/ipa_migrate_constants.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ipaserver/install/ipa_migrate_constants.py b/ipaserver/install/ipa_migrate_constants.py
index 09856f07cabd124a7899bc5f355a56eb23023cc0..4beaa4f42a667ba83008213075b3ded782a83260 100644
--- a/ipaserver/install/ipa_migrate_constants.py
+++ b/ipaserver/install/ipa_migrate_constants.py
@@ -870,7 +870,7 @@ DB_OBJECTS = {
'oc': ['ipantdomainattrs'],
'subtree': ',cn=ad,cn=etc,$SUFFIX',
'label': 'AD',
- 'mode': 'all',
+ 'mode': 'production',
'count': 0,
},
--
2.49.0

View File

@ -0,0 +1,47 @@
From c052bbbfd2737f88b6496be7d4849cf17d9a126f Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Tue, 29 Apr 2025 14:05:15 -0400
Subject: [PATCH] ipa-migrate - improve suffix replacement
When values are "normalized/converted" to a new domain the order in
which the host/release/suffix are converted matters. Replacing the
suffix first can lead to incorrect results, so convert the host/realm
before converting the suffix
Signed-off-by: Mark Reynolds <mreynolds@redhat.com>
relates: https://pagure.io/freeipa/issue/9776
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
ipaserver/install/ipa_migrate.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/ipaserver/install/ipa_migrate.py b/ipaserver/install/ipa_migrate.py
index 8ef0071f5c2edc1ce6cba780ac9a7d74122ea79d..a24a2ab7a5ffd4cf1d59179f14e2f5d348fd57e2 100644
--- a/ipaserver/install/ipa_migrate.py
+++ b/ipaserver/install/ipa_migrate.py
@@ -1084,11 +1084,9 @@ class IPAMigrate():
if isinstance(val, bytes) or isinstance(val, DN):
return val
- # Replace base DN
- val = self.replace_suffix_value(val)
-
# For DNS DN we only replace suffix
if dns:
+ val = self.replace_suffix_value(val)
return val
# Replace host
@@ -1102,6 +1100,9 @@ class IPAMigrate():
# Replace realm
val = val.replace(self.remote_realm, self.realm)
+ # Lastly, replace base DN
+ val = self.replace_suffix_value(val)
+
return val
def convert_values(self, values, dns=False):
--
2.49.0

View File

@ -0,0 +1,87 @@
From 5d893c9c3b8d384873f40d2524b1ebf0f34fb452 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Mon, 28 Apr 2025 18:01:39 +0200
Subject: [PATCH] kdb: keep ipadb_get_connection() from succeeding with null
LDAP context
The final call to ipadb_reinit_mspac() in ipadb_get_connection() is not
considered essential for the function to succeed, as there might be
cases where the required pieces of information to generate PACs are not
yet configured in the database. However, in environments where 389ds is
overwhelmed, the LDAP connection established at the beginning of
ipadb_get_connection() might already be lost while executing
ipadb_reinit_mspac().
Connection errors were not distinguished from configuration errors,
which could result in ipadb_get_connection() succeeding while the LDAP
context is set to null, leading to a KDC crash on the next LDAP request.
ipadb_get_connection() now explicitly checks the value of the LDAP
context before returning.
Fixes: https://pagure.io/freeipa/issue/9777
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Rafael Guterres Jeffman <rjeffman@redhat.com>
---
daemons/ipa-kdb/ipa_kdb.c | 31 ++++++++++++++++++++++++-------
1 file changed, 24 insertions(+), 7 deletions(-)
diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c
index 903e19e83bbe383b878a3b9261dd501f96058d51..531ee223e1d5157c87a5c31dfe44b9cfa8dcc554 100644
--- a/daemons/ipa-kdb/ipa_kdb.c
+++ b/daemons/ipa-kdb/ipa_kdb.c
@@ -530,26 +530,43 @@ int ipadb_get_connection(struct ipadb_context *ipactx)
/* get adtrust options using default refresh interval */
ret = ipadb_reinit_mspac(ipactx, false, &stmsg);
- if (ret && stmsg)
- krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg);
+ if (ret) {
+ if (stmsg) {
+ krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg);
+ }
+ /* Initialization of the MS-PAC generator is an optional dependency.
+ * Fail only if the connection was lost. */
+ if (!ipactx->lcontext) {
+ goto done;
+ }
+ }
ret = 0;
done:
ldap_msgfree(res);
+ /* LDAP context should never be null on success, but keep this test out of
+ * security to make sure we do not return an invalid context. */
+ if (ret == 0 && !ipactx->lcontext) {
+ krb5_klog_syslog(LOG_WARNING, "Internal malfunction: LDAP connection "
+ "process resulted in an invalid context "
+ "(please report this incident)");
+ ret = LDAP_SERVER_DOWN;
+ }
+
if (ret) {
+ /* Cleanup LDAP context if connection failed. */
if (ipactx->lcontext) {
ldap_unbind_ext_s(ipactx->lcontext, NULL, NULL);
ipactx->lcontext = NULL;
}
- if (ret == LDAP_SERVER_DOWN) {
- return ETIMEDOUT;
- }
- return EIO;
+
+ /* Replace LDAP error code by POSIX error code. */
+ ret = ret == LDAP_SERVER_DOWN ? ETIMEDOUT : EIO;
}
- return 0;
+ return ret;
}
static krb5_principal ipadb_create_local_tgs(krb5_context kcontext,
--
2.49.0

View File

@ -0,0 +1,35 @@
From 17fdff8f2f1664a387147e13a851bc1248abc29c Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Mon, 19 May 2025 09:56:36 +0200
Subject: [PATCH] ipatests: test_manual_renewal_master_transfer must wait for
replication
The test is transferring the CA renewal role from master to replica.
It calls ipa config-mod on the replica then checks with ipa config-show
on the master.
Wait for replication to complete between the 2 steps.
Fixes: https://pagure.io/freeipa/issue/9790
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
ipatests/test_integration/test_replica_promotion.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/ipatests/test_integration/test_replica_promotion.py b/ipatests/test_integration/test_replica_promotion.py
index c754cef88cb275987f5afdaad43f2ea07e3b7476..3c67833d3101aef095539953e04c31d028c746d3 100644
--- a/ipatests/test_integration/test_replica_promotion.py
+++ b/ipatests/test_integration/test_replica_promotion.py
@@ -417,6 +417,9 @@ class TestRenewalMaster(IntegrationTest):
replica = self.replicas[0]
replica.run_command(['ipa', 'config-mod',
'--ca-renewal-master-server', replica.hostname])
+ # wait for replication to complete before checking on the master
+ tasks.wait_for_replication(replica.ldap_connect())
+
result = self.master.run_command(["ipa", "config-show"]).stdout_text
assert("IPA CA renewal master: %s" % replica.hostname in result), (
"Replica hostname not found among CA renewal masters"
--
2.49.0

View File

@ -0,0 +1,225 @@
From 6f1b9a4228e400ef23f0f411ebf8a98c30cd2f9f Mon Sep 17 00:00:00 2001
From: David Hanina <dhanina@redhat.com>
Date: Mon, 5 May 2025 17:31:18 +0200
Subject: [PATCH] Require baserid and secondarybaserid
This has been already required for some time, just not really enforced.
Also adds few new tests, and removes test without providing rid.
Fixes: https://pagure.io/freeipa/issue/9779
Signed-off-by: David Hanina <dhanina@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
ipaclient/plugins/idrange.py | 31 +++------------
ipaserver/plugins/idrange.py | 35 +++++++----------
ipatests/test_cmdline/test_cli.py | 13 -------
ipatests/test_xmlrpc/test_range_plugin.py | 46 +++++++++++++++++++++++
4 files changed, 66 insertions(+), 59 deletions(-)
diff --git a/ipaclient/plugins/idrange.py b/ipaclient/plugins/idrange.py
index 1a8d68ed7ff724854d5ea2f3dd43ec9644b5c671..b62cb1e3526d33a0d762809142b6e372f6f608ea 100644
--- a/ipaclient/plugins/idrange.py
+++ b/ipaclient/plugins/idrange.py
@@ -19,7 +19,6 @@
from ipaclient.frontend import MethodOverride
from ipalib.plugable import Registry
-from ipalib import api
register = Registry()
@@ -33,8 +32,7 @@ class idrange_add(MethodOverride):
Also ensure that secondary-rid-base is prompted for when rid-base is
specified and vice versa, in case that dom-sid was not specified.
- Also ensure that rid-base and secondary-rid-base is prompted for
- if ipa-adtrust-install has been run on the system.
+ Also ensure that rid-base and secondary-rid-base is prompted for.
"""
# dom-sid can be specified using dom-sid or dom-name options
@@ -63,27 +61,10 @@ class idrange_add(MethodOverride):
else:
# This is a local range
- # Find out whether ipa-adtrust-install has been ran
- adtrust_is_enabled = api.Command['adtrust_is_enabled']()['result']
- if adtrust_is_enabled:
- # If ipa-adtrust-install has been ran, all local ranges
- # require both RID base and secondary RID base
-
- if rid_base is None:
- set_from_prompt('ipabaserid')
-
- if secondary_rid_base is None:
- set_from_prompt('ipasecondarybaserid')
-
- else:
- # This is a local range on a server with no adtrust support
-
- # Prompt for secondary RID base only if RID base was given
- if rid_base is not None and secondary_rid_base is None:
- set_from_prompt('ipasecondarybaserid')
+ # All local ranges require both RID base and secondary RID base
+ if rid_base is None:
+ set_from_prompt('ipabaserid')
- # Symetrically, prompt for RID base if secondary RID base was
- # given
- if rid_base is None and secondary_rid_base is not None:
- set_from_prompt('ipabaserid')
+ if secondary_rid_base is None:
+ set_from_prompt('ipasecondarybaserid')
diff --git a/ipaserver/plugins/idrange.py b/ipaserver/plugins/idrange.py
index d155fb46da8240449a077d35e86a91ee9f95c132..1c8b5c6899ec927d753b7d9b116d35396b536339 100644
--- a/ipaserver/plugins/idrange.py
+++ b/ipaserver/plugins/idrange.py
@@ -73,10 +73,14 @@ Both types have the following attributes in common:
With those two attributes a range object can reserve the Posix IDs starting
with base-id up to but not including base-id+range-size exclusively.
-Additionally an ID range of the local domain may set
+Additionally an ID range of the local domain must set
- rid-base: the first RID(*) of the corresponding RID range
- secondary-rid-base: first RID of the secondary RID range
+If the server is updated from a previous version and defines local ID ranges
+missing the rid-base and secondary-rid-base, it is recommended to use
+`ipa-idrange-fix` command to identify the missing values and fix the ID ranges.
+
and an ID range of a trusted domain must set
- rid-base: the first RID of the corresponding RID range
- sid: domain SID of the trusted domain
@@ -519,11 +523,15 @@ class idrange_add(LDAPCreate):
'or ipa-ad-trust-posix when '
'auto-private-groups is specified'))
- # secondary base rid must be set if and only if base rid is set
- if is_set('ipasecondarybaserid') != is_set('ipabaserid'):
- raise errors.ValidationError(name='ID Range setup',
- error=_('Options secondary-rid-base and rid-base must '
- 'be used together'))
+ # base rid and secondary base rid must be set for sidgen
+ if not (is_set('ipabaserid') and is_set('ipasecondarybaserid')):
+ raise errors.ValidationError(
+ name='ID Range setup',
+ error=_(
+ 'You must specify both rid-base and '
+ 'secondary-rid-base options.'
+ )
+ )
# and they must not overlap
if is_set('ipabaserid') and is_set('ipasecondarybaserid'):
@@ -534,21 +542,6 @@ class idrange_add(LDAPCreate):
raise errors.ValidationError(name='ID Range setup',
error=_("Primary RID range and secondary RID range"
" cannot overlap"))
-
- # rid-base and secondary-rid-base must be set if
- # ipa-adtrust-install has been run on the system
- adtrust_is_enabled = api.Command['adtrust_is_enabled']()['result']
-
- if adtrust_is_enabled and not (
- is_set('ipabaserid') and is_set('ipasecondarybaserid')):
- raise errors.ValidationError(
- name='ID Range setup',
- error=_(
- 'You must specify both rid-base and '
- 'secondary-rid-base options, because '
- 'ipa-adtrust-install has already been run.'
- )
- )
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
diff --git a/ipatests/test_cmdline/test_cli.py b/ipatests/test_cmdline/test_cli.py
index 718798d68083285ce8aefe23af951bc819bdefdb..6c86bbb657a0d9a7b74ef34ad20a796a10073315 100644
--- a/ipatests/test_cmdline/test_cli.py
+++ b/ipatests/test_cmdline/test_cli.py
@@ -276,25 +276,12 @@ class TestCLIParsing:
ipasecondarybaserid=u'500000',
)
- def test_without_options():
- self.check_command(
- 'idrange_add range1 --base-id=1 --range-size=1',
- 'idrange_add',
- cn=u'range1',
- ipabaseid=u'1',
- ipaidrangesize=u'1',
- )
-
adtrust_dn = 'cn=ADTRUST,cn=%s,cn=masters,cn=ipa,cn=etc,%s' % \
(api.env.host, api.env.basedn)
adtrust_is_enabled = api.Command['adtrust_is_enabled']()['result']
mockldap = None
if not adtrust_is_enabled:
- # ipa-adtrust-install not run - no need to pass rid-base
- # and secondary-rid-base
- test_without_options()
-
# Create a mock service object to test against
adtrust_add = dict(
ipaconfigstring=b'enabledService',
diff --git a/ipatests/test_xmlrpc/test_range_plugin.py b/ipatests/test_xmlrpc/test_range_plugin.py
index 36469525b14ee507f2d8580b1f021ff09b82c99d..ffc89c028168740e7b8ae217259af512abff2d8a 100644
--- a/ipatests/test_xmlrpc/test_range_plugin.py
+++ b/ipatests/test_xmlrpc/test_range_plugin.py
@@ -1086,4 +1086,50 @@ class test_range(Declarative):
),
),
+ # Fail without baserid and secondarybaserid
+
+ dict(
+ desc='Try creating ID range %r without both rid' % (testrange9),
+ command=('idrange_add', [testrange9],
+ dict(ipabaseid=testrange9_base_id,
+ ipaidrangesize=testrange9_size)),
+ expected=errors.ValidationError(
+ name='ID Range setup',
+ error=(
+ 'You must specify both rid-base and '
+ 'secondary-rid-base options.'
+ )
+ )
+ ),
+
+ dict(
+ desc='Try creating ID range %r without'
+ 'secondarybaserid' % (testrange9),
+ command=('idrange_add', [testrange9],
+ dict(ipabaseid=testrange9_base_id,
+ ipaidrangesize=testrange9_size,
+ ipabaserid=testrange9_base_rid)),
+ expected=errors.ValidationError(
+ name='ID Range setup',
+ error=(
+ 'You must specify both rid-base and '
+ 'secondary-rid-base options.'
+ )
+ )
+ ),
+
+ dict(
+ desc='Try creating ID range %r without baserid' % (testrange9),
+ command=('idrange_add', [testrange9],
+ dict(ipabaseid=testrange9_base_id,
+ ipaidrangesize=testrange9_size,
+ ipasecondarybaserid=testrange9_secondary_base_rid)),
+ expected=errors.ValidationError(
+ name='ID Range setup',
+ error=(
+ 'You must specify both rid-base and '
+ 'secondary-rid-base options.'
+ )
+ )
+ ),
]
--
2.49.0

View File

@ -0,0 +1,90 @@
From 1c069653806ce8224132a35d6d3bd01ac53098b6 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Mon, 26 May 2025 18:24:12 +0200
Subject: [PATCH] ipa config-mod: fix internalerror when setting an empty
ipaconfigstring
When ipa config-mod is called with --ipaconfigstring="", the command
fails with an InternalError.
This happens because the code added for 32bits uid did not properly
handle this case.
Same issue if ipa subid-stats is called with a null ipaconfigstring.
This commit now handles when ipaconfigstring is empty or None, and adds
a test.
Fixes: https://pagure.io/freeipa/issue/9794
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Francisco Trivino <ftrivino@redhat.com>
---
ipaserver/plugins/config.py | 4 +--
ipatests/test_integration/test_commands.py | 30 ++++++++++++++++++++++
2 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/ipaserver/plugins/config.py b/ipaserver/plugins/config.py
index c509c2c13adfb4950741f63ffcbc9f3f806c0c3b..d9769ab1fb8498c24ce41ad32af40938bdaee804 100644
--- a/ipaserver/plugins/config.py
+++ b/ipaserver/plugins/config.py
@@ -524,7 +524,7 @@ class config(LDAPObject):
def is_config_option_present(self, option):
dn = DN(('cn', 'ipaconfig'), ('cn', 'etc'), self.api.env.basedn)
configentry = self.api.Backend.ldap2.get_entry(dn, ['ipaconfigstring'])
- configstring = configentry['ipaconfigstring']
+ configstring = configentry.get('ipaconfigstring') or []
return (option.lower() in map(str.lower, configstring))
@@ -702,7 +702,7 @@ class config_mod(LDAPUpdate):
error=_('SELinux user map default user not in order list'))
if 'ipaconfigstring' in entry_attrs:
- configstring = entry_attrs['ipaconfigstring']
+ configstring = entry_attrs['ipaconfigstring'] or []
if 'SubID:Disable'.lower() in map(str.lower, configstring):
# Check if SubIDs already allocated
try:
diff --git a/ipatests/test_integration/test_commands.py b/ipatests/test_integration/test_commands.py
index f64152908b3e1cbca451697043c1fcc8ad37fee6..9cad5772127bcd860aeecc8dabe73d5f160faf7b 100644
--- a/ipatests/test_integration/test_commands.py
+++ b/ipatests/test_integration/test_commands.py
@@ -2123,6 +2123,36 @@ class TestIPACommandWithoutReplica(IntegrationTest):
assert old_err_msg not in dirsrv_error_log
assert re.search(new_err_msg, dirsrv_error_log)
+ @pytest.fixture
+ def update_ipaconfigstring(self):
+ """
+ This fixture stores the value of ipaconfigstring parameter
+ and reverts to the initial value
+ """
+ ldap = self.master.ldap_connect()
+ dn = DN(
+ ("cn", "ipaconfig"), ('cn', 'etc'),
+ self.master.domain.basedn
+ )
+ entry = ldap.get_entry(dn)
+ val = entry.get("ipaconfigstring")
+ yield
+
+ # re-read the entry as the value may have been changed by the test
+ entry = ldap.get_entry(dn)
+ entry["ipaconfigstring"] = val
+ ldap.update_entry(entry)
+
+ def test_empty_ipaconfigstring(self, update_ipaconfigstring):
+ """
+ Test for https://pagure.io/freeipa/issue/9794
+
+ Test that setting an empty ipaconfigstring does not fail.
+ Subsequent calls to ipa subid-stats should also succeed.
+ """
+ self.master.run_command(['ipa', 'config-mod', "--ipaconfigstring="])
+ self.master.run_command(['ipa', 'subid-stats'])
+
def test_ipa_cacert_manage_prune(self):
"""Test for ipa-cacert-manage prune
--
2.49.0

View File

@ -0,0 +1,52 @@
From 383574be4e645155fb58a79612138e51c3bdc4eb Mon Sep 17 00:00:00 2001
From: Sudhir Menon <sumenon@redhat.com>
Date: Tue, 13 May 2025 15:58:56 +0530
Subject: [PATCH] ipatests: Test to check dot forwarders are added to unbound.
This test checks that dns forwarder is listed in
dnsserver-show command and also the dot forwarder is
added to unbound and included in /etc/unbound/conf.d/zzz-ipa.conf
Signed-off-by: Sudhir Menon <sumenon@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Antonio Torres <antorres@redhat.com>
---
ipatests/test_integration/test_edns.py | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/ipatests/test_integration/test_edns.py b/ipatests/test_integration/test_edns.py
index b42570ffa2c1cba8271ff08e084da0107e57d054..dd046f226926d09074d8d6ce536999c5d452fcc4 100644
--- a/ipatests/test_integration/test_edns.py
+++ b/ipatests/test_integration/test_edns.py
@@ -247,6 +247,7 @@ class TestDNSOverTLS(IntegrationTest):
class TestDNS_DoT(TestDNS):
+
@classmethod
def install(cls, mh):
tasks.install_packages(cls.master, ['*ipa-server-encrypted-dns'])
@@ -255,3 +256,20 @@ class TestDNS_DoT(TestDNS):
"--dot-forwarder", "1.1.1.1#cloudflare-dns.com"
]
tasks.install_master(cls.master, extra_args=args)
+
+ def test_check_dot_forwarder_added_in_ipa_conf(self):
+ """
+ This test checks that forwarders is listed in
+ dnsserver-show command and also the dot forwarder is
+ added to unbound and included in
+ /etc/unbound/conf.d/zzz-ipa.conf
+ """
+ msg = 'Forwarders: 127.0.0.55'
+ cmd1 = self.master.run_command(
+ ["ipa", "dnsserver-show", self.master.hostname]
+ )
+ assert msg in cmd1.stdout_text
+ contents = self.master.get_file_contents(
+ paths.UNBOUND_CONF, encoding='utf-8'
+ )
+ assert 'forward-addr: 1.1.1.1#cloudflare-dns.com' in contents
--
2.49.0

View File

@ -0,0 +1,147 @@
From 777f4c0ed631f70b64f6a972e7e6cb140155ef1f Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Thu, 8 May 2025 13:55:34 -0400
Subject: [PATCH] Fix some issues identified by a static analyzer
Remove resource leak when reading the IPA config in ipa-getkeytab
Free popt in ipa-getkeytab
Initialize ret in ipa-otpd/passkey.c
Use the correct free function in util/ipa_krb5.c
Related: https://pagure.io/freeipa/issue/9468
Fixes: https://pagure.io/freeipa/issue/9365
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: David Hanina <dhanina@redhat.com>
---
client/ipa-getkeytab.c | 13 ++++++++++++-
daemons/ipa-otpd/passkey.c | 2 +-
util/ipa_krb5.c | 2 +-
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/client/ipa-getkeytab.c b/client/ipa-getkeytab.c
index 228b981c2c38c5f9227d84cbae20f598564b5dcf..8ca4b8130cd668cbbc03e969399b5fe47ce42f1e 100644
--- a/client/ipa-getkeytab.c
+++ b/client/ipa-getkeytab.c
@@ -866,6 +866,7 @@ static int read_ipa_config(struct ipa_config **ipacfg)
(*ipacfg)->domain = ini_get_string_config_value(obj, &ret);
}
+ ini_config_destroy(cfgctx);
return 0;
}
@@ -984,7 +985,7 @@ int main(int argc, const char *argv[])
krb5_context krbctx;
krb5_ccache ccache;
krb5_principal uprinc = NULL;
- krb5_principal sprinc;
+ krb5_principal sprinc = NULL;
krb5_error_code krberr;
struct keys_container keys = { 0 };
krb5_keytab kt;
@@ -1026,6 +1027,7 @@ int main(int argc, const char *argv[])
fprintf(stdout, "%s\n", enc);
}
ipa_krb5_free_ktypes(krbctx, ktypes);
+ poptFreeContext(pc);
exit (0);
}
@@ -1033,6 +1035,7 @@ int main(int argc, const char *argv[])
if (!quiet) {
poptPrintUsage(pc, stderr, 0);
}
+ poptFreeContext(pc);
exit(2);
}
@@ -1041,12 +1044,14 @@ int main(int argc, const char *argv[])
if (!quiet) {
poptPrintUsage(pc, stderr, 0);
}
+ poptFreeContext(pc);
exit(2);
}
if (askbindpw) {
bindpw = ask_password(krbctx, _("Enter LDAP password"), NULL, false);
if (!bindpw) {
+ poptFreeContext(pc);
exit(2);
}
}
@@ -1056,6 +1061,7 @@ int main(int argc, const char *argv[])
_("Bind password required when using a bind DN (-w or -W).\n"));
if (!quiet)
poptPrintUsage(pc, stderr, 0);
+ poptFreeContext(pc);
exit(10);
}
@@ -1064,6 +1070,7 @@ int main(int argc, const char *argv[])
"and bind DN simultaneously.\n"));
if (!quiet)
poptPrintUsage(pc, stderr, 0);
+ poptFreeContext(pc);
exit(2);
}
@@ -1071,6 +1078,7 @@ int main(int argc, const char *argv[])
fprintf(stderr, _("Invalid SASL bind mechanism\n"));
if (!quiet)
poptPrintUsage(pc, stderr, 0);
+ poptFreeContext(pc);
exit(2);
}
@@ -1083,8 +1091,10 @@ int main(int argc, const char *argv[])
"simultaneously.\n"));
if (!quiet)
poptPrintUsage(pc, stderr, 0);
+ poptFreeContext(pc);
exit(2);
}
+ poptFreeContext(pc);
if (server && (strcasecmp(server, "_srv_") == 0)) {
struct srvrec *srvrecs, *srv;
@@ -1119,6 +1129,7 @@ int main(int argc, const char *argv[])
/* Discovery failed, fall through to option methods */
server = NULL;
}
+ free(ipacfg);
}
if (!server && !ldap_uri) {
diff --git a/daemons/ipa-otpd/passkey.c b/daemons/ipa-otpd/passkey.c
index 8351f0fcf9e2245a83563eefe2c17b04c5b9f4e3..ad3c45467ba9af46cf2e333e2dbfd938c8c8d643 100644
--- a/daemons/ipa-otpd/passkey.c
+++ b/daemons/ipa-otpd/passkey.c
@@ -307,7 +307,7 @@ bool is_passkey(struct otpd_queue_item *item)
static json_t *ipa_passkey_to_json_array(char **ipa_passkey)
{
- int ret;
+ int ret = 0;
const char *sep;
char *start;
size_t c;
diff --git a/util/ipa_krb5.c b/util/ipa_krb5.c
index bb98ab897cf8ea933c025bdb9abf7d394cae4583..0087e53e689fc4dc5549908b3eadd6d963d94489 100644
--- a/util/ipa_krb5.c
+++ b/util/ipa_krb5.c
@@ -80,7 +80,7 @@ static krb5_error_code ipa_get_random_salt(krb5_context krbctx,
void
ipa_krb5_free_ktypes(krb5_context context, krb5_enctype *val)
{
- free(val);
+ krb5_free_enctypes(context, val);
}
/*
--
2.49.0

View File

@ -0,0 +1,30 @@
From a31654e5c4ba61177928abede5885a247365d067 Mon Sep 17 00:00:00 2001
From: PRANAV THUBE <pthube@redhat.com>
Date: Mon, 19 May 2025 14:46:19 +0530
Subject: [PATCH] ipatests: Ignore /run/log/journal in test_uninstallation.py
Update - Add /run/log/journal to the allowed list for leftover files/directories
Fixes: https://pagure.io/freeipa/issue/9788
Signed-off-by: PRANAV THUBE <pthube@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
ipatests/test_integration/test_uninstallation.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/ipatests/test_integration/test_uninstallation.py b/ipatests/test_integration/test_uninstallation.py
index 049c50db536ae1070f5f958e76b12a1518da0aba..f1cc1917dd0f216be3b11803554e86d1d22c3888 100644
--- a/ipatests/test_integration/test_uninstallation.py
+++ b/ipatests/test_integration/test_uninstallation.py
@@ -178,6 +178,7 @@ class TestUninstallCleanup(IntegrationTest):
'/var/log',
'/var/tmp/systemd-private',
'/run/systemd',
+ '/run/log/journal',
'/var/lib/authselect/backups/pre_ipaclient',
'/var/named/data/named.run',
paths.DNSSEC_SOFTHSM_PIN_SO, # See commit eb54814741
--
2.49.0

View File

@ -0,0 +1,77 @@
From 3ba0f6a34cb018a36bc548667e2b433d05da6a45 Mon Sep 17 00:00:00 2001
From: Sudhir Menon <sumenon@redhat.com>
Date: Tue, 6 May 2025 15:37:54 +0530
Subject: [PATCH] ipatests: Tests for krbLastSuccessfulAuth warning
This testcase checks that ipa-healthcheck issues
warning when ipaconfigstring=AllowNThash
Ref: https://github.com/freeipa/freeipa-healthcheck/issues/315
Signed-off-by: Sudhir Menon <sumenon@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
.../test_integration/test_ipahealthcheck.py | 40 ++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/ipatests/test_integration/test_ipahealthcheck.py b/ipatests/test_integration/test_ipahealthcheck.py
index b8ee2884de51a2e0b2dcf2991452486c29c4ed00..0ebc7149f88394bf6b6355adbb88b3ad92697517 100644
--- a/ipatests/test_integration/test_ipahealthcheck.py
+++ b/ipatests/test_integration/test_ipahealthcheck.py
@@ -1526,6 +1526,45 @@ class TestIpaHealthCheck(IntegrationTest):
]
)
+ @pytest.fixture
+ def change_pwd_plugin_default(self):
+ """
+ Fixture to change the password plugin feature
+ to AllowNThash and change it to default
+ """
+ self.master.run_command(
+ [
+ "ipa", "config-mod", "--delattr",
+ "ipaconfigstring=KDC:Disable Last Success"
+ ]
+ )
+ yield
+ self.master.run_command(
+ [
+ "ipa", "config-mod", "--addattr",
+ "ipaconfigstring=KDC:Disable Last Success"
+ ]
+ )
+
+ def test_krbLastSuccessfulAuth_warning(self, change_pwd_plugin_default):
+ """
+ This test checks that warning message is displayed
+ when password plugin feature is modified to
+ AllowNThash
+ """
+ err_msg = (
+ "Last Successful Auth is enabled. "
+ "It may cause performance problems."
+ )
+ returncode, data = run_healthcheck(
+ self.master, "ipahealthcheck.ipa.config",
+ "IPAkrbLastSuccessfulAuth",
+ )
+ assert returncode == 1
+ for check in data:
+ assert check["result"] == "WARNING"
+ assert check["kw"]["msg"] == err_msg
+
@pytest.fixture
def expire_cert_critical(self):
"""
@@ -1553,7 +1592,6 @@ class TestIpaHealthCheck(IntegrationTest):
assert "Expired Certificate" in check["kw"]["items"]
assert check["kw"]["msg"] == msg
-
def test_ipa_healthcheck_expiring(self, restart_service):
"""
There are two overlapping tests for expiring certs, check both.
--
2.49.0

View File

@ -0,0 +1,82 @@
From cef199631109b91462bf25ae8893ca8980faf5bf Mon Sep 17 00:00:00 2001
From: Sudhir Menon <sumenon@redhat.com>
Date: Wed, 21 May 2025 17:20:04 +0530
Subject: [PATCH] ipatests: ipahealthcheck warns for user provided certificates
about to expire
This patch tests that ipa-healthcheck tools warns when IPA server is
installed CALess and user provided certificates are about to expire.
Signed-off-by: Sudhir Menon <sumenon@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
.../test_integration/test_ipahealthcheck.py | 48 +++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/ipatests/test_integration/test_ipahealthcheck.py b/ipatests/test_integration/test_ipahealthcheck.py
index 0ebc7149f88394bf6b6355adbb88b3ad92697517..13fcc3d43545590e025598fcc9c9ee40f62dae76 100644
--- a/ipatests/test_integration/test_ipahealthcheck.py
+++ b/ipatests/test_integration/test_ipahealthcheck.py
@@ -26,6 +26,7 @@ from ipatests.pytest_ipa.integration import tasks
from ipaplatform.paths import paths
from ipaplatform.osinfo import osinfo
from ipaserver.install.installutils import resolve_ip_addresses_nss
+from ipatests.test_integration.test_caless import CALessBase
from ipatests.test_integration.base import IntegrationTest
from pkg_resources import parse_version
from ipatests.test_integration.test_cert import get_certmonger_fs_id
@@ -3135,3 +3136,50 @@ class TestIpaHealthCheckSingleMaster(IntegrationTest):
finally:
# cleanup
tasks.uninstall_master(self.master)
+
+
+class TestIPAHealthcheckWithCALess(CALessBase):
+ """
+ Install CALess server with user provided certificate.
+ """
+ num_replicas = 0
+
+ @classmethod
+ def install(cls, mh):
+ super(TestIPAHealthcheckWithCALess, cls).install(mh)
+ cls.create_pkcs12('ca1/server')
+ cls.prepare_cacert('ca1')
+ result = cls.install_server()
+ assert result.returncode == 0
+
+ @pytest.fixture
+ def expire_cert_warn(self):
+ """
+ Fixture to move the cert to about to expire, by moving the
+ system date using date -s command and revert it back
+ """
+ self.master.run_command(['date','-s', '+11Months10Days'])
+ yield
+ self.master.run_command(['date','-s', '-11Months10Days'])
+ self.master.run_command(['ipactl', 'restart'])
+
+ def test_ipahealthcheck_warns_on_expired_user_certs(self, expire_cert_warn):
+ """
+ This testcase checks that ipa-healthcheck warns
+ on expiring user-provided certificates.
+ """
+ msg = (
+ 'Request id {key} expires in {days} days. '
+ 'You need to manually renew this certificate.'
+ )
+ returncode, data = run_healthcheck(
+ self.master, "ipahealthcheck.ipa.certs",
+ "IPAUserProvidedExpirationCheck",
+ )
+ assert returncode == 1
+ certs = [d["kw"]["key"] for d in data]
+ assert set(certs) == {'HTTP', 'LDAP', 'KDC'}
+ for check in data:
+ assert check["result"] == "WARNING"
+ assert check["kw"]["key"] in ("LDAP", "HTTP", "KDC")
+ assert check["kw"]["msg"] == msg
--
2.49.0

View File

@ -0,0 +1,278 @@
From 0c98af9f70c62da3d3dea02b91a9330a5f9f669a Mon Sep 17 00:00:00 2001
From: David Hanina <dhanina@redhat.com>
Date: Thu, 22 May 2025 08:25:07 +0200
Subject: [PATCH] Warn when UID is out of local ID ranges
Provides simple warning when creating new user with uid out of
all local ranges, as this is the main culprit of breaking Kerberos, by
not generating ipantsecurityidentifier. We don't have to check for
user-mod, because modification never changes ipantsecurityidentifier.
We do not have to check groups, as groups are ignored for ipa without
AD trust. It's reasonable to revisit this in the future for group
creation and warn against groups out of ranges as well as
warn for users with groups without SID, in case AD trust is enabled.
Fixes: https://pagure.io/freeipa/issue/9781
Signed-off-by: David Hanina <dhanina@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
ipalib/messages.py | 12 +++++
ipaserver/plugins/baseuser.py | 29 +++++++++++-
ipatests/test_xmlrpc/test_stageuser_plugin.py | 45 ++++++++++++++++++-
ipatests/test_xmlrpc/test_user_plugin.py | 43 ++++++++++++++++++
.../test_xmlrpc/tracker/stageuser_plugin.py | 22 +++++++++
5 files changed, 148 insertions(+), 3 deletions(-)
diff --git a/ipalib/messages.py b/ipalib/messages.py
index 6a70bbc7556126748cc2ec031fc2af36bfe76f74..a440ca6221d00e6d753c94f87396fc5d7ae177b5 100644
--- a/ipalib/messages.py
+++ b/ipalib/messages.py
@@ -519,6 +519,18 @@ class ServerUpgradeRequired(PublicMessage):
)
+class UidNumberOutOfLocalIDRange(PublicMessage):
+ """
+ **13034** UID Number is out of all local ID Ranges
+ """
+ errno = 13034
+ type = "warning"
+ format = _(
+ "User '%(user)s', with UID Number '%(uidnumber)d' is out of all ID "
+ "Ranges, 'SID' will not be correctly generated."
+ )
+
+
def iter_messages(variables, base):
"""Return a tuple with all subclasses
"""
diff --git a/ipaserver/plugins/baseuser.py b/ipaserver/plugins/baseuser.py
index 22393b8f6c5d3e40b57f11947d0a0358d3a087bc..21e05d4d983502fde76af549594d678d51451e9c 100644
--- a/ipaserver/plugins/baseuser.py
+++ b/ipaserver/plugins/baseuser.py
@@ -23,7 +23,7 @@ from cryptography.hazmat.primitives.serialization import load_pem_public_key
import re
import six
-from ipalib import api, errors, constants
+from ipalib import api, errors, constants, messages
from ipalib import (
Flag, Int, Password, Str, Bool, StrEnum, DateTime, DNParam)
from ipalib.parameters import Principal, Certificate, MAX_UINT32
@@ -198,6 +198,22 @@ def validate_passkey(ugettext, key):
return None
+def is_in_local_idrange(uidnumber):
+ result = api.Command.idrange_find(
+ iparangetype='ipa-local',
+ sizelimit=0,
+ )
+
+ for r in result['result']:
+ if 'ipabaserid' in r:
+ ipabaseid = int(r['ipabaseid'][0])
+ ipaidrangesize = int(r['ipaidrangesize'][0])
+ if ipabaseid <= uidnumber < ipabaseid + ipaidrangesize:
+ return True
+
+ return False
+
+
class baseuser(LDAPObject):
"""
baseuser object.
@@ -621,6 +637,17 @@ class baseuser_add(LDAPCreate):
add_missing_object_class(ldap, 'ipaidpuser', dn,
entry_attrs, update=False)
+ # Check and warn if we're out of local idrange
+ # Skip dynamically assigned uid, old clients say 999
+ uidnumber = entry_attrs.get('uidnumber')
+ if (
+ uidnumber != -1
+ and uidnumber != 999
+ and not is_in_local_idrange(uidnumber)
+ ):
+ self.add_message(messages.UidNumberOutOfLocalIDRange(
+ user=entry_attrs.get('uid'), uidnumber=uidnumber))
+
def post_common_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj.convert_usercertificate_post(entry_attrs, **options)
diff --git a/ipatests/test_xmlrpc/test_stageuser_plugin.py b/ipatests/test_xmlrpc/test_stageuser_plugin.py
index 6ed593fbf24dd2e8ce087625b9cb4c21c9a3c145..dc4940a9983a410640d93efb1185ed4d394a8c2c 100644
--- a/ipatests/test_xmlrpc/test_stageuser_plugin.py
+++ b/ipatests/test_xmlrpc/test_stageuser_plugin.py
@@ -80,9 +80,7 @@ options_def = OrderedDict([
('car license', {u'carlicense': u'abc1234'}),
('SSH key', {u'ipasshpubkey': sshpubkey}),
('manager', {u'manager': u'auser1'}),
- ('user ID number', {u'uidnumber': uid}),
('group ID number', {u'gidnumber': gid}),
- ('UID and GID numbers', {u'uidnumber': uid, u'gidnumber': gid}),
('password', {u'userpassword': u'Secret123'}),
('random password', {u'random': True}),
])
@@ -90,6 +88,13 @@ options_def = OrderedDict([
options_ok = list(options_def.values())
options_ids = list(options_def.keys())
+warn_options_def = OrderedDict([
+ ('user ID number', {u'uidnumber': uid}),
+ ('UID and GID numbers', {u'uidnumber': uid, u'gidnumber': gid}),
+])
+
+warn_options_ok = list(warn_options_def.values())
+warn_options_ids = list(warn_options_def.keys())
@pytest.fixture(scope='class')
def stageduser(request, xmlrpc_setup):
@@ -108,6 +113,12 @@ def stageduser2(request, xmlrpc_setup):
return tracker.make_fixture_activate(request)
+@pytest.fixture(scope='class', params=warn_options_ok, ids=warn_options_ids)
+def warn_stageduser(request, xmlrpc_setup):
+ tracker = StageUserTracker(u'warnuser', u'staged', u'user', **request.param)
+ return tracker.make_fixture_activate(request)
+
+
@pytest.fixture(scope='class')
def user_activated(request, xmlrpc_setup):
tracker = UserTracker(u'suser2', u'staged', u'user')
@@ -273,6 +284,36 @@ class TestStagedUser(XMLRPC_test):
user_activated.delete()
+ def test_warn_create_with_attr(self, warn_stageduser, user, user_activated):
+ """ Tests creating a user with various valid attributes that throw
+ a warning listed in 'warn_options_ok' list"""
+ # create staged user with specified parameters
+ user.ensure_exists() # necessary for manager test
+ warn_stageduser.ensure_missing()
+ command = warn_stageduser.make_create_command()
+ result = command()
+ warn_stageduser.track_create()
+ warn_stageduser.check_create_with_warning(result, (13034,))
+
+ # activate user, verify that specified values were preserved
+ # after activation
+ user_activated.ensure_missing()
+ user_activated = UserTracker(
+ warn_stageduser.uid, warn_stageduser.givenname,
+ warn_stageduser.sn, **warn_stageduser.kwargs)
+ user_activated.create_from_staged(warn_stageduser)
+ command = warn_stageduser.make_activate_command()
+ result = command()
+ user_activated.check_activate(result)
+
+ # verify the staged user does not exist after activation
+ command = warn_stageduser.make_retrieve_command()
+ with raises_exact(errors.NotFound(
+ reason=u'%s: stage user not found' % warn_stageduser.uid)):
+ command()
+
+ user_activated.delete()
+
def test_delete_stageduser(self, stageduser):
stageduser.delete()
diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py
index c0415cae6eb0389c91b804ab28dc2d9f131930c6..420c80213177dc513e10451c0c53506e879ba93f 100644
--- a/ipatests/test_xmlrpc/test_user_plugin.py
+++ b/ipatests/test_xmlrpc/test_user_plugin.py
@@ -826,6 +826,49 @@ class TestCreate(XMLRPC_test):
user_idp.check_create(result, ['ipaidpsub'])
user_idp.delete()
+ def test_out_of_idrange(self):
+ """Test ensuring warning is thrown when uid is out of range"""
+ uidnumber = 2000
+ testuser = UserTracker(
+ name="testwarning", givenname="test",
+ sn="warning", uidnumber=uidnumber
+ )
+ testuser.attrs.update(
+ uidnumber=[u'2000'],
+ )
+ command = testuser.make_create_command()
+ result = command()
+ result_messages = result['messages']
+ assert len(result_messages) == 1
+ assert result_messages[0]['type'] == 'warning'
+ assert result_messages[0]['code'] == 13034
+ testuser.delete()
+
+ def test_in_idrange(self):
+ """Test ensuring no warning is thrown when uid is in range"""
+ result = api.Command.idrange_find(
+ iparangetype='ipa-local',
+ sizelimit=0,
+ )
+
+ assert len(result) >= 1
+ ipabaseid = int(result['result'][0]['ipabaseid'][0])
+ ipaidrangesize = int(result['result'][0]['ipaidrangesize'][0])
+
+ # Take the last valid id, as we're not sure which has not yet been used
+ valid_id = ipabaseid + ipaidrangesize - 1
+ testuser = UserTracker(
+ name="testnowarning", givenname="test",
+ sn="nowarning", uidnumber=valid_id
+ )
+ testuser.attrs.update(
+ uidnumber=[str(valid_id)],
+ )
+ command = testuser.make_create_command()
+ result = command()
+ assert "messages" not in result
+ testuser.delete()
+
@pytest.mark.tier1
class TestUserWithGroup(XMLRPC_test):
diff --git a/ipatests/test_xmlrpc/tracker/stageuser_plugin.py b/ipatests/test_xmlrpc/tracker/stageuser_plugin.py
index 17744a98e9d4a8c5939e9c912b348689674becd9..93157ba3a44362c56a955c3d52d0d18678a9bc5d 100644
--- a/ipatests/test_xmlrpc/tracker/stageuser_plugin.py
+++ b/ipatests/test_xmlrpc/tracker/stageuser_plugin.py
@@ -3,6 +3,7 @@
#
import six
+import copy
from ipalib import api, errors
from ipaplatform.constants import constants as platformconstants
@@ -187,6 +188,27 @@ class StageUserTracker(PasskeyMixin, KerberosAliasMixin, Tracker):
result=self.filter_attrs(expected),
), result)
+ def check_create_with_warning(self, result,
+ warning_codes=(), extra_keys=()):
+ """ Check 'stageuser-add' command result """
+ expected = self.filter_attrs(self.create_keys | set(extra_keys))
+
+ result = copy.deepcopy(result)
+ assert 'messages' in result
+ assert len(result['messages']) == len(warning_codes)
+ codes = [message['code'] for message in result['messages']]
+ for code in warning_codes:
+ assert code in codes
+ codes.pop(codes.index(code))
+
+ del result['messages']
+
+ assert_deepequal(dict(
+ value=self.uid,
+ summary=u'Added stage user "%s"' % self.uid,
+ result=self.filter_attrs(expected),
+ ), result)
+
def check_delete(self, result):
""" Check 'stageuser-del' command result """
assert_deepequal(dict(
--
2.49.0

View File

@ -0,0 +1,80 @@
From 0155718308fa58f43f2ec8df240c1df1c929195e Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Mon, 2 Jun 2025 14:47:48 +0200
Subject: [PATCH] ipatests: fix invalid range creation in
test_ipa_idrange_fix.py
The test is creating a local ID range without rid-base and
secondary-rid-base in order to test the behavior of ipa-idrange-fix.
Since the patch for ticket #9779 it is not possible any more to call
ipa idrange-add for local range without these parameters. The test needs
to create the invalid local range using a direct ldapmodify instead.
Fixes: https://pagure.io/freeipa/issue/9801
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: David Hanina <dhanina@redhat.com>
---
.../test_integration/test_ipa_idrange_fix.py | 39 ++++++++++++-------
1 file changed, 25 insertions(+), 14 deletions(-)
diff --git a/ipatests/test_integration/test_ipa_idrange_fix.py b/ipatests/test_integration/test_ipa_idrange_fix.py
index 0c915bd0931ed11a3aa86c533ee8748aa8a7ec07..6559818d3b290211ed421b652be7a424a3b51052 100644
--- a/ipatests/test_integration/test_ipa_idrange_fix.py
+++ b/ipatests/test_integration/test_ipa_idrange_fix.py
@@ -40,13 +40,18 @@ class TestIpaIdrangeFix(IntegrationTest):
def test_idrange_no_rid_bases(self):
"""Test ipa-idrange-fix command with IDrange with no RID bases."""
- self.master.run_command([
- "ipa",
- "idrange-add",
- "idrange_no_rid_bases",
- "--base-id", '10000',
- "--range-size", '20000',
- ])
+ # Use ldapmodify to create the range without rid bases
+ idrange_ldif = (
+ "dn: cn=idrange_no_rid_bases,cn=ranges,cn=etc,{suffix}\n"
+ "changetype: add\n"
+ "objectclass: top\n"
+ "objectclass: ipaIDrange\n"
+ "objectclass: ipadomainidrange\n"
+ "ipaRangeType: ipa-local\n"
+ "ipaBaseID: 10000\n"
+ "ipaIDRangeSize: 20000\n"
+ ).format(suffix=str(self.master.domain.basedn))
+ tasks.ldapmodify_dm(self.master, idrange_ldif)
result = self.master.run_command(["ipa-idrange-fix", "--unattended"])
expected_text = "RID bases updated for range 'idrange_no_rid_bases'"
@@ -62,13 +67,19 @@ class TestIpaIdrangeFix(IntegrationTest):
previously had a range with RID bases reversed - secondary lower than
primary. It is a valid configuration, so we should fix no-RID range.
"""
- self.master.run_command([
- "ipa",
- "idrange-add",
- "idrange_no_rid_bases",
- "--base-id", '10000',
- "--range-size", '20000',
- ])
+ # Use ldapmodify to create the range without rid bases
+ idrange_ldif = (
+ "dn: cn=idrange_no_rid_bases,cn=ranges,cn=etc,{suffix}\n"
+ "changetype: add\n"
+ "objectclass: top\n"
+ "objectclass: ipaIDrange\n"
+ "objectclass: ipadomainidrange\n"
+ "ipaRangeType: ipa-local\n"
+ "ipaBaseID: 10000\n"
+ "ipaIDRangeSize: 20000\n"
+ ).format(suffix=str(self.master.domain.basedn))
+ tasks.ldapmodify_dm(self.master, idrange_ldif)
+
self.master.run_command([
"ipa",
"idrange-add",
--
2.49.0

View File

@ -218,7 +218,7 @@
Name: %{package_name}
Version: %{IPA_VERSION}
Release: 16%{?rc_version:.%rc_version}%{?dist}
Release: 17%{?rc_version:.%rc_version}%{?dist}
Summary: The Identity, Policy and Audit system
License: GPL-3.0-or-later
@ -314,6 +314,20 @@ Patch0069: 0069-Add-a-check-into-ipa-cert-fix-tool-to-avoid-updating.patch
Patch0070: 0070-Test-fix-for-the-update.patch
Patch0071: 0071-Correct-dnsrecord_-tests-for-raw-structured.patch
Patch0072: 0072-ipa-sidgen-fix-memory-leak-in-ipa_sidgen_add_post_op.patch
Patch0073: 0073-ipa-migrate-remove-replication-state-information.patch
Patch0074: 0074-ipa-migrate-do-not-process-AD-entgries-in-staging-mo.patch
Patch0075: 0075-ipa-migrate-improve-suffix-replacement.patch
Patch0076: 0076-kdb-keep-ipadb_get_connection-from-succeeding-with-n.patch
Patch0077: 0077-ipatests-test_manual_renewal_master_transfer-must-wa.patch
Patch0078: 0078-Require-baserid-and-secondarybaserid.patch
Patch0079: 0079-ipa-config-mod-fix-internalerror-when-setting-an-emp.patch
Patch0080: 0080-ipatests-Test-to-check-dot-forwarders-are-added-to-u.patch
Patch0081: 0081-Fix-some-issues-identified-by-a-static-analyzer.patch
Patch0082: 0082-ipatests-Ignore-run-log-journal-in-test_uninstallati.patch
Patch0083: 0083-ipatests-Tests-for-krbLastSuccessfulAuth-warning.patch
Patch0084: 0084-ipatests-ipahealthcheck-warns-for-user-provided-cert.patch
Patch0085: 0085-Warn-when-UID-is-out-of-local-ID-ranges.patch
Patch0086: 0086-ipatests-fix-invalid-range-creation-in-test_ipa_idra.patch
Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch
%endif
%endif
@ -1966,6 +1980,14 @@ fi
%endif
%changelog
* Wed Jun 04 2025 Florence Blanc-Renaud <flo@redhat.com> - 4.12.2-17
- Resolves: RHEL-95010 [RFE] Give warning when adding user with UID out of any ID range
- Resolves: RHEL-93890 Include latest fixes in python3-ipatests package
- Resolves: RHEL-93887 ipa idrange-add --help should be more clear about required options
- Resolves: RHEL-93483 Unable to modify IPA config; --ipaconfigstring="" causes internal error
- Resolves: RHEL-88834 kdb: ipadb_get_connection() succeeds but returns null LDAP context
- Resolves: RHEL-68800 ipa-migrate with LDIF file from backup of remote server, fails with error 'change collided with another change'
* Tue Apr 29 2025 Florence Blanc-Renaud <flo@redhat.com> - 4.12.2-16
- Resolves: RHEL-88900 [RFE] Add check on CA cert expiry for ipa-cert-fix
- Resolves: RHEL-88037 Server installation: dot-forwarder not added as a forwarder