Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* Copyright 2008-2010 Sun Microsystems, Inc.
* Portions Copyright 2011-2016 ForgeRock AS.
* Portions copyright 2011 profiq s.r.o.
* Portions copyright 2026 3A Systems, LLC.
*/
package org.opends.server.plugins;

Expand Down Expand Up @@ -991,10 +992,9 @@ public PluginResult.PreOperation doPreOperation(
}

final List<Modification> mods = modifyOperation.getModifications();
final Entry entry = modifyOperation.getModifiedEntry();

/* Make sure the entry belongs to one of the configured naming contexts. */
DN entryDN = entry.getName();
DN entryDN = modifyOperation.getEntryDN();
DN entryBaseDN = getEntryBaseDN(entryDN);
if (entryBaseDN == null)
{
Expand All @@ -1009,14 +1009,35 @@ public PluginResult.PreOperation doPreOperation(
if (modType != ModificationType.ADD
&& modType != ModificationType.REPLACE)
{
break;
continue;
}

Attribute modifiedAttribute = entry.getAttribute(mod.getAttribute().getAttributeDescription());
if (modifiedAttribute != null)
Attribute modifiedAttribute = mod.getAttribute();
if (modifiedAttribute != null && !modifiedAttribute.isEmpty())
{
// Only enforce referential integrity on attributes that this plugin is configured to manage.
final AttributeType modifiedAttrType = modifiedAttribute.getAttributeDescription().getAttributeType();
boolean isManagedAttributeType = false;
if (modifiedAttrType != null && attributeTypes != null)
{
for (AttributeType configuredType : attributeTypes)
{
if (modifiedAttrType.equals(configuredType)
|| modifiedAttrType.isSubTypeOf(configuredType))
{
isManagedAttributeType = true;
break;
}
}
}

if (!isManagedAttributeType)
{
// Skip integrity checks for attributes not configured for this plugin.
continue;
}
PluginResult.PreOperation result =
isIntegrityMaintained(modifiedAttribute, entryDN, entryBaseDN);
isIntegrityMaintained(modifiedAttribute, entryDN, entryBaseDN);
if (result.getResultCode() != ResultCode.SUCCESS)
{
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* Copyright 2008-2010 Sun Microsystems, Inc.
* Portions copyright 2011 profiq s.r.o.
* Portions Copyright 2014-2016 ForgeRock AS.
* Portions copyright 2026 3A Systems, LLC.
*/
package org.opends.server.plugins;

Expand Down Expand Up @@ -1829,4 +1830,60 @@ public void testEnforceIntegrityModifyGroupAddMemberNC() throws Exception
"member", "uid=user.1,ou=people,ou=dept,o=test");
assertEquals(modOperation.getResultCode(), ResultCode.SUCCESS);
}

@Test
public void testEnforceIntegrityModifyGroupAddMissingUniqueMember() throws Exception
{
replaceAttrEntry(configDN, "ds-cfg-enabled", "false");
replaceAttrEntry(configDN, dsConfigPluginType,
"postoperationdelete",
"postoperationmodifydn",
"subordinatemodifydn",
"subordinatedelete",
"preoperationadd",
"preoperationmodify");
addAttrEntry(configDN, dsConfigBaseDN, "dc=example,dc=com");
replaceAttrEntry(configDN, dsConfigEnforceIntegrity, "true");
replaceAttrEntry(configDN, dsConfigAttrType, "uniquemember");
addAttrEntry(configDN, dsConfigAttrFiltMapping,
"uniquemember:(objectclass=person)");
replaceAttrEntry(configDN, "ds-cfg-enabled", "true");

ModifyOperation modOperation = addAttrEntry(DN.valueOf(ugroup),
"uniquemember", "uid=user.100,ou=people,ou=dept,dc=example,dc=com");
assertEquals(modOperation.getResultCode(), ResultCode.CONSTRAINT_VIOLATION);
}

@Test
public void testEnforceIntegrityModifyGroupAddMissingUniqueMemberWithPriorDelete() throws Exception
{
// Configure the plugin in the same way as for the single-ADD test.
replaceAttrEntry(configDN, "ds-cfg-enabled", "false");
replaceAttrEntry(configDN, dsConfigPluginType,
"postoperationdelete",
"postoperationmodifydn",
"subordinatemodifydn",
"subordinatedelete",
"preoperationadd",
"preoperationmodify");
addAttrEntry(configDN, dsConfigBaseDN, "dc=example,dc=com");
replaceAttrEntry(configDN, dsConfigEnforceIntegrity, "true");
replaceAttrEntry(configDN, dsConfigAttrType, "uniquemember");
addAttrEntry(configDN, dsConfigAttrFiltMapping,
"uniquemember:(objectclass=person)");
replaceAttrEntry(configDN, "ds-cfg-enabled", "true");

// Ensure 'description' exists on ugroup so the DELETE modification succeeds.
addAttrEntry(DN.valueOf(ugroup), "description", "test description");
// Build a modify request with a non-ADD/REPLACE modification first,
// followed by an ADD of a uniquemember referencing a missing DN.
final ModifyRequest modifyRequest = Requests.newModifyRequest(DN.valueOf(ugroup));
modifyRequest.addModification(DELETE, "description");
modifyRequest.addModification(ADD, "uniquemember",
"uid=user.100,ou=people,ou=dept,dc=example,dc=com");

final InternalClientConnection connection = getRootConnection();
final ModifyOperation multiModOperation = connection.processModify(modifyRequest);
assertEquals(multiModOperation.getResultCode(), ResultCode.CONSTRAINT_VIOLATION);
}
}
Loading