[#1118] Register the shipped Referential Integrity plugin for the pre-operation types check-references needs, and refuse check-references without them - #1123
Conversation
maximthomas
left a comment
There was a problem hiding this comment.
praise: The fix is made where the bug is, and the upgrade path covers the case-sensitivity trap.
resource/config/config.ldif: the shippedcn=Referential Integrityentry now listspreOperationAddandpreOperationModify, matching the definition's default.ReferentialIntegrityPlugin.isConfigurationAcceptablegives oneERR_PLUGIN_REFERENT_CHECK_REFERENCES_WITHOUT_PLUGIN_TYPEreason for each missing type.UpgradeUtils.getUpgradeSchema()declaresds-cfg-plugin-typewithcaseIgnoreMatch, so the 5.2.0 task does not add a secondpreOperationAddnext to thepreoperationaddthat dsconfig writes.UpgradeUtilsTestCaserow 2 pins this.- Run locally at f4f2fc9:
ReferentialIntegrityPluginTestCase54/54 andUpgradeUtilsTestCase4/4. All new cases are green.
question (non-blocking): Is it intended that at boot, an enabled RI plugin with check-references: true and no pre-operation types is no longer loaded at all?
opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java:176, :285-296
initializePlugin:176 runs the new check and throws ConfigException. PluginConfigManager.initializeUserPlugins logs the error and continues (:349-352), so the post-operation delete/modifyDN and subordinate cleanup of member/uniqueMember also stops. At BASE that cleanup ran and only the check was inert. The 5.2.0 task heals every 5.1.x → 5.2.0 upgrade. It does not heal an instance already on a 5.2.0-SNAPSHOT build: getUpgradeTasks uses TASKS.subMap(from, false, to, true) and the version compare ignores the revision. A hand-edited or restored config.ldif is not healed either. If unloading is intended, this matches how other invalid RI configs already fail at boot, and nothing needs to change. If it is not intended, the change would log the check-references reasons as warnings in initializePlugin and load the plugin, and keep the refusal for configuration changes.
suggestion (non-blocking): No test runs the register("5.2.0", …) call. The test applies only the task's constants.
opendj-server-legacy/src/test/java/org/opends/server/tools/upgrade/UpgradeUtilsTestCase.java:141-145, opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/Upgrade.java:652-655
testAddReferentialIntegrityPluginTypesMirrorsFreshInstallTemplate passes REFERENTIAL_INTEGRITY_PLUGIN_FILTER and ADD_REFERENTIAL_INTEGRITY_PRE_OPERATION_PLUGIN_TYPES directly to UpgradeUtils.updateConfigFile, and no test reads TASKS or getUpgradeTasks. Deleting the register call, or keying it at a version a 5.1.x → 5.2.0 upgrade never reaches, keeps every test green. Upgraded instances would then keep the four old types, and the new check would refuse check-references: true. The registration at the head is correct by reading. Only the pin is missing.
// Upgrade.java:782 — package-private for the test
static List<UpgradeTask> getUpgradeTasks(final BuildVersion fromVersion, final BuildVersion toVersion)
// UpgradeUtilsTestCase
@Test
public void testAddReferentialIntegrityPluginTypesTaskRunsOnUpgradeTo520() throws Exception
{
final List<String> summaries = new ArrayList<>();
for (final UpgradeTask task : Upgrade.getUpgradeTasks(BuildVersion.valueOf("5.1.2"), BuildVersion.valueOf("5.2.0")))
{
summaries.add(task.toString());
}
assertTrue(summaries.contains(INFO_UPGRADE_TASK_ADD_REFERENTIAL_INTEGRITY_PRE_OPERATION_PLUGIN_TYPES.get().toString()),
summaries.toString());
}Pin: this turns red when the register call is deleted or re-versioned. updateConfigEntry's task returns its summary from toString() (UpgradeTasks.java:1159-1161). A different filter literal inside the call would still go uncaught.
issue (non-blocking): The guide says OpenDJ refuses the set itself. On a disabled plugin, which is how the entry ships, the refusal comes only when the plugin is enabled.
opendj-doc-generated-ref/src/main/asciidoc/server-dev-guide/chap-groups.adoc:542
PluginConfigManager calls the plugin's isConfigurationAcceptable only if (configuration.isEnabled()) (:4357, :4439). cn=Referential Integrity ships with ds-cfg-enabled: false. On it, set-plugin-prop --set check-references:true is accepted even when a type is missing, and --set enabled:true is what gets refused. The misconfiguration still cannot become active, so only the sentence is wrong.
When the plugin is enabled, OpenDJ refuses to set `check-references` to `true` if `plugin-type` lacks either of them, and it refuses to enable a plugin configured that way.suggestion (non-blocking): The refusal's remedy does not work on a running plugin that was registered without the types.
opendj-server-legacy/src/messages/org/opends/messages/plugin.properties:357-360, opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java:294
Take a plugin that was enabled with the four old types. An admin follows the message: adds preoperationadd and preoperationmodify, then sets check-references: true. Every change is accepted. But PluginConfigManager.applyConfigurationChange does not re-register plugin types for an existing plugin, so adds and modifies are still not checked until the plugin is re-enabled. That is the #1118 symptom again (the root is #1120). The guide says to re-enable; the message does not.
ERR_PLUGIN_REFERENT_CHECK_REFERENCES_WITHOUT_PLUGIN_TYPE_131=The property \
'check-references' is set to true, but the property 'plugin-type' does not list \
'%s', so the references added by that operation would not be checked. Add '%s' to \
'plugin-type', then disable and re-enable the plugin, or set 'check-references' to false…y plugin for the pre-operation types check-references needs, and refuse check-references without them The shipped cn=Referential Integrity entry listed only the post-operation and subordinate plugin types, so check-references:true was accepted and checked nothing. Add preOperationAdd and preOperationModify to the template and, via a 5.2.0 upgrade task, to every referential integrity plugin entry; the upgrade schema now matches ds-cfg-plugin-type ignoring case so a type already added in the lower case dsconfig writes is not added twice. The plugin now refuses check-references:true when either type is missing, and the developer guide says so. Fixes OpenIdentityPlatform#1118
…ion without the pre-operation types with a warning, and pin the 5.2.0 upgrade task Refusing such a configuration at startup also stopped the delete and modify DN clean-up, which ran before the check existed. The server now loads it and logs a warning for each missing type. Enabling the plugin or changing its configuration is still refused. The refusal message and the developer guide now say to disable and re-enable the plugin after adding the types. The guide also says the refusal applies when the plugin is enabled. A test now checks that an upgrade from 5.1.x to 5.2.0 runs the task that adds the types.
f4f2fc9 to
8701e0c
Compare
|
@maximthomas all four points are taken in 8701e0c. The branch is rebased onto master d0ce1d7. question: unloading at boot: this was not intended. Refusing the configuration in
The three configurations moved from
suggestion: pin for issue: the guide sentence: replaced with your wording. The guide also says that a plugin already configured that way at startup is loaded with a warning. suggestion: the refusal's remedy: Run locally at 8701e0c:
|
maximthomas
left a comment
There was a problem hiding this comment.
praise: The round-1 points are fixed where they arise, and the boot road keeps the clean-up.
ReferentialIntegrityPlugin.initializePluginnow runsisConfigurationAcceptableIgnoringCheckReferencesPluginTypesand logs oneWARN_PLUGIN_REFERENT_CHECK_REFERENCES_WITHOUT_PLUGIN_TYPEper missing type (:176-187). A stored pre-#1118 entry therefore keeps its delete and modify DN clean-up.testAddReferentialIntegrityPluginTypesTaskRunsOnUpgradeTo520pins the 5.2.0 registration through the now package-privateUpgrade.getUpgradeTasks.- Run locally at 8701e0c:
ReferentialIntegrityPluginTestCase58/58 andUpgradeUtilsTestCase5/5. Every new case is green.
…tial integrity plugin refused at startup, and remove the MSAD plugin's listener on finalize Review round 2 of OpenIdentityPlatform#1127: - ReferentialIntegrityPlugin registers its change listener only after its configuration check, and finalizePlugin() returns early when the check refused the configuration. Before, the listener was registered first and finalizePlugin() failed with a NullPointerException before it removed it, so an instance refused at startup, where there is no acceptance phase, kept listening to its entry. - MsadPlugin removes its change listener in finalizePlugin(), so neither a plugin type change nor a refused plugin type leaves a listener behind. SambaPasswordPlugin.finalizePlugin() no longer fails on an instance that refused its configuration. - The DirectoryServerPlugin.finalizePlugin() Javadoc says that it is also called on an instance whose initializePlugin() threw. - OpenIdentityPlatform#1123 told the administrator to disable and re-enable the referential integrity plugin after adding plugin types, in chap-groups.adoc and in the check-references error and warning. Added plugin types now take effect at once, so the sentence is replaced and the advice dropped from both messages. - Tests: a change that leaves the plugin types alone keeps the running instance; a referential integrity configuration refused by initializePlugin() leaves no change listener behind.
Summary
The shipped
cn=Referential Integrity,cn=Plugins,cn=configentry registered the plugin forpostOperationDelete,postOperationModifyDN,subordinateModifyDNandsubordinateDeleteonly.check-referencesruns in the plugin'spreOperationAddandpreOperationModifyhooks, so on the shipped entrycheck-references:truewas accepted and checked nothing (the behaviour reported in #579).Changes
config.ldif: the shipped entry listspreOperationAddandpreOperationModify, as the definition's default forplugin-typealready does.ReferentialIntegrityPlugin.isConfigurationAcceptable: refusescheck-references:truewhenplugin-typelacks either type, with oneERR_PLUGIN_REFERENT_CHECK_REFERENCES_WITHOUT_PLUGIN_TYPEreason per missing type. The plugin manager runs this check when the plugin is enabled, and when its configuration is changed while it is enabled. The message says to disable and re-enable the plugin after adding the types, because of Changing plugin-type on an enabled plugin has no effect until the plugin is re-enabled, and the server does not report it #1120.ReferentialIntegrityPlugin.initializePlugin: a configuration already stored without the types is still loaded when the server starts, with oneWARN_PLUGIN_REFERENT_CHECK_REFERENCES_WITHOUT_PLUGIN_TYPEwarning per missing type. Refusing it there would also stop the delete and modify DN clean-up, which does not need these types and ran before this change. The upgrade task heals every 5.1.x instance. The warning covers the rest: an instance already on a 5.2.0 snapshot, and a hand-edited or restoredconfig.ldif.objectClass=ds-cfg-referential-integrity-plugin, so instances upgraded from earlier versions are healed and do not start failing the new check. The add is permissive, so it is idempotent.UpgradeUtils.getUpgradeSchema(): declaresds-cfg-plugin-typewithcaseIgnoreMatch. Without it the upgrade schema matches the attribute case-exactly, and the task would addpreOperationAddnext to apreoperationaddan administrator already added withdsconfig, which writes plugin types in lower case.check-referencesneeds the two plugin types. The refusal applies to an enabled plugin, and to enabling one. A plugin already configured without the types when the server starts is loaded with a warning. Plugin types take effect when the plugin is enabled.Tests
ReferentialIntegrityPluginTestCasecheckReferencesWithoutPreOperationTypes: three configurations, the pre-fix shipped types and each pre-operation type missing on its own, each with the types it lacks;testCheckReferencesWithoutPreOperationTypesIsNotAcceptable: each one is refused, with exactly one reason per missing type;testCheckReferencesWithoutPreOperationTypesIsLoadedWithWarning: each one still initializes, and a warning is logged for each missing type;testShippedEntryAcceptsCheckReferences: the entry read from the fresh-installconfig.ldifinitializes withcheck-references:true;testCheckReferencesWithoutPreOperationTypesIsRejected: turningcheck-referenceson for the running plugin without the types is refused, and the reason names both types;testEnablingCheckReferencesWithoutPreOperationTypesIsRejected: on a disabled plugincheck-references:truewithout the types is accepted, and enabling the plugin is then refused, with both types named.UpgradeUtilsTestCasetestAddReferentialIntegrityPluginTypesMirrorsFreshInstallTemplate: applied twice to the pre-fix entry, and to one wherepreoperationaddwas already added in lower case, the task leaves exactly the plugin types of the fresh-install template;testAddReferentialIntegrityPluginTypesTaskRunsOnUpgradeTo520:Upgrade.getUpgradeTasks(now package-private) from 5.1.2 to 5.2.0 includes the task.Before the fix the new cases failed; in the lower-case case the upgrade produced 7 plugin types instead of 6. After it: 58/58 and 5/5. Each of these mutants is caught: no check, a check for
preOperationAddonly, a case-exact upgrade schema, a refusal at startup, no startup warning, no refusal inisConfigurationAcceptable, theregistercall removed, and the task registered at 5.3.0.Related
plugin-typeon a plugin that is already enabled has no effect until it is re-enabled, and the server does not report it. Not addressed here; [#1120] Apply a change to plugin-type on an enabled plugin without disabling and enabling it again #1127 fixes it. Whichever of [#1118] Register the shipped Referential Integrity plugin for the pre-operation types check-references needs, and refuse check-references without them #1123 and [#1120] Apply a change to plugin-type on an enabled plugin without disabling and enabling it again #1127 is merged second drops the "disable and re-enable" advice from the refusal message and the developer guide.Fixes #1118