/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* or http://forgerock.org/license/CDDLv1.0.html.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2011 profiq s.r.o.
* Portions Copyright 2013-2015 ForgeRock AS
*/
package org.opends.server.plugins;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ModificationType;
import org.forgerock.opendj.ldap.ResultCode;
import org.opends.server.TestCaseUtils;
import org.opends.server.admin.server.AdminTestCaseUtils;
import org.opends.server.admin.std.meta.AttributeCleanupPluginCfgDefn;
import org.opends.server.admin.std.server.AttributeCleanupPluginCfg;
import org.opends.server.api.plugin.PluginResult;
import org.opends.server.api.plugin.PluginType;
import org.opends.server.core.AddOperationBasis;
import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.*;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.opends.server.TestCaseUtils.*;
import static org.testng.Assert.*;
/**
* Tests for the attribute cleanup plugin.
*/
@SuppressWarnings("javadoc")
public class AttributeCleanupPluginTestCase extends PluginTestCase
{
@BeforeClass
public void startServer() throws Exception
{
TestCaseUtils.startServer();
}
@DataProvider(name = "validConfigs")
public Object[][] getValidConfigs() throws Exception
{
List<Entry> entries = TestCaseUtils.makeEntries(
"dn: cn=Attribute Cleanup,cn=Plugins,cn=config",
"objectClass: top",
"objectClass: ds-cfg-plugin",
"objectClass: ds-cfg-attribute-cleanup-plugin",
"cn: Attribute Cleanup",
"ds-cfg-enabled: true",
"ds-cfg-plugin-type: preparseadd",
"ds-cfg-plugin-type: preparsemodify",
"ds-cfg-java-class: org.opends.server.plugins.AttributeCleanupPlugin",
"",
"dn: cn=Attribute Cleanup,cn=Plugins,cn=config",
"objectClass: top",
"objectClass: ds-cfg-plugin",
"objectClass: ds-cfg-attribute-cleanup-plugin",
"cn: Attribute Cleanup",
"ds-cfg-enabled: true",
"ds-cfg-plugin-type: preparseadd",
"ds-cfg-plugin-type: preparsemodify",
"ds-cfg-java-class: org.opends.server.plugins.AttributeCleanupPlugin",
"ds-cfg-remove-inbound-attributes: modifyTimeStamp",
"ds-cfg-remove-inbound-attributes: createTimeStamp",
"",
"dn: cn=Attribute Cleanup,cn=Plugins,cn=config",
"objectClass: top",
"objectClass: ds-cfg-plugin",
"objectClass: ds-cfg-attribute-cleanup-plugin",
"cn: Attribute Cleanup",
"ds-cfg-enabled: true",
"ds-cfg-plugin-type: preparseadd",
"ds-cfg-plugin-type: preparsemodify",
"ds-cfg-java-class: org.opends.server.plugins.AttributeCleanupPlugin",
"ds-cfg-rename-inbound-attributes: cn:uid");
return toArrayArray(entries);
}
@Test(dataProvider = "validConfigs")
public void testInitializeWithValidConfigs(Entry e)
throws Exception
{
Set<PluginType> pluginTypes = getPluginTypes(e);
assertFalse(pluginTypes.isEmpty());
AttributeCleanupPluginCfg config =
AdminTestCaseUtils.getConfiguration(
AttributeCleanupPluginCfgDefn.getInstance(),e);
assertNotNull(config);
AttributeCleanupPlugin plugin = new AttributeCleanupPlugin();
plugin.initializePlugin(pluginTypes, config);
plugin.finalizePlugin();
}
@DataProvider(name = "invalidConfigs")
public Object[][] getInvalidConfigs() throws Exception
{
List<Entry> entries = TestCaseUtils.makeEntries(
/* local attribute is not defined */
"dn: cn=Attribute Cleanup,cn=Plugins,cn=config",
"objectClass: top",
"objectClass: ds-cfg-plugin",
"objectClass: ds-cfg-attribute-cleanup-plugin",
"cn: Attribute Cleanup",
"ds-cfg-enabled: true",
"ds-cfg-plugin-type: preparseadd",
"ds-cfg-plugin-type: preparsemodify",
"ds-cfg-java-class: org.opends.server.plugins.AttributeCleanupPlugin",
"ds-cfg-rename-inbound-attributes: cn:badAttr",
"",
/* duplicate attributes */
"dn: cn=Attribute Cleanup,cn=Plugins,cn=config",
"objectClass: top",
"objectClass: ds-cfg-plugin",
"objectClass: ds-cfg-attribute-cleanup-plugin",
"cn: Attribute Cleanup",
"ds-cfg-enabled: true",
"ds-cfg-plugin-type: preparseadd",
"ds-cfg-plugin-type: preparsemodify",
"ds-cfg-java-class: org.opends.server.plugins.AttributeCleanupPlugin",
"ds-cfg-rename-inbound-attributes: cn:uid",
"ds-cfg-rename-inbound-attributes: cn:description",
"",
/* self mapping */
"dn: cn=Attribute Cleanup,cn=Plugins,cn=config",
"objectClass: top",
"objectClass: ds-cfg-plugin",
"objectClass: ds-cfg-attribute-cleanup-plugin",
"cn: Attribute Cleanup",
"ds-cfg-enabled: true",
"ds-cfg-plugin-type: preparseadd",
"ds-cfg-plugin-type: preparsemodify",
"ds-cfg-java-class: org.opends.server.plugins.AttributeCleanupPlugin",
"ds-cfg-rename-inbound-attributes: cn:cn");
return toArrayArray(entries);
}
private Object[][] toArrayArray(List<Entry> entries)
{
Object[][] array = new Object[entries.size()][1];
for (int i=0; i < array.length; i++)
{
array[i] = new Object[] { entries.get(i) };
}
return array;
}
@Test(dataProvider = "invalidConfigs",
expectedExceptions = { ConfigException.class } )
public void testInitializeWithInvalidConfigs(Entry e)
throws ConfigException, InitializationException
{
Set<PluginType> pluginTypes = getPluginTypes(e);
assertFalse(pluginTypes.isEmpty());
AttributeCleanupPluginCfg config =
AdminTestCaseUtils.getConfiguration(
AttributeCleanupPluginCfgDefn.getInstance(),e);
assertNotNull(config);
AttributeCleanupPlugin plugin = new AttributeCleanupPlugin();
plugin.initializePlugin(pluginTypes, config);
plugin.finalizePlugin();
}
/**
* Verifies the attribute renaming in the incoming ADD operation.
*
* @throws Exception in case of bugs.
*/
@Test
public void testRenameAttributesForAddOperation() throws Exception
{
// Configure the plugin to rename incoming 'cn' attributes to 'description'.
Entry confEntry = TestCaseUtils.makeEntry(
"dn: cn=Attribute Cleanup,cn=Plugins,cn=config",
"objectClass: top",
"objectClass: ds-cfg-plugin",
"objectClass: ds-cfg-attribute-cleanup-plugin",
"cn: Attribute Cleanup",
"ds-cfg-enabled: true",
"ds-cfg-plugin-type: preparseadd",
"ds-cfg-plugin-type: preparsemodify",
"ds-cfg-rename-inbound-attributes: cn:description",
"ds-cfg-java-class: org.opends.server.plugins.AttributeCleanupPlugin");
Set<PluginType> pluginTypes = getPluginTypes(confEntry);
AttributeCleanupPluginCfg config =
AdminTestCaseUtils.getConfiguration(
AttributeCleanupPluginCfgDefn.getInstance(),confEntry);
AttributeCleanupPlugin plugin = new AttributeCleanupPlugin();
plugin.initializePlugin(pluginTypes, config);
/* Construct the ADD operation as follows:
*
* dn: uid=test,dc=example,dc=com
* objectClass: top
* objectClass: person
* objectClass: organizationalPerson
* objectClass: inetOrgPerson
* uid: test
* cn: Name Surname
* sn: Surname
*/
ArrayList<ByteString> values = new ArrayList<>();
values.add(ByteString.valueOfUtf8("top"));
values.add(ByteString.valueOfUtf8("person"));
values.add(ByteString.valueOfUtf8("organizationalperson"));
values.add(ByteString.valueOfUtf8("inetorgperson"));
List<RawAttribute> rawAttributes = new ArrayList<>();
rawAttributes.add(RawAttribute.create("objectClass", values));
rawAttributes.add(RawAttribute.create("uid", "test"));
rawAttributes.add(RawAttribute.create("cn", "Name Surname"));
rawAttributes.add(RawAttribute.create("sn", "Surname"));
AddOperationBasis addOperation =
new AddOperationBasis(InternalClientConnection.getRootConnection(),
1,
1,
null,
ByteString.valueOfUtf8("dn: uid=test,dc=example,dc=com"),
rawAttributes);
/* Process the operation. The processing should continue. */
PluginResult.PreParse res = plugin.doPreParse(addOperation);
assertTrue(res.continueProcessing());
/* Verify that the 'cn' attribute has been renamed to 'description'
* by getting the 'decription' attribute and matching the value with
* the original 'cn' value.
*/
List<RawAttribute> rawAttrs = addOperation.getRawAttributes();
assertNotNull(rawAttrs);
for(RawAttribute rawAttr : rawAttrs)
{
if(rawAttr.getAttributeType().equalsIgnoreCase("description"))
{
List<ByteString> attrVals = rawAttr.getValues();
assertEquals("Name Surname", attrVals.get(0).toString());
plugin.finalizePlugin();
return;
}
}
fail();
}
/**
* Verifies the attribute removal in the incoming ADD request.
* @throws Exception in case of bugs.
*/
@Test
public void testRemoveAttributesForAddOperation() throws Exception
{
/* Configure the plugin to remove 'modifyTimeStamp' and
* 'createTimeStamp' attributes from the incoming ADD requests.
*/
Entry confEntry = TestCaseUtils.makeEntry(
"dn: cn=Attribute Cleanup,cn=Plugins,cn=config",
"objectClass: top",
"objectClass: ds-cfg-plugin",
"objectClass: ds-cfg-attribute-cleanup-plugin",
"cn: Attribute Cleanup",
"ds-cfg-enabled: true",
"ds-cfg-plugin-type: preparseadd",
"ds-cfg-plugin-type: preparsemodify",
"ds-cfg-remove-inbound-attributes: modifyTimeStamp",
"ds-cfg-remove-inbound-attributes: createTimeStamp",
"ds-cfg-java-class: org.opends.server.plugins.AttributeCleanupPlugin");
Set<PluginType> pluginTypes = getPluginTypes(confEntry);
AttributeCleanupPluginCfg config =
AdminTestCaseUtils.getConfiguration(
AttributeCleanupPluginCfgDefn.getInstance(),confEntry);
AttributeCleanupPlugin plugin = new AttributeCleanupPlugin();
plugin.initializePlugin(pluginTypes, config);
/* Create the ADD operation as follows:
*
* dn: uid=test,dc=example,dc=com
* objectClass: top
* objectClass: person
* objectClass: organizationalPerson
* objectClass: inetOrgPerson
* uid: test
* cn: Name Surname
* sn: Surname
* modifyTimeStamp: 2011091212400000Z
* createTimeStamp: 2011091212400000Z
*/
ArrayList<ByteString> values = new ArrayList<>();
values.add(ByteString.valueOfUtf8("top"));
values.add(ByteString.valueOfUtf8("person"));
values.add(ByteString.valueOfUtf8("organizationalperson"));
values.add(ByteString.valueOfUtf8("inetorgperson"));
List<RawAttribute> rawAttributes = new ArrayList<>();
rawAttributes.add(RawAttribute.create("objectClass", values));
rawAttributes.add(RawAttribute.create("uid", "test"));
rawAttributes.add(RawAttribute.create("cn", "Name Surname"));
rawAttributes.add(RawAttribute.create("sn", "Surname"));
rawAttributes.add(RawAttribute.create("modifyTimeStamp", "2011091212400000Z"));
rawAttributes.add(RawAttribute.create("createTimeStamp", "2011091212400000Z"));
AddOperationBasis addOperation =
new AddOperationBasis(InternalClientConnection.getRootConnection(),
1,
1,
null,
ByteString.valueOfUtf8("dn: uid=test,dc=example,dc=com"),
rawAttributes);
/* Process the operation and expect the server to continue
* processing the operation.
*/
PluginResult.PreParse res = plugin.doPreParse(addOperation);
assertTrue(res.continueProcessing());
/* Verify that the '*TimeStamp' attributes have been removed. */
List<RawAttribute> rawAttrs = addOperation.getRawAttributes();
assertNotNull(rawAttrs);
for(RawAttribute rawAttr : rawAttrs)
{
assertFalse(rawAttr.getAttributeType().equalsIgnoreCase("modifyTimeStamp")
|| rawAttr.getAttributeType().equalsIgnoreCase("createTimeStamp"),
"Attribute '" + rawAttr.getAttributeType() + "' exists and it shouldn't");
}
plugin.finalizePlugin();
}
/**
* In some cases the plugin might remove all attributes from the
* incoming MODIFY request which would make the request invalid by the
* LDAP standards. However, this is a special case and the request
* should be silently dropped while the client should be notified of
* SUCCESS.
* @throws Exception in case of a bug.
*/
@Test
public void testRemoveAttributesForModifyOperationInvalid() throws Exception
{
/* Configure the plugin to remove 'modifyTimeStamp' and
* 'createTimeStamp' attributes from the incoming MODIFY request.
*/
Entry confEntry = TestCaseUtils.makeEntry(
"dn: cn=Attribute Cleanup,cn=Plugins,cn=config",
"objectClass: top",
"objectClass: ds-cfg-plugin",
"objectClass: ds-cfg-attribute-cleanup-plugin",
"cn: Attribute Cleanup",
"ds-cfg-enabled: true",
"ds-cfg-plugin-type: preparseadd",
"ds-cfg-plugin-type: preparsemodify",
"ds-cfg-remove-inbound-attributes: modifyTimeStamp",
"ds-cfg-remove-inbound-attributes: createTimeStamp",
"ds-cfg-java-class: org.opends.server.plugins.AttributeCleanupPlugin");
Set<PluginType> pluginTypes = getPluginTypes(confEntry);
AttributeCleanupPluginCfg config =
AdminTestCaseUtils.getConfiguration(
AttributeCleanupPluginCfgDefn.getInstance(),confEntry);
AttributeCleanupPlugin plugin = new AttributeCleanupPlugin();
plugin.initializePlugin(pluginTypes, config);
/* Create the MODIFY request as follows:
*
* dn: uid=test,dc=example,dc=com
* changetype: modify
* replace: modifyTimeStamp
* modifyTimeStamp: 2011091212400000Z
* -
* replace: createTimeStamp
* createTimeStamp: 2011091212400000Z
* -
*/
List<RawModification> rawMods= new ArrayList<>();
rawMods.add(RawModification.create(ModificationType.REPLACE,
"modifyTimeStamp",
"2011091212400000Z"));
rawMods.add(RawModification.create(ModificationType.REPLACE,
"createTimeStamp",
"2011091212400000Z"));
ModifyOperationBasis modifyOperation =
new ModifyOperationBasis(InternalClientConnection.getRootConnection(),
1,
1,
null,
ByteString.valueOfUtf8("dn: uid=test,dc=example,dc=com"),
rawMods);
/* Process the request. The result should be SUCCESS and the server
* should stop the processing.
*/
PluginResult.PreParse res = plugin.doPreParse(modifyOperation);
assertFalse(res.continueProcessing());
assertSame(res.getResultCode(), ResultCode.SUCCESS);
plugin.finalizePlugin();
}
/**
* Verify the attribute renaming for a MODIFY operation.
* @throws Exception in case of a bug.
*/
@Test
public void testRemoveAttributesForModifyOperationValid() throws Exception
{
/* Configure the plugin to remove 'modifyTimeStamp' and
* 'createTimeStamp' attributes from the incoming requests.
*/
Entry confEntry = TestCaseUtils.makeEntry(
"dn: cn=Attribute Cleanup,cn=Plugins,cn=config",
"objectClass: top",
"objectClass: ds-cfg-plugin",
"objectClass: ds-cfg-attribute-cleanup-plugin",
"cn: Attribute Cleanup",
"ds-cfg-enabled: true",
"ds-cfg-plugin-type: preparseadd",
"ds-cfg-plugin-type: preparsemodify",
"ds-cfg-remove-inbound-attributes: modifyTimeStamp",
"ds-cfg-remove-inbound-attributes: createTimeStamp",
"ds-cfg-java-class: org.opends.server.plugins.AttributeCleanupPlugin");
Set<PluginType> pluginTypes = getPluginTypes(confEntry);
AttributeCleanupPluginCfg config =
AdminTestCaseUtils.getConfiguration(
AttributeCleanupPluginCfgDefn.getInstance(),confEntry);
AttributeCleanupPlugin plugin = new AttributeCleanupPlugin();
plugin.initializePlugin(pluginTypes, config);
/* Create the MODIFY operation as follows:
*
* dn: uid=test,dc=example,dc=com
* changetype: modify
* replace: cn
* cn: Test User
* -
* replace: sn
* sn: User
* -
* replace: modifyTimeStamp
* modifyTimeStamp: 2011091212400000Z
* -
* replace: createTimeStamp
* createTimeStamp: 2011091212400000Z
* -
*/
List<RawModification> rawMods= new ArrayList<>();
rawMods.add(RawModification.create(ModificationType.REPLACE,
"cn",
"Test User"));
rawMods.add(RawModification.create(ModificationType.REPLACE,
"sn",
"User"));
rawMods.add(RawModification.create(ModificationType.REPLACE,
"modifyTimeStamp",
"2011091212400000Z"));
rawMods.add(RawModification.create(ModificationType.REPLACE,
"createTimeStamp",
"2011091212400000Z"));
ModifyOperationBasis modifyOperation =
new ModifyOperationBasis(InternalClientConnection.getRootConnection(),
1,
1,
null,
ByteString.valueOfUtf8("dn: uid=test,dc=example,dc=com"),
rawMods);
/* Process the MODIFY operation making sure the remaining number of
* modifications is 2 and that the '*TimeStamp' modifications are
* removed.
*/
plugin.doPreParse(modifyOperation);
assertEquals(modifyOperation.getRawModifications().size(), 2);
rawMods = modifyOperation.getRawModifications();
assertNotNull(rawMods);
for(RawModification rawMod : rawMods )
{
RawAttribute modAttr = rawMod.getAttribute();
if(modAttr.getAttributeType().equalsIgnoreCase("modifyTimeStamp")
|| modAttr.getAttributeType().equalsIgnoreCase("createTimeStamp"))
{
fail("Attribute '" + modAttr.getAttributeType()
+ "' exists and it shouldn't");
}
}
plugin.finalizePlugin();
}
/**
* Verify the attribute renaming for the MODIFY operation.
*/
@Test
public void testRenameAttributesForModifyOperation() throws Exception
{
/* Configure the plugin to rename the 'modifyTimeStamp' attribute to
* 'description'.
*/
Entry confEntry = TestCaseUtils.makeEntry(
"dn: cn=Attribute Cleanup,cn=Plugins,cn=config",
"objectClass: top",
"objectClass: ds-cfg-plugin",
"objectClass: ds-cfg-attribute-cleanup-plugin",
"cn: Attribute Cleanup",
"ds-cfg-enabled: true",
"ds-cfg-plugin-type: preparseadd",
"ds-cfg-plugin-type: preparsemodify",
"ds-cfg-rename-inbound-attributes: modifyTimeStamp:description",
"ds-cfg-java-class: org.opends.server.plugins.AttributeCleanupPlugin");
Set<PluginType> pluginTypes = getPluginTypes(confEntry);
AttributeCleanupPluginCfg config =
AdminTestCaseUtils.getConfiguration(
AttributeCleanupPluginCfgDefn.getInstance(),confEntry);
AttributeCleanupPlugin plugin = new AttributeCleanupPlugin();
plugin.initializePlugin(pluginTypes, config);
/* Create the MODIFY operation as follows:
*
* dn: uid=test,dc=exampple,dc=com
* changetype: modify
* replace: cn
* cn: Test User
* -
* replace: sn
* sn: User
* -
* replace: modifyTimeStamp
* modifyTimeStamp: 2011091212400000Z
*/
List<RawModification> rawMods= new ArrayList<>();
rawMods.add(RawModification.create(ModificationType.REPLACE,
"cn",
"Test User"));
rawMods.add(RawModification.create(ModificationType.REPLACE,
"sn",
"User"));
rawMods.add(RawModification.create(ModificationType.REPLACE,
"modifyTimeStamp",
"2011091212400000Z"));
ModifyOperationBasis modifyOperation =
new ModifyOperationBasis(InternalClientConnection.getRootConnection(),
1,
1,
null,
ByteString.valueOfUtf8("dn: uid=test,dc=example,dc=com"),
rawMods);
/* Process the MODIFY operation. */
PluginResult.PreParse res = plugin.doPreParse(modifyOperation);
assertTrue(res.continueProcessing());
/* Verify that the attribute has been properly renamed by comparing
* the value of the attribute 'description' with the original value
* of the 'modifyTimeStamp' attribute.
*/
rawMods = modifyOperation.getRawModifications();
assertNotNull(rawMods);
for(RawModification rawMod : rawMods )
{
RawAttribute modAttr = rawMod.getAttribute();
if (modAttr.getAttributeType().equalsIgnoreCase("description"))
{
List<ByteString> descrValues = modAttr.getValues();
assertEquals("2011091212400000Z", descrValues.get(0).toString());
plugin.finalizePlugin();
return;
}
assertFalse(modAttr.getAttributeType().equalsIgnoreCase("modifyTimeStamp"),
"modifyTimeStamp shouldn't exist but it does.");
}
fail();
}
}