Summary
The shipped cn=Referential Integrity,cn=Plugins,cn=config entry registers the plugin for four plugin types only: postOperationDelete, postOperationModifyDN, subordinateModifyDN and subordinateDelete. The check-references feature of the plugin runs in its preOperationAdd and preOperationModify hooks, and the definition's default for plugin-type includes those two types. On the shipped entry, setting check-references:true therefore checks nothing: the plugin is never invoked for add and modify operations, and the server reports no problem.
Cause
- Template:
opendj-server-legacy/resource/config/config.ldif, lines 1387-1390, four ds-cfg-plugin-type values.
- Definition default:
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/ReferentialIntegrityPluginConfiguration.xml, lines 55-66, six values including preoperationadd and preoperationmodify.
- The checks live in
ReferentialIntegrityPlugin.doPreOperation(PreOperationAddOperation) (line 1054) and doPreOperation(PreOperationModifyOperation) (line 985), both gated by isCheckReferences(). The plugin is only invoked for the operation types listed in plugin-type.
ReferentialIntegrityPlugin.isConfigurationAcceptable accepts check-references:true without the pre-operation types and does not warn.
A plugin created with dsconfig create-plugin --type referential-integrity gets all six types from the default, so only the shipped entry, and instances upgraded from earlier versions, are affected.
Steps to reproduce
dsconfig set-plugin-prop --plugin-name "Referential Integrity" \
--set enabled:true --set check-references:true \
-h localhost -p 4444 -D "cn=Directory Manager" -w password -X -n
ldapmodify -h localhost -p 1389 -D "cn=Directory Manager" -w password <<EOF
dn: cn=group,ou=Groups,dc=example,dc=com
changetype: modify
add: member
member: uid=does-not-exist,ou=People,dc=example,dc=com
EOF
Result: the modification succeeds and the dangling reference is stored.
Expected: the modification is rejected with CONSTRAINT_VIOLATION, as it is on a plugin entry that lists preOperationAdd and preOperationModify.
Proposal
- Add
preOperationAdd and preOperationModify to the shipped entry in config.ldif.
- Add an upgrade task, keyed at the release that ships the fix, that adds the two values to the existing entry when they are missing.
plugin-type requires a component restart, and the plugin is disabled by default, so the change takes effect the next time the plugin is enabled or the server restarts. The upgrade tool reads config.ldif with its own schema (UpgradeUtils.getUpgradeSchema()), which matches attributes it does not declare case-exactly, and dsconfig stores plugin types in lower case (preoperationadd). Without declaring ds-cfg-plugin-type with caseIgnoreMatch there, the task would add preOperationAdd next to a preoperationadd an administrator already added by hand.
- Make
isConfigurationAcceptable reject check-references:true when plugin-type lacks preOperationAdd or preOperationModify, so a misconfigured entry is reported instead of silently checking nothing. The upgrade task heals every referential integrity plugin entry, so after an upgrade only an entry edited by hand can fail to initialize.
- Say in the "Configuring Referential Integrity" section of the developer guide (
chap-groups.adoc) that check-references needs the preOperationAdd and preOperationModify plugin types.
Related
Summary
The shipped
cn=Referential Integrity,cn=Plugins,cn=configentry registers the plugin for four plugin types only:postOperationDelete,postOperationModifyDN,subordinateModifyDNandsubordinateDelete. Thecheck-referencesfeature of the plugin runs in itspreOperationAddandpreOperationModifyhooks, and the definition's default forplugin-typeincludes those two types. On the shipped entry, settingcheck-references:truetherefore checks nothing: the plugin is never invoked for add and modify operations, and the server reports no problem.Cause
opendj-server-legacy/resource/config/config.ldif, lines 1387-1390, fourds-cfg-plugin-typevalues.opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/ReferentialIntegrityPluginConfiguration.xml, lines 55-66, six values includingpreoperationaddandpreoperationmodify.ReferentialIntegrityPlugin.doPreOperation(PreOperationAddOperation)(line 1054) anddoPreOperation(PreOperationModifyOperation)(line 985), both gated byisCheckReferences(). The plugin is only invoked for the operation types listed inplugin-type.ReferentialIntegrityPlugin.isConfigurationAcceptableacceptscheck-references:truewithout the pre-operation types and does not warn.A plugin created with
dsconfig create-plugin --type referential-integritygets all six types from the default, so only the shipped entry, and instances upgraded from earlier versions, are affected.Steps to reproduce
Result: the modification succeeds and the dangling reference is stored.
Expected: the modification is rejected with
CONSTRAINT_VIOLATION, as it is on a plugin entry that listspreOperationAddandpreOperationModify.Proposal
preOperationAddandpreOperationModifyto the shipped entry inconfig.ldif.plugin-typerequires a component restart, and the plugin is disabled by default, so the change takes effect the next time the plugin is enabled or the server restarts. The upgrade tool readsconfig.ldifwith its own schema (UpgradeUtils.getUpgradeSchema()), which matches attributes it does not declare case-exactly, anddsconfigstores plugin types in lower case (preoperationadd). Without declaringds-cfg-plugin-typewithcaseIgnoreMatchthere, the task would addpreOperationAddnext to apreoperationaddan administrator already added by hand.isConfigurationAcceptablerejectcheck-references:truewhenplugin-typelackspreOperationAddorpreOperationModify, so a misconfigured entry is reported instead of silently checking nothing. The upgrade task heals every referential integrity plugin entry, so after an upgrade only an entry edited by hand can fail to initialize.chap-groups.adoc) thatcheck-referencesneeds thepreOperationAddandpreOperationModifyplugin types.Related
check-references:truewith the four shipped plugin types, and auniqueMembervalue pointing to a deleted user is accepted.