Bump version to 1.4.3.39-21

- Resolves: RHEL-141419 - (&(cn:dn:=groups)) no longer returns results [rhel-8.10.z]
- Resolves: RHEL-140272 - ipa-healthcheck is complaining about missing or
                          incorrectly configured system indexes. [rhel-8.10.z]
This commit is contained in:
Arun Bansal 2026-01-23 16:02:04 +05:30
parent f40036e368
commit 4b29fe4ce7
3 changed files with 334 additions and 1 deletions

View File

@ -0,0 +1,91 @@
From c160ef5a53f0ae9725790ebcd2667dcda2089f14 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Tue, 28 Oct 2025 10:49:18 -0400
Subject: [PATCH 1/2] Issue 7071 - search filter (&(cn:dn:=groups)) no longer
returns results
Description:
When processing an "and" filter and it only contains one filter component then
the logic in the code breaks down and the filter is seen as not matching.
The logic breaks down because we are not setting "nomatch" after the access
check is successful. If there are two components then it works fine
because we do the access check on the first filter component and set that
the access check was done(access_check_done), but "nomatch" is not set yet.
So when the next filter component is checked for access we see that the access
check was done and then we set "nomatch".
To recap we always need to set "nomatch" when the access check is successful
in order to handle the case where an "and" fitler only has one component.
Relates: https://github.com/389ds/389-ds-base/issues/7071
Reviewed by: spichugi(Thanks!)
---
.../tests/suites/filter/complex_filters_test.py | 17 ++++++++++++++---
ldap/servers/slapd/filterentry.c | 7 ++++++-
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/dirsrvtests/tests/suites/filter/complex_filters_test.py b/dirsrvtests/tests/suites/filter/complex_filters_test.py
index 62be27381..3180ab229 100644
--- a/dirsrvtests/tests/suites/filter/complex_filters_test.py
+++ b/dirsrvtests/tests/suites/filter/complex_filters_test.py
@@ -25,8 +25,15 @@ AND_FILTERS = [("(&(uid=uid1)(sn=last1)(givenname=first1))", 1),
("(&(uid=*)(&(sn=last3)(givenname=*)))", 1),
("(&(uid=uid5)(&(&(sn=*))(&(givenname=*))))", 1),
("(&(objectclass=*)(uid=*)(sn=last*))", 5),
- ("(&(objectclass=*)(uid=*)(sn=last1))", 1)]
-
+ ("(&(objectclass=*)(uid=*)(sn=last1))", 1),
+ ("(&(sn:dn:=last1))", 1),
+ ("(&(sn:dn:=last1)(givenname:dn:=first1))", 1),
+ ("(&(sn:dn:=last1)(givenname=first1))", 1),
+ ("(&(sn=last1)(givenname=first1)(uid:dn:=uid1))", 1),
+ ("(&(uid:dn:=uid1))", 1),
+ ("(&(uid:dn:=uid1)(cn:dn:=full1))", 1),
+ ("(&(uid:dn:=uid1)(givenname:dn:=first1))", 1),
+ ("(&(uid:dn:=uid1)(givenname:dn:=first1)(cn:dn:=full1))", 1)]
OR_FILTERS = [("(|(uid=uid1)(sn=last1)(givenname=first1))", 1),
("(|(uid=uid1)(|(sn=last1)(givenname=first1)))", 1),
("(|(uid=uid1)(|(|(sn=last1))(|(givenname=first1))))", 1),
@@ -51,7 +58,11 @@ ZERO_AND_FILTERS = [("(&(uid=uid1)(sn=last1)(givenname=NULL))", 0),
("(&(uid=uid1)(&(sn=last1)(givenname=NULL)))", 0),
("(&(uid=uid1)(&(&(sn=last1))(&(givenname=NULL))))", 0),
("(&(uid=uid1)(&(&(sn=last1))(&(givenname=NULL)(sn=*)))(|(sn=NULL)))", 0),
- ("(&(uid=uid1)(&(&(sn=last*))(&(givenname=first*)))(&(sn=NULL)))", 0)]
+ ("(&(uid=uid1)(&(&(sn=last*))(&(givenname=first*)))(&(sn=NULL)))", 0),
+ ("(&(uid:dn:=not_uid))", 0),
+ ("(&(uid:dn:=not_uid)(cn:dn:=full1))", 0),
+ ("(&(uid:dn:=uid1)(givenname:dn:=not_first1))", 0),
+ ("(&(uid:dn:=uid1)(givenname:dn:=first1)(cn:dn:=not_full1))", 0)]
ZERO_OR_FILTERS = [("(|(uid=NULL)(sn=NULL)(givenname=NULL))", 0),
("(|(uid=NULL)(|(sn=NULL)(givenname=NULL)))", 0),
diff --git a/ldap/servers/slapd/filterentry.c b/ldap/servers/slapd/filterentry.c
index cae5c7edc..1c513fe62 100644
--- a/ldap/servers/slapd/filterentry.c
+++ b/ldap/servers/slapd/filterentry.c
@@ -1011,13 +1011,18 @@ vattr_test_filter_list_and(
nomatch = -1;
break;
} else {
+ /* We have a match, but we need to check access */
if (!verify_access || (*access_check_done)) {
nomatch = 0;
} else {
/* check access */
rc = slapi_vattr_filter_test_ext_internal(pb, e, f, verify_access, 1, access_check_done);
- if (rc)
+ if (rc) {
undefined = rc;
+ } else {
+ /* Access is good so mark this as a match */
+ nomatch = 0;
+ }
}
}
}
--
2.52.0

View File

@ -0,0 +1,235 @@
From 05ce84ae76e0e71381bcc7b8491a74e7edcd888f Mon Sep 17 00:00:00 2001
From: Viktor Ashirov <vashirov@redhat.com>
Date: Tue, 20 Jan 2026 09:52:47 +0100
Subject: [PATCH 2/2] Issue 7189 - DSBLE0007 generates incorrect remediation
commands for scan limits
Bug Description:
The generated dsconf commands for fixing missing system indexes had two issues:
1. The --add-scanlimit value was not quoted, causing the shell to interpret
"limit=5000 type=eq flags=AND" as multiple arguments instead of a single
value, resulting in "unrecognized arguments: type=eq flags=AND" error.
2. When both matching rule and scanlimit were missing, two separate commands
were generated where the second would fail because the matching rule was
already added by the first command.
Fix Description:
1. Quote the scanlimit value in all remediation commands
2. Combine matching rule and scanlimit fixes into a single command when
both are missing for the same index instead of expected_scanlimit)
Fixes: https://github.com/389ds/389-ds-base/issues/7189
Reviewed by: @progier389, @droideck (Thanks!)
---
.../healthcheck/health_system_indexes_test.py | 126 ++++++++++++++++++
src/lib389/lib389/backend.py | 39 +++---
2 files changed, 147 insertions(+), 18 deletions(-)
diff --git a/dirsrvtests/tests/suites/healthcheck/health_system_indexes_test.py b/dirsrvtests/tests/suites/healthcheck/health_system_indexes_test.py
index 1700ba207..f25de4214 100644
--- a/dirsrvtests/tests/suites/healthcheck/health_system_indexes_test.py
+++ b/dirsrvtests/tests/suites/healthcheck/health_system_indexes_test.py
@@ -406,6 +406,132 @@ def test_retrocl_plugin_missing_matching_rule(topology_st, retrocl_plugin_enable
run_healthcheck_and_flush_log(topology_st, standalone, json=True, searched_code=JSON_OUTPUT)
+def test_missing_scanlimit(topology_st, log_buffering_enabled):
+ """Check if healthcheck returns DSBLE0007 code when parentId index is missing scanlimit
+
+ :id: 40e1bf6a-2397-459b-bdf3-f787ca118b86
+ :setup: Standalone instance
+ :steps:
+ 1. Create DS instance
+ 2. Remove nsIndexIDListScanLimit from parentId index
+ 3. Use healthcheck without --json option
+ 4. Use healthcheck with --json option
+ 5. Verify the remediation command has properly quoted scanlimit
+ 6. Re-add the scanlimit
+ 7. Use healthcheck without --json option
+ 8. Use healthcheck with --json option
+ :expectedresults:
+ 1. Success
+ 2. Success
+ 3. healthcheck reports DSBLE0007 code and related details
+ 4. healthcheck reports DSBLE0007 code and related details
+ 5. The scanlimit value is quoted in the remediation command
+ 6. Success
+ 7. healthcheck reports no issues found
+ 8. healthcheck reports no issues found
+ """
+
+ RET_CODE = "DSBLE0007"
+ PARENTID_DN = "cn=parentid,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config"
+ SCANLIMIT_VALUE = "limit=5000 type=eq flags=AND"
+
+ standalone = topology_st.standalone
+
+ log.info("Remove nsIndexIDListScanLimit from parentId index")
+ parentid_index = Index(standalone, PARENTID_DN)
+ parentid_index.remove("nsIndexIDListScanLimit", SCANLIMIT_VALUE)
+
+ run_healthcheck_and_flush_log(topology_st, standalone, json=False, searched_code=RET_CODE)
+
+ # Verify the remediation command has properly quoted scanlimit
+ args = FakeArgs()
+ args.instance = standalone.serverid
+ args.verbose = standalone.verbose
+ args.list_errors = False
+ args.list_checks = False
+ args.exclude_check = []
+ args.check = ["backends"]
+ args.dry_run = False
+ args.json = False
+ health_check_run(standalone, topology_st.logcap.log, args)
+ # Check that the scanlimit is quoted in the output
+ assert topology_st.logcap.contains('--add-scanlimit "limit=5000 type=eq flags=AND"')
+ log.info("Verified scanlimit is properly quoted in remediation command")
+ topology_st.logcap.flush()
+
+ run_healthcheck_and_flush_log(topology_st, standalone, json=True, searched_code=RET_CODE)
+
+ log.info("Re-add the nsIndexIDListScanLimit")
+ parentid_index = Index(standalone, PARENTID_DN)
+ parentid_index.add("nsIndexIDListScanLimit", SCANLIMIT_VALUE)
+
+ run_healthcheck_and_flush_log(topology_st, standalone, json=False, searched_code=CMD_OUTPUT)
+ run_healthcheck_and_flush_log(topology_st, standalone, json=True, searched_code=JSON_OUTPUT)
+
+
+def test_missing_matching_rule_and_scanlimit(topology_st, log_buffering_enabled):
+ """Check if healthcheck generates a single combined command when both matching rule and scanlimit are missing
+
+ :id: af8214ad-5e4c-422a-8f74-3e99227551df
+ :setup: Standalone instance
+ :steps:
+ 1. Create DS instance
+ 2. Remove both integerOrderingMatch and nsIndexIDListScanLimit from parentId index
+ 3. Use healthcheck and verify a single combined command is generated
+ 4. Re-add the matching rule and scanlimit
+ 5. Use healthcheck without --json option
+ 6. Use healthcheck with --json option
+ :expectedresults:
+ 1. Success
+ 2. Success
+ 3. healthcheck reports DSBLE0007 and generates a single command with both --add-mr and --add-scanlimit
+ 4. Success
+ 5. healthcheck reports no issues found
+ 6. healthcheck reports no issues found
+ """
+
+ RET_CODE = "DSBLE0007"
+ PARENTID_DN = "cn=parentid,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config"
+ SCANLIMIT_VALUE = "limit=5000 type=eq flags=AND"
+
+ standalone = topology_st.standalone
+
+ log.info("Remove both integerOrderingMatch and nsIndexIDListScanLimit from parentId index")
+ parentid_index = Index(standalone, PARENTID_DN)
+ parentid_index.remove("nsMatchingRule", "integerOrderingMatch")
+ parentid_index.remove("nsIndexIDListScanLimit", SCANLIMIT_VALUE)
+
+ # Run healthcheck and verify combined command
+ args = FakeArgs()
+ args.instance = standalone.serverid
+ args.verbose = standalone.verbose
+ args.list_errors = False
+ args.list_checks = False
+ args.exclude_check = []
+ args.check = ["backends"]
+ args.dry_run = False
+ args.json = False
+ health_check_run(standalone, topology_st.logcap.log, args)
+
+ # Verify DSBLE0007 is reported
+ assert topology_st.logcap.contains(RET_CODE)
+ log.info("healthcheck returned code: %s" % RET_CODE)
+
+ # Verify a single combined command is generated with both --add-mr and --add-scanlimit
+ assert topology_st.logcap.contains('--add-mr integerOrderingMatch --add-scanlimit "limit=5000 type=eq flags=AND"')
+ log.info("Verified combined command with both --add-mr and --add-scanlimit")
+
+ topology_st.logcap.flush()
+
+ log.info("Re-add the integerOrderingMatch matching rule and scanlimit")
+ parentid_index = Index(standalone, PARENTID_DN)
+ parentid_index.add("nsMatchingRule", "integerOrderingMatch")
+ parentid_index.add("nsIndexIDListScanLimit", SCANLIMIT_VALUE)
+
+ run_healthcheck_and_flush_log(topology_st, standalone, json=False, searched_code=CMD_OUTPUT)
+ run_healthcheck_and_flush_log(topology_st, standalone, json=True, searched_code=JSON_OUTPUT)
+
+
def test_multiple_missing_indexes(topology_st, log_buffering_enabled):
"""Check if healthcheck returns DSBLE0007 code when multiple system indexes are missing
diff --git a/src/lib389/lib389/backend.py b/src/lib389/lib389/backend.py
index 14b64d1d3..3cea0df36 100644
--- a/src/lib389/lib389/backend.py
+++ b/src/lib389/lib389/backend.py
@@ -602,7 +602,7 @@ class Backend(DSLdapObject):
if expected_config.get('matching_rule'):
cmd += f" --matching-rule {expected_config['matching_rule']}"
if expected_config.get('scanlimit'):
- cmd += f" --add-scanlimit {expected_config['scanlimit']}"
+ cmd += f" --add-scanlimit \"{expected_config['scanlimit']}\""
remediation_commands.append(cmd)
reindex_attrs.add(attr_name) # New index needs reindexing
else:
@@ -624,28 +624,31 @@ class Backend(DSLdapObject):
remediation_commands.append(cmd)
reindex_attrs.add(attr_name)
- # Check matching rules
+ # Check matching rules and scanlimit together to generate a single combined command
expected_mr = expected_config.get('matching_rule')
+ expected_scanlimit = expected_config.get('scanlimit')
+
+ missing_mr = False
if expected_mr:
actual_mrs_lower = [mr.lower() for mr in actual_mrs]
if expected_mr.lower() not in actual_mrs_lower:
discrepancies.append(f"Index {attr_name} missing matching rule: {expected_mr}")
- # Add the missing matching rule
- cmd = f"dsconf YOUR_INSTANCE backend index set {bename} --attr {attr_name} --add-mr {expected_mr}"
- remediation_commands.append(cmd)
- reindex_attrs.add(attr_name)
-
- # Check fine grain definitions for parentid ONLY
- expected_scanlimit = expected_config.get('scanlimit')
- if (attr_name.lower() == "parentid") and expected_scanlimit and (len(actual_scanlimit) == 0):
- discrepancies.append(f"Index {attr_name} missing fine grain definition of IDs limit: {expected_mr}")
- # Add the missing scanlimit
- if expected_mr:
- cmd = f"dsconf YOUR_INSTANCE backend index set {bename} --attr {attr_name} --add-mr {expected_mr} --add-scanlimit {expected_scanlimit}"
- else:
- cmd = f"dsconf YOUR_INSTANCE backend index set {bename} --attr {attr_name} --add-scanlimit {expected_scanlimit}"
- remediation_commands.append(cmd)
- reindex_attrs.add(attr_name)
+ missing_mr = True
+
+ missing_scanlimit = False
+ if expected_scanlimit and (len(actual_scanlimit) == 0):
+ discrepancies.append(f"Index {attr_name} missing fine grain definition of IDs limit: {expected_scanlimit}")
+ missing_scanlimit = True
+
+ # Generate a single combined command for all missing items
+ if missing_mr or missing_scanlimit:
+ cmd = f"dsconf YOUR_INSTANCE backend index set {bename} --attr {attr_name}"
+ if missing_mr:
+ cmd += f" --add-mr {expected_mr}"
+ if missing_scanlimit:
+ cmd += f" --add-scanlimit \"{expected_scanlimit}\""
+ remediation_commands.append(cmd)
+ reindex_attrs.add(attr_name)
except Exception as e:
self._log.debug(f"_lint_system_indexes - Error checking index {attr_name}: {e}")
--
2.52.0

View File

@ -52,7 +52,7 @@ ExcludeArch: i686
Summary: 389 Directory Server (base)
Name: 389-ds-base
Version: 1.4.3.39
Release: %{?relprefix}20%{?prerel}%{?dist}
Release: %{?relprefix}21%{?prerel}%{?dist}
License: GPL-3.0-or-later WITH GPL-3.0-389-ds-base-exception AND (0BSD OR Apache-2.0 OR MIT) AND (Apache-2.0 OR Apache-2.0 WITH LLVM-exception OR MIT) AND (Apache-2.0 OR BSD-2-Clause OR MIT) AND (Apache-2.0 OR BSL-1.0) AND (Apache-2.0 OR LGPL-2.1-or-later OR MIT) AND (Apache-2.0 OR MIT OR Zlib) AND (Apache-2.0 OR MIT) AND (MIT OR Apache-2.0) AND Unicode-3.0 AND (MIT OR Unlicense) AND Apache-2.0 AND BSD-3-Clause AND MIT AND MPL-2.0
URL: https://www.port389.org
Group: System Environment/Daemons
@ -373,6 +373,8 @@ Patch72: 0072-Issue-6966-2nd-On-large-DB-unlimited-IDL-scan-limit-.patc
Patch73: 0073-Issue-7056-DSBLE0007-doesn-t-generate-remediation-st.patch
Patch74: 0074-Issue-7172-Index-ordering-mismatch-after-upgrade-717.patch
Patch75: 0075-Issue-7172-2nd-Index-ordering-mismatch-after-upgrade.patch
Patch76: 0076-Issue-7071-search-filter-cn-dn-groups-no-longer-retu.patch
Patch77: 0077-Issue-7189-DSBLE0007-generates-incorrect-remediation.patch
#Patch100: cargo.patch
@ -998,6 +1000,11 @@ exit 0
%doc README.md
%changelog
* Fri Jan 23 2026 Arun Bansal <arbansal@redhat.com> - 1.4.3.39-21
- Resolves: RHEL-141419 - (&(cn:dn:=groups)) no longer returns results [rhel-8.10.z]
- Resolves: RHEL-140272 - ipa-healthcheck is complaining about missing or
incorrectly configured system indexes. [rhel-8.10.z]
* Tue Jan 13 2026 Arun Bansal <arbansal@redhat.com> - 1.4.3.39-20
- Resolves: RHEL-140086 - Upgrading IDM to latest version: 389-ds-base and ipa-server breaks replication [rhel-8.10.z]