diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/processor/ResourceObjectIdentification.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/processor/ResourceObjectIdentification.java index 2bee3b86837..60f5f030bf9 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/processor/ResourceObjectIdentification.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/processor/ResourceObjectIdentification.java @@ -77,6 +77,9 @@ public ObjectClassComplexTypeDefinition getObjectClassDefinition() { public static ResourceObjectIdentification create(ObjectClassComplexTypeDefinition objectClassDefinition, Collection> allIdentifiers) throws SchemaException { + if (allIdentifiers == null) { + throw new IllegalArgumentException("Cannot create ResourceObjectIdentification with null identifiers"); + } Collection> primaryIdentifiers = null; Collection> secondaryIdentifiers = null; for (ResourceAttribute identifier: allIdentifiers) { @@ -118,11 +121,15 @@ public static ResourceObjectIdentification createFromAttributes(ObjectClassCompl } public void validatePrimaryIdenfiers() { - if (primaryIdentifiers == null || primaryIdentifiers.isEmpty()) { + if (!hasPrimaryIdentifiers()) { throw new IllegalStateException("No primary identifiers in " + this); } } + public boolean hasPrimaryIdentifiers() { + return primaryIdentifiers != null && !primaryIdentifiers.isEmpty(); + } + @Override public int hashCode() { final int prime = 31; diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/EntitlementConverter.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/EntitlementConverter.java index 3ed20b7406c..e8085b42f5e 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/EntitlementConverter.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/EntitlementConverter.java @@ -199,8 +199,8 @@ private void postProcessEntitlementSubjectToEntitlement ResourceAttributeContainer identifiersContainer = new ResourceAttributeContainer( ShadowAssociationType.F_IDENTIFIERS, entitlementDef.toResourceAttributeContainerDefinition(), prismContext); associationCVal.add(identifiersContainer); - LOGGER.trace("Assocciation attribute value resolved to valueAtrribute {} and identifiers container {}", valueAttribute, identifiersContainer); identifiersContainer.add(valueAttribute); + LOGGER.trace("Assocciation attribute value resolved to valueAtrribute {} and identifiers container {}", valueAttribute, identifiersContainer); } } @@ -660,9 +660,9 @@ private PrismObject collectEntitlementAsObjectOperation(Prov ResourceAttributeContainer identifiersContainer = ShadowUtil.getAttributesContainer(associationCVal, ShadowAssociationType.F_IDENTIFIERS); - Collection> entitlementIdentifiers = identifiersContainer.getAttributes(); + Collection> entitlementIdentifiersFromAssociation = identifiersContainer.getAttributes(); - ResourceObjectDiscriminator disc = new ResourceObjectDiscriminator(entitlementOcDef.getTypeName(), entitlementIdentifiers); + ResourceObjectDiscriminator disc = new ResourceObjectDiscriminator(entitlementOcDef.getTypeName(), entitlementIdentifiersFromAssociation); ResourceObjectOperations operations = roMap.get(disc); if (operations == null) { operations = new ResourceObjectOperations(); @@ -741,8 +741,8 @@ private PrismObject collectEntitlementAsObjectOperation(Prov if (ResourceTypeUtil.isAvoidDuplicateValues(resource)) { PrismObject currentObjectShadow = operations.getCurrentShadow(); if (currentObjectShadow == null) { - LOGGER.trace("Fetching entitlement shadow {} to avoid value duplication (intent={})", entitlementIdentifiers, entitlementIntent); - currentObjectShadow = resourceObjectReferenceResolver.fetchResourceObject(entitlementCtx, entitlementIdentifiers, null, result); + LOGGER.trace("Fetching entitlement shadow {} to avoid value duplication (intent={})", entitlementIdentifiersFromAssociation, entitlementIntent); + currentObjectShadow = resourceObjectReferenceResolver.fetchResourceObject(entitlementCtx, entitlementIdentifiersFromAssociation, null, result); operations.setCurrentShadow(currentObjectShadow); } // TODO it seems that duplicate values are checked twice: once here and the second time in ResourceObjectConverter.executeModify diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectConverter.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectConverter.java index afb6fe9da01..cef3fcd58ff 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectConverter.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectConverter.java @@ -922,9 +922,14 @@ private PrismObject executeEntitlementChangesModify(ProvisioningCont Map roMap = new HashMap<>(); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("executeEntitlementChangesModify, old shadow:\n{}", subjectShadowBefore.debugDump(1)); + } + for (ItemDelta subjectDelta : subjectDeltas) { + ItemPath subjectItemPath = subjectDelta.getPath(); - if (new ItemPath(ShadowType.F_ASSOCIATION).equivalent(subjectDelta.getPath())) { + if (new ItemPath(ShadowType.F_ASSOCIATION).equivalent(subjectItemPath)) { ContainerDelta containerDelta = (ContainerDelta)subjectDelta; subjectShadowAfter = entitlementConverter.collectEntitlementsAsObjectOperation(ctx, roMap, containerDelta, subjectShadowBefore, subjectShadowAfter, parentResult); @@ -934,9 +939,12 @@ private PrismObject executeEntitlementChangesModify(ProvisioningCont ContainerDelta associationDelta = ContainerDelta.createDelta(ShadowType.F_ASSOCIATION, subjectShadowBefore.getDefinition()); PrismContainer associationContainer = subjectShadowBefore.findContainer(ShadowType.F_ASSOCIATION); if (associationContainer == null || associationContainer.isEmpty()){ - LOGGER.trace("No shadow association container in old shadow. Skipping processing entitlements change."); + LOGGER.trace("No shadow association container in old shadow. Skipping processing entitlements change for {}.", subjectItemPath); continue; } + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Processing association container in old shadow for {}:\n{}", subjectItemPath, associationContainer.debugDump(1)); + } // Delete + re-add association values that should ensure correct functioning in case of rename // This has to be done only for associations that require explicit referential integrity. @@ -954,13 +962,16 @@ private PrismObject executeEntitlementChangesModify(ProvisioningCont continue; } QName valueAttributeName = associationDefinition.getResourceObjectAssociationType().getValueAttribute(); - if (!ShadowUtil.matchesAttribute(subjectDelta.getPath(), valueAttributeName)) { + if (!ShadowUtil.matchesAttribute(subjectItemPath, valueAttributeName)) { continue; } LOGGER.trace("Processing association {} on rename", associationName); associationDelta.addValuesToDelete(associationValue.clone()); associationDelta.addValuesToAdd(associationValue.clone()); } + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Resulting association delta for {}:\n{}", subjectItemPath, associationDelta.debugDump(1)); + } if (!associationDelta.isEmpty()) { entitlementConverter.collectEntitlementsAsObjectOperation(ctx, roMap, associationDelta, subjectShadowBefore, subjectShadowAfter, parentResult); } diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectReferenceResolver.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectReferenceResolver.java index aba42c3db43..c7e7452a7b3 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectReferenceResolver.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectReferenceResolver.java @@ -179,6 +179,45 @@ Collection> resolvePrimaryIdentifier(Provisioning return primaryIdentifiers; } + /** + * Resolve primary identifier from a collection of identifiers that may contain only secondary identifiers. + */ + private ResourceObjectIdentification resolvePrimaryIdentifiers(ProvisioningContext ctx, + ResourceObjectIdentification identification, OperationResult result) + throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, + SecurityViolationException { + if (identification == null) { + return identification; + } + if (identification.hasPrimaryIdentifiers()) { + return identification; + } + Collection> secondaryIdentifiers = (Collection>) identification.getSecondaryIdentifiers(); + PrismObject repoShadow = shadowManager.lookupShadowBySecondaryIdentifiers(ctx, secondaryIdentifiers, result); + if (repoShadow == null) { + // TODO: we should attempt resource search here + throw new ObjectNotFoundException("No repository shadow for "+secondaryIdentifiers+", cannot resolve identifiers"); + } + PrismContainer attributesContainer = repoShadow.findContainer(ShadowType.F_ATTRIBUTES); + if (attributesContainer == null) { + throw new SchemaException("No attributes in "+repoShadow+", cannot resolve identifiers "+secondaryIdentifiers); + } + RefinedObjectClassDefinition ocDef = ctx.getObjectClassDefinition(); + Collection primaryIdentifiers = new ArrayList<>(); + for (PrismProperty property: attributesContainer.getValue().getProperties()) { + if (ocDef.isPrimaryIdentifier(property.getElementName())) { + RefinedAttributeDefinition attrDef = ocDef.findAttributeDefinition(property.getElementName()); + ResourceAttribute primaryIdentifier = new ResourceAttribute<>(property.getElementName(), + attrDef, prismContext); + primaryIdentifier.setRealValue(property.getRealValue()); + primaryIdentifiers.add(primaryIdentifier); + } + } + LOGGER.trace("Resolved {} to primary identifiers {} (object class {})", identification, primaryIdentifiers, ocDef); + return new ResourceObjectIdentification(identification.getObjectClassDefinition(), primaryIdentifiers, + identification.getSecondaryIdentifiers()); + } + public PrismObject fetchResourceObject(ProvisioningContext ctx, Collection> identifiers, @@ -196,6 +235,7 @@ public PrismObject fetchResourceObject(ProvisioningContext ctx, } ResourceObjectIdentification identification = ResourceObjectIdentification.create(objectClassDefinition, identifiers); + identification = resolvePrimaryIdentifiers(ctx, identification, parentResult); identification.validatePrimaryIdenfiers(); return connector.fetchObject(ShadowType.class, identification, attributesToReturn, ctx, parentResult); diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapMultidomainTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapMultidomainTest.java new file mode 100644 index 00000000000..4f5dfe49e7c --- /dev/null +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapMultidomainTest.java @@ -0,0 +1,1422 @@ +/** + * Copyright (c) 2015-2016 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.evolveum.midpoint.testing.conntest; + +import static com.evolveum.midpoint.test.IntegrationTestTools.display; +import static com.evolveum.midpoint.testing.conntest.AdUtils.*; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Collection; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.commons.lang.StringUtils; +import org.apache.directory.api.ldap.model.cursor.CursorException; +import org.apache.directory.api.ldap.model.entry.DefaultEntry; +import org.apache.directory.api.ldap.model.entry.DefaultModification; +import org.apache.directory.api.ldap.model.entry.Entry; +import org.apache.directory.api.ldap.model.entry.Modification; +import org.apache.directory.api.ldap.model.entry.ModificationOperation; +import org.apache.directory.api.ldap.model.exception.LdapException; +import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; +import org.apache.directory.api.ldap.model.name.Ava; +import org.apache.directory.api.ldap.model.name.Rdn; +import org.apache.directory.ldap.client.api.LdapNetworkConnection; +import org.testng.AssertJUnit; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.delta.PropertyDelta; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.ObjectPaging; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.OrderDirection; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.prism.util.PrismTestUtil; +import com.evolveum.midpoint.schema.SearchResultList; +import com.evolveum.midpoint.schema.SearchResultMetadata; +import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.processor.ResourceAttribute; +import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; +import com.evolveum.midpoint.schema.processor.ResourceSchema; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.MiscSchemaUtil; +import com.evolveum.midpoint.schema.util.ObjectQueryUtil; +import com.evolveum.midpoint.schema.util.ShadowUtil; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.test.AbstractIntegrationTest; +import com.evolveum.midpoint.test.IntegrationTestTools; +import com.evolveum.midpoint.test.util.MidPointTestConstants; +import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.util.DOMUtil; +import com.evolveum.midpoint.util.MiscUtil; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.SystemException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.CredentialsType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PasswordType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; +import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; + +/** + * @author semancik + * + */ +@Listeners({com.evolveum.midpoint.tools.testng.AlphabeticalMethodInterceptor.class}) +public abstract class AbstractAdLdapMultidomainTest extends AbstractLdapTest { + + protected static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "ad-ldap-multidomain"); + + protected static final File ROLE_PIRATES_FILE = new File(TEST_DIR, "role-pirate.xml"); + protected static final String ROLE_PIRATES_OID = "5dd034e8-41d2-11e5-a123-001e8c717e5b"; + + protected static final File ROLE_SUBMISSIVE_FILE = new File(TEST_DIR, "role-submissive.xml"); + protected static final String ROLE_SUBMISSIVE_OID = "0c0c81b2-d0a1-11e5-b51e-0309a826745e"; + + protected static final File ROLE_META_ORG_FILE = new File(TEST_DIR, "role-meta-org.xml"); + protected static final String ROLE_META_ORG_OID = "f2ad0ace-45d7-11e5-af54-001e8c717e5b"; + + public static final String ATTRIBUTE_OBJECT_GUID_NAME = "objectGUID"; + public static final String ATTRIBUTE_SAM_ACCOUNT_NAME_NAME = "sAMAccountName"; + public static final String ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME = "userAccountControl"; + public static final QName ATTRIBUTE_USER_ACCOUNT_CONTROL_QNAME = new QName(MidPointConstants.NS_RI, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME); + public static final String ATTRIBUTE_UNICODE_PWD_NAME = "unicodePwd"; + + protected static final String ACCOUNT_JACK_SAM_ACCOUNT_NAME = "jack"; + protected static final String ACCOUNT_JACK_FULL_NAME = "Jack Sparrow"; + protected static final String ACCOUNT_JACK_PASSWORD = "qwe.123"; + + protected static final String USER_CPTBARBOSSA_FULL_NAME = "Captain Hector Barbossa"; + + private static final String GROUP_PIRATES_NAME = "pirates"; + private static final String GROUP_MELEE_ISLAND_NAME = "Mêlée Island"; + + protected static final int NUMBER_OF_ACCOUNTS = 7; + private static final String ASSOCIATION_GROUP_NAME = "group"; + + private static final String NS_EXTENSION = "http://whatever.com/my"; + private static final QName EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME = new QName(NS_EXTENSION, "showInAdvancedViewOnly"); + + protected static final File USER_SUBMAN_FILE = new File(TEST_DIR, "user-subman.xml"); + private static final String USER_SUBMAN_OID ="910ac45a-8bd6-11e6-9122-ef88d95095f0"; + private static final String USER_SUBMAN_NAME = "subman"; + private static final String USER_SUBMAN_GIVEN_NAME = "Sub"; + private static final String USER_SUBMAN_FAMILY_NAME = "Man"; + private static final String USER_SUBMAN_FULL_NAME = "Sub Man"; + private static final String USER_SUBMAN_PASSWORD = "sub.123"; + + + private boolean allowDuplicateSearchResults = false; + + protected String jackAccountOid; + protected String groupPiratesOid; + protected long jackLockoutTimestamp; + protected String accountBarbossaOid; + protected String orgMeleeIslandOid; + protected String groupMeleeOid; + + private String accountSubmanOid; + + @Override + public String getStartSystemCommand() { + return null; + } + + @Override + public String getStopSystemCommand() { + return null; + } + + @Override + protected File getBaseDir() { + return TEST_DIR; + } + + @Override + protected String getSyncTaskOid() { + return "cd1e0ff2-0099-11e5-9e22-001e8c717e5b"; + } + + @Override + protected boolean useSsl() { + return true; + } + + @Override + protected String getLdapSuffix() { + return "DC=ad,DC=evolveum,DC=com"; + } + + @Override + protected String getLdapBindDn() { + return "CN=midpoint,CN=Users,DC=ad,DC=evolveum,DC=com"; + } + + @Override + protected String getLdapBindPassword() { + return "qwe.123"; + } + + @Override + protected int getSearchSizeLimit() { + return -1; + } + + @Override + public String getPrimaryIdentifierAttributeName() { + return "objectGUID"; + } + + @Override + protected String getPeopleLdapSuffix() { + return "CN=Users,"+getLdapSuffix(); + } + + @Override + protected String getGroupsLdapSuffix() { + return "CN=Users,"+getLdapSuffix(); + } + + protected String getLdapSubSuffix() { + return "DC=sub,DC=ad,DC=evolveum,DC=com"; + } + + protected String getPeopleLdapSubSuffix() { + return "CN=Users,"+getLdapSubSuffix(); + } + + @Override + protected String getLdapAccountObjectClass() { + return "user"; + } + + @Override + protected String getLdapGroupObjectClass() { + return "group"; + } + + @Override + protected String getLdapGroupMemberAttribute() { + return "member"; + } + + private QName getAssociationGroupQName() { + return new QName(MidPointConstants.NS_RI, ASSOCIATION_GROUP_NAME); + } + + @Override + protected boolean allowDuplicateSearchResults() { + return allowDuplicateSearchResults; + } + + @Override + protected boolean isGroupMemberMandatory() { + return false; + } + + private UserLdapConnectionConfig getSubLdapConnectionConfig() { + UserLdapConnectionConfig config = new UserLdapConnectionConfig(); + config.setLdapHost("hydra.ad.evolveum.com"); + config.setLdapPort(getLdapServerPort()); + config.setBindDn("CN=midpoint,CN=Users,DC=sub,DC=ad,DC=evolveum,DC=com"); + config.setBindPassword(getLdapBindPassword()); + config.setBaseContext(getLdapSubSuffix()); + return config; + } + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + + binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_OBJECT_GUID_NAME); + binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_UNICODE_PWD_NAME); + + // Users + repoAddObjectFromFile(USER_BARBOSSA_FILE, UserType.class, initResult); + repoAddObjectFromFile(USER_GUYBRUSH_FILE, UserType.class, initResult); + repoAddObjectFromFile(USER_SUBMAN_FILE, UserType.class, initResult); + + // Roles + repoAddObjectFromFile(ROLE_PIRATES_FILE, RoleType.class, initResult); + repoAddObjectFromFile(ROLE_SUBMISSIVE_FILE, RoleType.class, initResult); + repoAddObjectFromFile(ROLE_META_ORG_FILE, RoleType.class, initResult); + + } + + @Test + public void test000Sanity() throws Exception { + final String TEST_NAME = "test000Sanity"; + TestUtil.displayTestTile(this, TEST_NAME); + + assertLdapPassword(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME, ACCOUNT_JACK_PASSWORD); + cleanupDelete(toAccountDn(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME)); + cleanupDelete(toAccountDn(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME)); + cleanupDelete(toAccountDn(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME)); + cleanupDelete(getSubLdapConnectionConfig(), toAccountSubDn(USER_SUBMAN_NAME, USER_SUBMAN_FULL_NAME)); + cleanupDelete(toGroupDn(GROUP_MELEE_ISLAND_NAME)); + } + + @Test + @Override + public void test020Schema() throws Exception { + final String TEST_NAME = "test020Schema"; + TestUtil.displayTestTile(this, TEST_NAME); + + accountObjectClassDefinition = AdUtils.assertAdSchema(resource, getAccountObjectClass(), prismContext); + + assertLdapConnectorInstances(1); + } + + @Test + public void test100SeachJackBySamAccountName() throws Exception { + final String TEST_NAME = "test100SeachJackBySamAccountName"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + ObjectQuery query = createSamAccountNameQuery(ACCOUNT_JACK_SAM_ACCOUNT_NAME); + + rememberConnectorOperationCount(); + rememberConnectorSimulatedPagingSearchCount(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertEquals("Unexpected search result: "+shadows, 1, shadows.size()); + + PrismObject shadow = shadows.get(0); + display("Shadow", shadow); + assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); + jackAccountOid = shadow.getOid(); + +// assertConnectorOperationIncrement(2); + assertConnectorSimulatedPagingSearchIncrement(0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(1); + } + + @Test + public void test105SeachPiratesByCn() throws Exception { + final String TEST_NAME = "test105SeachPiratesByCn"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getGroupObjectClass(), prismContext); + ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter("cn", GROUP_PIRATES_NAME)); + + rememberConnectorOperationCount(); + rememberConnectorSimulatedPagingSearchCount(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertEquals("Unexpected search result: "+shadows, 1, shadows.size()); + + PrismObject shadow = shadows.get(0); + display("Shadow", shadow); + groupPiratesOid = shadow.getOid(); + +// assertConnectorOperationIncrement(1); + assertConnectorSimulatedPagingSearchIncrement(0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(1); + } + + @Test + public void test110GetJack() throws Exception { + final String TEST_NAME = "test110GetJack"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + rememberConnectorOperationCount(); + rememberConnectorSimulatedPagingSearchCount(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + PrismObject shadow = modelService.getObject(ShadowType.class, jackAccountOid, null, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + display("Shadow", shadow); + assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); + jackAccountOid = shadow.getOid(); + + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + + assertAttribute(shadow, "dn", "CN=Jack Sparrow,CN=Users,DC=ad,DC=evolveum,DC=com"); + assertAttribute(shadow, "cn", ACCOUNT_JACK_FULL_NAME); + assertAttribute(shadow, "sn", "Sparrow"); + assertAttribute(shadow, "description", "The best pirate the world has ever seen"); + assertAttribute(shadow, "sAMAccountName", ACCOUNT_JACK_SAM_ACCOUNT_NAME); + assertAttribute(shadow, "lastLogon", 0L); + + assertConnectorOperationIncrement(1); + assertConnectorSimulatedPagingSearchIncrement(0); + + assertLdapConnectorInstances(1); + } + + + /** + * No paging. It should return all accounts. + */ + @Test + public void test150SeachAllAccounts() throws Exception { + final String TEST_NAME = "test150SeachAllAccounts"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + rememberConnectorOperationCount(); + rememberConnectorSimulatedPagingSearchCount(); + + // WHEN + SearchResultList> searchResultList = doSearch(TEST_NAME, query, + NUMBER_OF_ACCOUNTS, task, result); + + // TODO: why 11? should be 1 +// assertConnectorOperationIncrement(11); + assertConnectorSimulatedPagingSearchIncrement(0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + +// assertLdapConnectorInstances(2); + } + + /** + * This is in one block. + */ + @Test + public void test152SeachFirst2Accounts() throws Exception { + final String TEST_NAME = "test152SeachFirst2Accounts"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = ObjectPaging.createEmptyPaging(); + paging.setMaxSize(2); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(TEST_NAME, query, 2, task, result); + +// assertConnectorOperationIncrement(1); + assertConnectorSimulatedPagingSearchIncrement(0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + +// assertLdapConnectorInstances(2); + } + +// /** +// * Blocksize is 5, so this gets more than two blocks. +// */ +// @Test +// public void test154SeachFirst11Accounts() throws Exception { +// final String TEST_NAME = "test154SeachFirst11Accounts"; +// TestUtil.displayTestTile(this, TEST_NAME); +// +// // GIVEN +// Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); +// OperationResult result = task.getResult(); +// +// ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); +// +// ObjectPaging paging = ObjectPaging.createEmptyPaging(); +// paging.setMaxSize(11); +// query.setPaging(paging); +// +// SearchResultList> searchResultList = doSearch(TEST_NAME, query, 11, task, result); +// +// assertConnectorOperationIncrement(1); +// assertConnectorSimulatedPagingSearchIncrement(0); +// +// SearchResultMetadata metadata = searchResultList.getMetadata(); +// if (metadata != null) { +// assertFalse(metadata.isPartialResults()); +// } +// +// assertLdapConnectorInstances(2); +// } +// +// @Test +// public void test162SeachFirst2AccountsOffset0() throws Exception { +// final String TEST_NAME = "test162SeachFirst2AccountsOffset0"; +// TestUtil.displayTestTile(this, TEST_NAME); +// +// // GIVEN +// Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); +// OperationResult result = task.getResult(); +// +// ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); +// +// ObjectPaging paging = ObjectPaging.createEmptyPaging(); +// paging.setOffset(0); +// paging.setMaxSize(2); +// query.setPaging(paging); +// +// SearchResultList> searchResultList = doSearch(TEST_NAME, query, 2, task, result); +// +// assertConnectorOperationIncrement(1); +// assertConnectorSimulatedPagingSearchIncrement(0); +// +// SearchResultMetadata metadata = searchResultList.getMetadata(); +// if (metadata != null) { +// assertFalse(metadata.isPartialResults()); +// } +// +// assertLdapConnectorInstances(2); +// } +// +// /** +// * Blocksize is 5, so this is in one block. +// * There is offset, so VLV should be used. +// * No explicit sorting. +// */ +// @Test +// public void test172Search2AccountsOffset1() throws Exception { +// final String TEST_NAME = "test172Search2AccountsOffset1"; +// TestUtil.displayTestTile(this, TEST_NAME); +// +// // GIVEN +// Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); +// OperationResult result = task.getResult(); +// +// ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); +// +// ObjectPaging paging = ObjectPaging.createPaging(1, 2); +// query.setPaging(paging); +// +// SearchResultList> searchResultList = doSearch(TEST_NAME, query, 2, task, result); +// +// assertConnectorOperationIncrement(1); +// assertConnectorSimulatedPagingSearchIncrement(0); +// +// SearchResultMetadata metadata = searchResultList.getMetadata(); +// if (metadata != null) { +// assertFalse(metadata.isPartialResults()); +// } +// +// assertLdapConnectorInstances(2); +// } +// +// /** +// * Blocksize is 5, so this gets more than two blocks. +// * There is offset, so VLV should be used. +// * No explicit sorting. +// */ +// @Test +// public void test174SeachFirst11AccountsOffset2() throws Exception { +// final String TEST_NAME = "test174SeachFirst11AccountsOffset2"; +// TestUtil.displayTestTile(this, TEST_NAME); +// +// // GIVEN +// Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); +// OperationResult result = task.getResult(); +// +// ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); +// +// ObjectPaging paging = ObjectPaging.createPaging(2, 11); +// query.setPaging(paging); +// +// allowDuplicateSearchResults = true; +// +// // WHEN +// SearchResultList> searchResultList = doSearch(TEST_NAME, query, 11, task, result); +// +// // THEN +// allowDuplicateSearchResults = false; +// +// assertConnectorOperationIncrement(1); +// assertConnectorSimulatedPagingSearchIncrement(0); +// +// SearchResultMetadata metadata = searchResultList.getMetadata(); +// if (metadata != null) { +// assertFalse(metadata.isPartialResults()); +// } +// +// assertLdapConnectorInstances(2); +// } +// +// /** +// * Blocksize is 5, so this is in one block. +// * There is offset, so VLV should be used. +// * Explicit sorting. +// */ +// @Test +// public void test182Search2AccountsOffset1SortCn() throws Exception { +// final String TEST_NAME = "test182Search2AccountsOffset1SortCn"; +// TestUtil.displayTestTile(this, TEST_NAME); +// +// // GIVEN +// Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); +// OperationResult result = task.getResult(); +// +// ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); +// +// ObjectPaging paging = ObjectPaging.createPaging(1, 2); +// paging.setOrdering(getAttributePath(resource, "cn"), OrderDirection.ASCENDING); +// query.setPaging(paging); +// +// SearchResultList> shadows = doSearch(TEST_NAME, query, 2, task, result); +// +// assertAccountShadow(shadows.get(0), "CN=Adalbert Meduza,OU=evolveum,DC=win,DC=evolveum,DC=com"); +// assertAccountShadow(shadows.get(1), "CN=Adalbert Meduza1,OU=evolveum,DC=win,DC=evolveum,DC=com"); +// +// assertConnectorOperationIncrement(1); +// assertConnectorSimulatedPagingSearchIncrement(0); +// +// SearchResultMetadata metadata = shadows.getMetadata(); +// if (metadata != null) { +// assertFalse(metadata.isPartialResults()); +// } +// +// assertLdapConnectorInstances(2); +// } + + @Test + public void test200AssignAccountBarbossa() throws Exception { + final String TEST_NAME = "test200AssignAccountBarbossa"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + long tsStart = System.currentTimeMillis(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + assignAccount(USER_BARBOSSA_OID, getResourceOid(), null, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "title", null); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getShadowModel(shadowOid); + display("Shadow (model)", shadow); + accountBarbossaOid = shadow.getOid(); + Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); + String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); + assertNotNull("No identifier in "+shadow, accountBarbossaIcfUid); + + assertEquals("Wrong ICFS UID", + AdUtils.formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), + accountBarbossaIcfUid); + + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); + + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + ResourceAttribute createTimestampAttribute = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, "createTimeStamp")); + assertNotNull("No createTimestamp in "+shadow, createTimestampAttribute); + Long createTimestamp = createTimestampAttribute.getRealValue(); + // LDAP server may be on a different host. Allow for some clock offset. + TestUtil.assertBetween("Wrong createTimestamp in "+shadow, roundTsDown(tsStart)-120000, roundTsUp(tsEnd)+120000, createTimestamp); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test210ModifyAccountBarbossaTitle() throws Exception { + final String TEST_NAME = "test210ModifyAccountBarbossaTitle"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + ObjectDelta delta = ObjectDelta.createEmptyModifyDelta(ShadowType.class, accountBarbossaOid, prismContext); + QName attrQName = new QName(MidPointConstants.NS_RI, "title"); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + PropertyDelta attrDelta = PropertyDelta.createModificationReplaceProperty( + new ItemPath(ShadowType.F_ATTRIBUTES, attrQName), attrDef, "Captain"); + delta.addModification(attrDelta); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + modelService.executeChanges(MiscSchemaUtil.createCollection(delta), null, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "title", "Captain"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test212ModifyAccountBarbossaShowInAdvancedViewOnlyTrue() throws Exception { + final String TEST_NAME = "test212ModifyAccountBarbossaShowInAdvancedViewOnlyTrue"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + ObjectDelta delta = ObjectDelta.createEmptyModifyDelta(ShadowType.class, accountBarbossaOid, prismContext); + QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + PropertyDelta attrDelta = PropertyDelta.createModificationReplaceProperty( + new ItemPath(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); + delta.addModification(attrDelta); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + modelService.executeChanges(MiscSchemaUtil.createCollection(delta), null, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "showInAdvancedViewOnly", "TRUE"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + +// assertLdapConnectorInstances(2); + } + + /** + * Modify USER, test boolean value mapping. + */ + @Test + public void test213ModifyUserBarbossaShowInAdvancedViewOnlyFalse() throws Exception { + final String TEST_NAME = "test213ModifyUserBarbossaShowInAdvancedViewOnlyFalse"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + + ObjectDelta delta = ObjectDelta.createEmptyModifyDelta(ShadowType.class, accountBarbossaOid, prismContext); + QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + PropertyDelta attrDelta = PropertyDelta.createModificationReplaceProperty( + new ItemPath(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); + delta.addModification(attrDelta); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + modifyUserReplace(USER_BARBOSSA_OID, + new ItemPath(UserType.F_EXTENSION, EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME), + task, result, Boolean.FALSE); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "showInAdvancedViewOnly", "FALSE"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test220ModifyUserBarbossaPassword() throws Exception { + final String TEST_NAME = "test220ModifyUserBarbossaPassword"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + ProtectedStringType userPasswordPs = new ProtectedStringType(); + userPasswordPs.setClearValue("here.There.Be.Monsters"); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + modifyUserReplace(USER_BARBOSSA_OID, + new ItemPath(UserType.F_CREDENTIALS, CredentialsType.F_PASSWORD, PasswordType.F_VALUE), + task, result, userPasswordPs); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "title", "Captain"); + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, "here.There.Be.Monsters"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test230DisableUserBarbossa() throws Exception { + final String TEST_NAME = "test230DisableUserBarbossa"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + modifyUserReplace(USER_BARBOSSA_OID, + new ItemPath(UserType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS), + task, result, ActivationStatusType.DISABLED); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + +// assertLdapConnectorInstances(2); + + PrismObject user = getUser(USER_BARBOSSA_OID); + assertAdministrativeStatus(user, ActivationStatusType.DISABLED); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountDisabled(shadow); + + try { + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, "here.There.Be.Monsters"); + AssertJUnit.fail("Password authentication works, but it should fail"); + } catch (SecurityException e) { + // this is expected + } + +// assertLdapConnectorInstances(2); + } + + @Test + public void test239EnableUserBarbossa() throws Exception { + final String TEST_NAME = "test239EnableUserBarbossa"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + modifyUserReplace(USER_BARBOSSA_OID, + new ItemPath(UserType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS), + task, result, ActivationStatusType.ENABLED); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + PrismObject user = getUser(USER_BARBOSSA_OID); + assertAdministrativeStatus(user, ActivationStatusType.ENABLED); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountEnabled(shadow); + +// assertLdapConnectorInstances(2); + } + + /** + * This should create account with a group. And disabled. + */ + @Test + public void test250AssignGuybrushPirates() throws Exception { + final String TEST_NAME = "test250AssignGuybrushPirates"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + modifyUserReplace(USER_GUYBRUSH_OID, + new ItemPath(UserType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS), + task, result, ActivationStatusType.DISABLED); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + assignRole(USER_GUYBRUSH_OID, ROLE_PIRATES_OID, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + display("Entry", entry); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + assertLdapGroupMember(entry, GROUP_PIRATES_NAME); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + assertAdministrativeStatus(user, ActivationStatusType.DISABLED); + String shadowOid = getSingleLinkOid(user); + + PrismObject shadow = getObject(ShadowType.class, shadowOid); + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + assertAccountDisabled(shadow); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test255ModifyUserGuybrushPassword() throws Exception { + final String TEST_NAME = "test255ModifyUserGuybrushPassword"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + ProtectedStringType userPasswordPs = new ProtectedStringType(); + userPasswordPs.setClearValue("wanna.be.a.123"); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + modifyUserReplace(USER_GUYBRUSH_OID, + new ItemPath(UserType.F_CREDENTIALS, CredentialsType.F_PASSWORD, PasswordType.F_VALUE), + task, result, userPasswordPs); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + try { + assertLdapPassword(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME, "wanna.be.a.123"); + AssertJUnit.fail("Password authentication works, but it should fail"); + } catch (SecurityException e) { + // this is expected, account is disabled + } + +// assertLdapConnectorInstances(2); + } + + @Test + public void test260EnableGyubrush() throws Exception { + final String TEST_NAME = "test260EnableGyubrush"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + modifyUserReplace(USER_GUYBRUSH_OID, + new ItemPath(UserType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS), + task, result, ActivationStatusType.ENABLED); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + assertAdministrativeStatus(user, ActivationStatusType.ENABLED); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountEnabled(shadow); + + assertLdapPassword(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME, "wanna.be.a.123"); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test300AssignBarbossaPirates() throws Exception { + final String TEST_NAME = "test300AssignBarbossaPirates"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + assignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + display("Entry", entry); + assertAttribute(entry, "title", "Captain"); + + assertLdapGroupMember(entry, GROUP_PIRATES_NAME); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + PrismObject shadow = getObject(ShadowType.class, shadowOid); + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test390ModifyUserBarbossaRename() throws Exception { + final String TEST_NAME = "test390ModifyUserBarbossaRename"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_BARBOSSA_OID, UserType.F_NAME, + PrismTestUtil.createPolyString(USER_CPTBARBOSSA_USERNAME)); + objectDelta.addModificationReplaceProperty(UserType.F_FULL_NAME, + PrismTestUtil.createPolyString(USER_CPTBARBOSSA_FULL_NAME)); + Collection> deltas = MiscSchemaUtil.createCollection(objectDelta); + + + // WHEN + TestUtil.displayWhen(TEST_NAME); + modelService.executeChanges(deltas, null, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); + assertAttribute(entry, "title", "Captain"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + display("Shadow after rename (model)", shadow); + + PrismObject repoShadow = repositoryService.getObject(ShadowType.class, shadowOid, null, result); + display("Shadow after rename (repo)", repoShadow); + + assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + +// assertLdapConnectorInstances(2); + } + + // TODO: create account with a group membership + + + @Test + public void test395UnAssignBarbossaPirates() throws Exception { + final String TEST_NAME = "test395UnAssignBarbossaPirates"; + TestUtil.displayTestTile(this, TEST_NAME); + + // TODO: do this on another account. There is a bad interference with rename. + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + unassignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); + display("Entry", entry); + assertAttribute(entry, "title", "Captain"); + + assertLdapNoGroupMember(entry, GROUP_PIRATES_NAME); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + PrismObject shadow = getObject(ShadowType.class, shadowOid); + IntegrationTestTools.assertNoAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test399UnAssignAccountBarbossa() throws Exception { + final String TEST_NAME = "test399UnAssignAccountBarbossa"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + unassignAccount(USER_BARBOSSA_OID, getResourceOid(), null, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertNoLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); + + PrismObject user = getUser(USER_BARBOSSA_OID); + assertNoLinkedAccount(user); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test500AddOrgMeleeIsland() throws Exception { + final String TEST_NAME = "test500AddOrgMeleeIsland"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + PrismObject org = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(OrgType.class).instantiate(); + OrgType orgType = org.asObjectable(); + orgType.setName(new PolyStringType(GROUP_MELEE_ISLAND_NAME)); + AssignmentType metaroleAssignment = new AssignmentType(); + ObjectReferenceType metaroleRef = new ObjectReferenceType(); + metaroleRef.setOid(ROLE_META_ORG_OID); + metaroleRef.setType(RoleType.COMPLEX_TYPE); + metaroleAssignment.setTargetRef(metaroleRef); + orgType.getAssignment().add(metaroleAssignment); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + addObject(org, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + orgMeleeIslandOid = org.getOid(); + Entry entry = assertLdapGroup(GROUP_MELEE_ISLAND_NAME); + + org = getObject(OrgType.class, orgMeleeIslandOid); + groupMeleeOid = getSingleLinkOid(org); + PrismObject shadow = getShadowModel(groupMeleeOid); + display("Shadow (model)", shadow); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test510AssignGuybrushMeleeIsland() throws Exception { + final String TEST_NAME = "test510AssignGuybrushMeleeIsland"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + assignOrg(USER_GUYBRUSH_OID, orgMeleeIslandOid, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getShadowModel(shadowOid); + display("Shadow (model)", shadow); + + assertLdapGroupMember(entry, GROUP_MELEE_ISLAND_NAME); + + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupMeleeOid); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test600AssignAccountSubman() throws Exception { + final String TEST_NAME = "test600AssignAccountSubman"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(this.getClass().getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + assignRole(USER_SUBMAN_OID, ROLE_SUBMISSIVE_OID, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + Entry entry = assertLdapSubAccount(USER_SUBMAN_NAME, USER_SUBMAN_FULL_NAME); + display("Sub entry", entry); + assertAttribute(entry, "title", null); + + PrismObject userAfter = getUser(USER_SUBMAN_OID); + String shadowOid = getSingleLinkOid(userAfter); + PrismObject shadow = getShadowModel(shadowOid); + display("Shadow (model)", shadow); + accountSubmanOid = shadow.getOid(); + Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); + String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); + assertNotNull("No identifier in "+shadow, accountBarbossaIcfUid); + + assertEquals("Wrong ICFS UID", + AdUtils.formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), + accountBarbossaIcfUid); + + assertLdapPassword(getSubLdapConnectionConfig(), USER_SUBMAN_NAME, USER_SUBMAN_FULL_NAME, USER_SUBMAN_PASSWORD); + + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + ResourceAttribute createTimestampAttribute = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, "createTimeStamp")); + assertNotNull("No createTimestamp in "+shadow, createTimestampAttribute); + Long createTimestamp = createTimestampAttribute.getRealValue(); + // LDAP server may be on a different host. Allow for some clock offset. + TestUtil.assertBetween("Wrong createTimestamp in "+shadow, roundTsDown(tsStart)-120000, roundTsUp(tsEnd)+120000, createTimestamp); + +// assertLdapConnectorInstances(2); + } + + @Override + protected void assertAccountShadow(PrismObject shadow, String dn) throws SchemaException { + super.assertAccountShadow(shadow, dn); + ResourceAttribute primaryIdAttr = ShadowUtil.getAttribute(shadow, getPrimaryIdentifierAttributeQName()); + assertNotNull("No primary identifier ("+getPrimaryIdentifierAttributeQName()+" in "+shadow, primaryIdAttr); + String primaryId = primaryIdAttr.getRealValue(); + assertTrue("Unexpected chars in primary ID: '"+primaryId+"'", primaryId.matches("[a-z0-9\\-]+")); + } + + @Override + protected Entry assertLdapAccount(String samAccountName, String cn) throws LdapException, IOException, CursorException { + Entry entry = searchLdapAccount("(cn="+cn+")"); + assertAttribute(entry, "cn", cn); + assertAttribute(entry, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName); + return entry; + } + + protected Entry assertLdapSubAccount(String samAccountName, String cn) throws LdapException, IOException, CursorException { + Entry entry = searchLdapAccount(getSubLdapConnectionConfig(), "(cn="+cn+")"); + assertAttribute(entry, "cn", cn); + assertAttribute(entry, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName); + return entry; + } + + @Override + protected void assertNoLdapAccount(String uid) throws LdapException, IOException, CursorException { + throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); + } + + protected void assertNoLdapAccount(String uid, String cn) throws LdapException, IOException, CursorException { + LdapNetworkConnection connection = ldapConnect(); + List entriesCn = ldapSearch(connection, "(cn="+cn+")"); + List entriesSamAccountName = ldapSearch(connection, "(sAMAccountName="+uid+")"); + ldapDisconnect(connection); + + assertEquals("Unexpected number of entries for cn="+cn+": "+entriesCn, 0, entriesCn.size()); + assertEquals("Unexpected number of entries for sAMAccountName="+uid+": "+entriesSamAccountName, 0, entriesSamAccountName.size()); + } + + @Override + protected String toAccountDn(String username) { + throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); + } + + @Override + protected String toAccountDn(String username, String fullName) { + return ("CN="+fullName+","+getPeopleLdapSuffix()); + } + + protected String toAccountSubDn(String username, String fullName) { + return ("CN="+fullName+","+getPeopleLdapSubSuffix()); + } + + @Override + protected Rdn toAccountRdn(String username, String fullName) { + try { + return new Rdn(new Ava("CN", fullName)); + } catch (LdapInvalidDnException e) { + throw new IllegalStateException(e.getMessage(),e); + } + } + + protected void assertLdapPassword(String uid, String fullName, String password) throws LdapException, IOException, CursorException { + assertLdapPassword(null, uid, fullName, password); + } + + protected void assertLdapPassword(UserLdapConnectionConfig config, String uid, String fullName, String password) throws LdapException, IOException, CursorException { + Entry entry = getLdapAccountByCn(config, fullName); + assertLdapPassword(config, entry, password); + } + + protected void assertLdapPassword(String uid, String password) throws LdapException, IOException, CursorException { + throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); + } + + protected ObjectQuery createSamAccountNameQuery(String samAccountName) throws SchemaException { + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter(ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName)); + return query; + } + + @Override + protected Entry createAccountEntry(String uid, String cn, String givenName, String sn) throws LdapException { + byte[] password = encodePassword("Secret.123"); + Entry entry = new DefaultEntry(toAccountDn(uid, cn), + "objectclass", getLdapAccountObjectClass(), + ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, uid, + "cn", cn, + "givenName", givenName, + "sn", sn, + ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512", + ATTRIBUTE_UNICODE_PWD_NAME, password); + return entry; + } + + private byte[] encodePassword(String password) { + String quotedPassword = "\"" + password + "\""; + try { + return quotedPassword.getBytes("UTF-16LE"); + } catch (UnsupportedEncodingException e) { + throw new SystemException(e.getMessage(), e); + } + } + + public void assertAttribute(PrismObject shadow, String attrName, T... expectedValues) { + assertAttribute(shadow, new QName(getResourceNamespace(), attrName), expectedValues); + } + + public void assertAttribute(PrismObject shadow, QName attrQname, T... expectedValues) { + List actualValues = ShadowUtil.getAttributeValues(shadow, attrQname); + PrismAsserts.assertSets("attribute "+attrQname+" in " + shadow, actualValues, expectedValues); + } + + protected abstract void assertAccountDisabled(PrismObject shadow); + + protected abstract void assertAccountEnabled(PrismObject shadow); +} diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapRawTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapRawTest.java index a06b6f43daf..8cadc46b212 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapRawTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapRawTest.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.testing.conntest; import static com.evolveum.midpoint.test.IntegrationTestTools.display; +import static com.evolveum.midpoint.testing.conntest.AdUtils.*; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertTrue; diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapTest.java index 96df201f69c..1d46faeaef4 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapTest.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.testing.conntest; import static com.evolveum.midpoint.test.IntegrationTestTools.display; +import static com.evolveum.midpoint.testing.conntest.AdUtils.*; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertNotNull; @@ -106,11 +107,7 @@ public abstract class AbstractAdLdapTest extends AbstractLdapSynchronizationTest protected static final File ROLE_META_ORG_FILE = new File(TEST_DIR, "role-meta-org.xml"); protected static final String ROLE_META_ORG_OID = "f2ad0ace-45d7-11e5-af54-001e8c717e5b"; - public static final String ATTRIBUTE_OBJECT_GUID_NAME = "objectGUID"; - public static final String ATTRIBUTE_SAM_ACCOUNT_NAME_NAME = "sAMAccountName"; - public static final String ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME = "userAccountControl"; - public static final QName ATTRIBUTE_USER_ACCOUNT_CONTROL_QNAME = new QName(MidPointConstants.NS_RI, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME); - public static final String ATTRIBUTE_UNICODE_PWD_NAME = "unicodePwd"; + protected static final String ACCOUNT_JACK_SAM_ACCOUNT_NAME = "jack"; protected static final String ACCOUNT_JACK_FULL_NAME = "Jack Sparrow"; @@ -268,62 +265,7 @@ public void test020Schema() throws Exception { final String TEST_NAME = "test020Schema"; TestUtil.displayTestTile(this, TEST_NAME); - ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); - display("Resource schema", resourceSchema); - - RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource); - display("Refined schema", refinedSchema); - accountObjectClassDefinition = refinedSchema.findObjectClassDefinition(getAccountObjectClass()); - assertNotNull("No definition for object class "+getAccountObjectClass(), accountObjectClassDefinition); - display("Account object class def", accountObjectClassDefinition); - - ResourceAttributeDefinition cnDef = accountObjectClassDefinition.findAttributeDefinition("cn"); - PrismAsserts.assertDefinition(cnDef, new QName(MidPointConstants.NS_RI, "cn"), DOMUtil.XSD_STRING, 1, 1); - assertTrue("cn read", cnDef.canRead()); - assertTrue("cn modify", cnDef.canModify()); - assertTrue("cn add", cnDef.canAdd()); - - ResourceAttributeDefinition samAccountNameDef = accountObjectClassDefinition.findAttributeDefinition(ATTRIBUTE_SAM_ACCOUNT_NAME_NAME); - PrismAsserts.assertDefinition(samAccountNameDef, - new QName(MidPointConstants.NS_RI, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME), DOMUtil.XSD_STRING, 0, 1); - assertTrue("samAccountNameDef read", samAccountNameDef.canRead()); - assertTrue("samAccountNameDef modify", samAccountNameDef.canModify()); - assertTrue("samAccountNameDef add", samAccountNameDef.canAdd()); - - - ResourceAttributeDefinition oDef = accountObjectClassDefinition.findAttributeDefinition("o"); - PrismAsserts.assertDefinition(oDef, new QName(MidPointConstants.NS_RI, "o"), DOMUtil.XSD_STRING, 0, -1); - assertTrue("o read", oDef.canRead()); - assertTrue("o modify", oDef.canModify()); - assertTrue("o add", oDef.canAdd()); - - ResourceAttributeDefinition createTimestampDef = accountObjectClassDefinition.findAttributeDefinition("createTimeStamp"); - PrismAsserts.assertDefinition(createTimestampDef, new QName(MidPointConstants.NS_RI, "createTimeStamp"), - DOMUtil.XSD_LONG, 0, 1); - assertTrue("createTimeStampDef read", createTimestampDef.canRead()); - assertFalse("createTimeStampDef modify", createTimestampDef.canModify()); - assertFalse("createTimeStampDef add", createTimestampDef.canAdd()); - - ResourceAttributeDefinition isCriticalSystemObjectDef = accountObjectClassDefinition.findAttributeDefinition("isCriticalSystemObject"); - PrismAsserts.assertDefinition(isCriticalSystemObjectDef, new QName(MidPointConstants.NS_RI, "isCriticalSystemObject"), - DOMUtil.XSD_BOOLEAN, 0, 1); - assertTrue("isCriticalSystemObject read", isCriticalSystemObjectDef.canRead()); - assertTrue("isCriticalSystemObject modify", isCriticalSystemObjectDef.canModify()); - assertTrue("isCriticalSystemObject add", isCriticalSystemObjectDef.canAdd()); - - ResourceAttributeDefinition nTSecurityDescriptorDef = accountObjectClassDefinition.findAttributeDefinition("nTSecurityDescriptor"); - PrismAsserts.assertDefinition(nTSecurityDescriptorDef, new QName(MidPointConstants.NS_RI, "nTSecurityDescriptor"), - DOMUtil.XSD_BASE64BINARY, 0, 1); - assertTrue("nTSecurityDescriptor read", nTSecurityDescriptorDef.canRead()); - assertTrue("nTSecurityDescriptor modify", nTSecurityDescriptorDef.canModify()); - assertTrue("nTSecurityDescriptor add", nTSecurityDescriptorDef.canAdd()); - - ResourceAttributeDefinition lastLogonDef = accountObjectClassDefinition.findAttributeDefinition("lastLogon"); - PrismAsserts.assertDefinition(lastLogonDef, new QName(MidPointConstants.NS_RI, "lastLogon"), - DOMUtil.XSD_LONG, 0, 1); - assertTrue("lastLogonDef read", lastLogonDef.canRead()); - assertTrue("lastLogonDef modify", lastLogonDef.canModify()); - assertTrue("lastLogonDef add", lastLogonDef.canAdd()); + accountObjectClassDefinition = AdUtils.assertAdSchema(resource, getAccountObjectClass(), prismContext); assertLdapConnectorInstances(1); } @@ -713,7 +655,7 @@ public void test200AssignAccountBarbossa() throws Exception { assertNotNull("No identifier in "+shadow, accountBarbossaIcfUid); assertEquals("Wrong ICFS UID", - formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), + AdUtils.formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), accountBarbossaIcfUid); assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); @@ -1404,33 +1346,6 @@ public void assertAttribute(PrismObject shadow, QName attrQname, PrismAsserts.assertSets("attribute "+attrQname+" in " + shadow, actualValues, expectedValues); } - /** - * Returns dashed GUID notation formatted from simple hex-encoded binary. - * - * E.g. "2f01c06bb1d0414e9a69dd3841a13506" -> "6bc0012f-d0b1-4e41-9a69-dd3841a13506" - */ - public String formatGuidToDashedNotation(String hexValue) { - if (hexValue == null) { - return null; - } - StringBuilder sb = new StringBuilder(); - sb.append(hexValue.substring(6, 8)); - sb.append(hexValue.substring(4, 6)); - sb.append(hexValue.substring(2, 4)); - sb.append(hexValue.substring(0, 2)); - sb.append('-'); - sb.append(hexValue.substring(10, 12)); - sb.append(hexValue.substring(8, 10)); - sb.append('-'); - sb.append(hexValue.substring(14, 16)); - sb.append(hexValue.substring(12, 14)); - sb.append('-'); - sb.append(hexValue.substring(16, 20)); - sb.append('-'); - sb.append(hexValue.substring(20, 32)); - return sb.toString(); - } - protected abstract void assertAccountDisabled(PrismObject shadow); protected abstract void assertAccountEnabled(PrismObject shadow); diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapTest.java index a9c0f734aeb..aa5a3520e23 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapTest.java @@ -514,12 +514,20 @@ protected Entry getLdapAccountByUid(String uid) throws LdapException, IOExceptio } protected Entry getLdapAccountByCn(String cn) throws LdapException, IOException, CursorException { - return searchLdapAccount("(cn="+cn+")"); + return getLdapAccountByCn(null, cn); + } + + protected Entry getLdapAccountByCn(UserLdapConnectionConfig config, String cn) throws LdapException, IOException, CursorException { + return searchLdapAccount(config, "(cn="+cn+")"); } protected Entry searchLdapAccount(String filter) throws LdapException, IOException, CursorException { - LdapNetworkConnection connection = ldapConnect(); - List entries = ldapSearch(connection, filter); + return searchLdapAccount(null, filter); + } + + protected Entry searchLdapAccount(UserLdapConnectionConfig config, String filter) throws LdapException, IOException, CursorException { + LdapNetworkConnection connection = ldapConnect(config); + List entries = ldapSearch(config, connection, filter); ldapDisconnect(connection); assertEquals("Unexpected number of entries for "+filter+": "+entries, 1, entries.size()); @@ -671,7 +679,15 @@ protected void assertLdapNoGroupMember(String accountEntryDn, String groupName) } protected List ldapSearch(LdapNetworkConnection connection, String filter) throws LdapException, CursorException { - return ldapSearch(connection, getLdapSuffix(), filter, SearchScope.SUBTREE, "*", "isMemberOf", "memberof", "isMemberOf", getPrimaryIdentifierAttributeName()); + return ldapSearch(null, connection, filter); + } + + protected List ldapSearch(UserLdapConnectionConfig config, LdapNetworkConnection connection, String filter) throws LdapException, CursorException { + String baseContext = getLdapSuffix(); + if (config != null && config.getBaseContext() != null) { + baseContext = config.getBaseContext(); + } + return ldapSearch(connection, baseContext, filter, SearchScope.SUBTREE, "*", "isMemberOf", "memberof", "isMemberOf", getPrimaryIdentifierAttributeName()); } protected List ldapSearch(LdapNetworkConnection connection, String baseDn, String filter, SearchScope scope, String... attributes) throws LdapException, CursorException { @@ -710,7 +726,11 @@ protected void assertLdapPassword(String uid, String password) throws LdapExcept } protected void assertLdapPassword(Entry entry, String password) throws LdapException, IOException, CursorException { - LdapNetworkConnection conn = ldapConnect(entry.getDn().toString(), password); + assertLdapPassword(null, entry, password); + } + + protected void assertLdapPassword(UserLdapConnectionConfig config, Entry entry, String password) throws LdapException, IOException, CursorException { + LdapNetworkConnection conn = ldapConnect(config, entry.getDn().toString(), password); assertTrue("Not connected", conn.isConnected()); assertTrue("Not authenticated", conn.isAuthenticated()); ldapDisconnect(conn); @@ -773,7 +793,14 @@ protected void deleteLdapEntry(String dn) throws LdapException, IOException { * Silent delete. Used to clean up after previous test runs. */ protected void cleanupDelete(String dn) throws LdapException, IOException, CursorException { - LdapNetworkConnection connection = ldapConnect(); + cleanupDelete(null, dn); + } + + /** + * Silent delete. Used to clean up after previous test runs. + */ + protected void cleanupDelete(UserLdapConnectionConfig config, String dn) throws LdapException, IOException, CursorException { + LdapNetworkConnection connection = ldapConnect(config); Entry entry = getLdapEntry(connection, dn); if (entry != null) { connection.delete(dn); @@ -815,11 +842,37 @@ protected LdapNetworkConnection ldapConnect() throws LdapException, IOException } protected LdapNetworkConnection ldapConnect(String bindDn, String bindPassword) throws LdapException, IOException { - LOGGER.trace("LDAP connect to {}:{} as {}", - getLdapServerHost(), getLdapServerPort(), bindDn); - LdapConnectionConfig config = new LdapConnectionConfig(); + UserLdapConnectionConfig config = new UserLdapConnectionConfig(); config.setLdapHost(getLdapServerHost()); config.setLdapPort(getLdapServerPort()); + config.setBindDn(bindDn); + config.setBindPassword(bindPassword); + + return ldapConnect(config); + } + + protected LdapNetworkConnection ldapConnect(UserLdapConnectionConfig config, String bindDn, String bindPassword) throws LdapException, IOException { + if (config == null) { + config = new UserLdapConnectionConfig(); + config.setLdapHost(getLdapServerHost()); + config.setLdapPort(getLdapServerPort()); + } + config.setBindDn(bindDn); + config.setBindPassword(bindPassword); + + return ldapConnect(config); + } + + protected LdapNetworkConnection ldapConnect(UserLdapConnectionConfig config) throws LdapException, IOException { + if (config == null) { + config = new UserLdapConnectionConfig(); + config.setLdapHost(getLdapServerHost()); + config.setLdapPort(getLdapServerPort()); + config.setBindDn(getLdapBindDn()); + config.setBindPassword(getLdapBindPassword()); + } + LOGGER.trace("LDAP connect to {}:{} as {}", + config.getLdapHost(), config.getLdapPort(), config.getBindDn()); if (useSsl()) { config.setUseSsl(true); @@ -843,21 +896,21 @@ public X509Certificate[] getAcceptedIssuers() { LdapNetworkConnection connection = new LdapNetworkConnection(config); boolean connected = connection.connect(); if (!connected) { - AssertJUnit.fail("Cannot connect to LDAP server "+getLdapServerHost()+":"+getLdapServerPort()); + AssertJUnit.fail("Cannot connect to LDAP server "+config.getLdapHost()+":"+config.getLdapPort()); } LOGGER.trace("LDAP connected to {}:{}, executing bind as {}", - getLdapServerHost(), getLdapServerPort(), bindDn); + config.getLdapHost(), config.getLdapPort(), config.getBindDn()); BindRequest bindRequest = new BindRequestImpl(); - bindRequest.setDn(new Dn(bindDn)); - bindRequest.setCredentials(bindPassword); + bindRequest.setDn(new Dn(config.getBindDn())); + bindRequest.setCredentials(config.getBindPassword()); bindRequest.setSimple(true); BindResponse bindResponse = connection.bind(bindRequest); if (bindResponse.getLdapResult().getResultCode() != ResultCodeEnum.SUCCESS) { ldapDisconnect(connection); - throw new SecurityException("Bind as "+bindDn+" failed: "+bindResponse.getLdapResult().getDiagnosticMessage()+" ("+bindResponse.getLdapResult().getResultCode()+")"); + throw new SecurityException("Bind as "+config.getBindDn()+" failed: "+bindResponse.getLdapResult().getDiagnosticMessage()+" ("+bindResponse.getLdapResult().getResultCode()+")"); } LOGGER.trace("LDAP connected to {}:{}, bound as {}", - getLdapServerHost(), getLdapServerPort(), bindDn); + config.getLdapHost(), config.getLdapPort(), config.getBindDn()); return connection; } diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AdUtils.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AdUtils.java new file mode 100644 index 00000000000..d638a9e17d5 --- /dev/null +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AdUtils.java @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2016 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.evolveum.midpoint.testing.conntest; + +import static com.evolveum.midpoint.test.IntegrationTestTools.display; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertTrue; + +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition; +import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; +import com.evolveum.midpoint.schema.processor.ResourceSchema; +import com.evolveum.midpoint.util.DOMUtil; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; + +/** + * @author semancik + * + */ +public class AdUtils { + + public static final String ATTRIBUTE_OBJECT_GUID_NAME = "objectGUID"; + public static final String ATTRIBUTE_SAM_ACCOUNT_NAME_NAME = "sAMAccountName"; + public static final String ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME = "userAccountControl"; + public static final QName ATTRIBUTE_USER_ACCOUNT_CONTROL_QNAME = new QName(MidPointConstants.NS_RI, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME); + public static final String ATTRIBUTE_UNICODE_PWD_NAME = "unicodePwd"; + + /** + * Returns dashed GUID notation formatted from simple hex-encoded binary. + * + * E.g. "2f01c06bb1d0414e9a69dd3841a13506" -> "6bc0012f-d0b1-4e41-9a69-dd3841a13506" + */ + public static String formatGuidToDashedNotation(String hexValue) { + if (hexValue == null) { + return null; + } + StringBuilder sb = new StringBuilder(); + sb.append(hexValue.substring(6, 8)); + sb.append(hexValue.substring(4, 6)); + sb.append(hexValue.substring(2, 4)); + sb.append(hexValue.substring(0, 2)); + sb.append('-'); + sb.append(hexValue.substring(10, 12)); + sb.append(hexValue.substring(8, 10)); + sb.append('-'); + sb.append(hexValue.substring(14, 16)); + sb.append(hexValue.substring(12, 14)); + sb.append('-'); + sb.append(hexValue.substring(16, 20)); + sb.append('-'); + sb.append(hexValue.substring(20, 32)); + return sb.toString(); + } + + public static ObjectClassComplexTypeDefinition assertAdSchema(PrismObject resource, QName accountObjectClass, PrismContext prismContext) throws SchemaException { + + ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); + display("Resource schema", resourceSchema); + + RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource); + display("Refined schema", refinedSchema); + ObjectClassComplexTypeDefinition accountObjectClassDefinition = refinedSchema.findObjectClassDefinition(accountObjectClass); + assertNotNull("No definition for object class "+accountObjectClass, accountObjectClassDefinition); + display("Account object class def", accountObjectClassDefinition); + + ResourceAttributeDefinition cnDef = accountObjectClassDefinition.findAttributeDefinition("cn"); + PrismAsserts.assertDefinition(cnDef, new QName(MidPointConstants.NS_RI, "cn"), DOMUtil.XSD_STRING, 1, 1); + assertTrue("cn read", cnDef.canRead()); + assertTrue("cn modify", cnDef.canModify()); + assertTrue("cn add", cnDef.canAdd()); + + ResourceAttributeDefinition samAccountNameDef = accountObjectClassDefinition.findAttributeDefinition(ATTRIBUTE_SAM_ACCOUNT_NAME_NAME); + PrismAsserts.assertDefinition(samAccountNameDef, + new QName(MidPointConstants.NS_RI, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME), DOMUtil.XSD_STRING, 0, 1); + assertTrue("samAccountNameDef read", samAccountNameDef.canRead()); + assertTrue("samAccountNameDef modify", samAccountNameDef.canModify()); + assertTrue("samAccountNameDef add", samAccountNameDef.canAdd()); + + + ResourceAttributeDefinition oDef = accountObjectClassDefinition.findAttributeDefinition("o"); + PrismAsserts.assertDefinition(oDef, new QName(MidPointConstants.NS_RI, "o"), DOMUtil.XSD_STRING, 0, -1); + assertTrue("o read", oDef.canRead()); + assertTrue("o modify", oDef.canModify()); + assertTrue("o add", oDef.canAdd()); + + ResourceAttributeDefinition createTimestampDef = accountObjectClassDefinition.findAttributeDefinition("createTimeStamp"); + PrismAsserts.assertDefinition(createTimestampDef, new QName(MidPointConstants.NS_RI, "createTimeStamp"), + DOMUtil.XSD_LONG, 0, 1); + assertTrue("createTimeStampDef read", createTimestampDef.canRead()); + assertFalse("createTimeStampDef modify", createTimestampDef.canModify()); + assertFalse("createTimeStampDef add", createTimestampDef.canAdd()); + + ResourceAttributeDefinition isCriticalSystemObjectDef = accountObjectClassDefinition.findAttributeDefinition("isCriticalSystemObject"); + PrismAsserts.assertDefinition(isCriticalSystemObjectDef, new QName(MidPointConstants.NS_RI, "isCriticalSystemObject"), + DOMUtil.XSD_BOOLEAN, 0, 1); + assertTrue("isCriticalSystemObject read", isCriticalSystemObjectDef.canRead()); + assertTrue("isCriticalSystemObject modify", isCriticalSystemObjectDef.canModify()); + assertTrue("isCriticalSystemObject add", isCriticalSystemObjectDef.canAdd()); + + ResourceAttributeDefinition nTSecurityDescriptorDef = accountObjectClassDefinition.findAttributeDefinition("nTSecurityDescriptor"); + PrismAsserts.assertDefinition(nTSecurityDescriptorDef, new QName(MidPointConstants.NS_RI, "nTSecurityDescriptor"), + DOMUtil.XSD_BASE64BINARY, 0, 1); + assertTrue("nTSecurityDescriptor read", nTSecurityDescriptorDef.canRead()); + assertTrue("nTSecurityDescriptor modify", nTSecurityDescriptorDef.canModify()); + assertTrue("nTSecurityDescriptor add", nTSecurityDescriptorDef.canAdd()); + + ResourceAttributeDefinition lastLogonDef = accountObjectClassDefinition.findAttributeDefinition("lastLogon"); + PrismAsserts.assertDefinition(lastLogonDef, new QName(MidPointConstants.NS_RI, "lastLogon"), + DOMUtil.XSD_LONG, 0, 1); + assertTrue("lastLogonDef read", lastLogonDef.canRead()); + assertTrue("lastLogonDef modify", lastLogonDef.canModify()); + assertTrue("lastLogonDef add", lastLogonDef.canAdd()); + + return accountObjectClassDefinition; + } +} diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/TestAdLdapChimera.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/TestAdLdapChimera.java new file mode 100644 index 00000000000..31be909993c --- /dev/null +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/TestAdLdapChimera.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2015-2016 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.evolveum.midpoint.testing.conntest; + +import java.io.File; + +import org.testng.annotations.AfterClass; +import org.testng.annotations.Listeners; + +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.test.util.MidPointTestConstants; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; + +/** + * @author semancik + * + */ +public class TestAdLdapChimera extends AbstractAdLdapMultidomainTest { + + @Override + protected String getResourceOid() { + return "eced6d24-73e3-11e5-8457-93eff15a6b85"; + } + + @Override + protected File getResourceFile() { + return new File(getBaseDir(), "resource-chimera.xml"); + } + + @Override + protected String getLdapServerHost() { + return "chimera.ad.evolveum.com"; + } + + @Override + protected int getLdapServerPort() { + return 636; + } + + @Override + protected void assertAccountDisabled(PrismObject shadow) { + assertAdministrativeStatus(shadow, ActivationStatusType.DISABLED); + } + + @Override + protected void assertAccountEnabled(PrismObject shadow) { + assertAdministrativeStatus(shadow, ActivationStatusType.ENABLED); + } + +} diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/UserLdapConnectionConfig.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/UserLdapConnectionConfig.java new file mode 100644 index 00000000000..2b3e0f7f4e0 --- /dev/null +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/UserLdapConnectionConfig.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2016 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.evolveum.midpoint.testing.conntest; + +import org.apache.directory.ldap.client.api.LdapConnectionConfig; + +/** + * @author semancik + * + */ +public class UserLdapConnectionConfig extends LdapConnectionConfig { + + private String bindDn; + private String bindPassword; + private String baseContext; + + public String getBindDn() { + return bindDn; + } + + public void setBindDn(String bindDn) { + this.bindDn = bindDn; + } + + public String getBindPassword() { + return bindPassword; + } + + public void setBindPassword(String bindPassword) { + this.bindPassword = bindPassword; + } + + public String getBaseContext() { + return baseContext; + } + + public void setBaseContext(String baseContext) { + this.baseContext = baseContext; + } + +} diff --git a/testing/conntest/src/test/resources/ad-ldap-multidomain/resource-chimera.xml b/testing/conntest/src/test/resources/ad-ldap-multidomain/resource-chimera.xml new file mode 100644 index 00000000000..51a5f71aa4e --- /dev/null +++ b/testing/conntest/src/test/resources/ad-ldap-multidomain/resource-chimera.xml @@ -0,0 +1,645 @@ + + + + Active Directory Chimera (LDAP) + + + + + c:connectorType + com.evolveum.polygon.connector.ldap.ad.AdLdapConnector + + + + + + + chimera.ad.evolveum.com + 636 + DC=ad,DC=evolveum,DC=com + CN=midpoint,CN=Users,DC=ad,DC=evolveum,DC=com + ssl + + qwe.123 + + host=hydra.ad.evolveum.com; baseContext=DC=sub,DC=ad,DC=evolveum,DC=com; bindDn=CN=midpoint,CN=Users,DC=sub,DC=ad,DC=evolveum,DC=com + ignore + resolve + + + false + false + false + + + + + + ri:user + ri:group + ri:organizationalUnit + ri:domain + + + + + + + + account + Default Account + true + ri:user + + ri:organizationalUnit + + + attributes/dn + CN=Users,DC=ad,DC=evolveum,DC=com + + + + + ri:dn + Distinguished Name + mr:distinguishedName + + + $user/fullName + + + + + + + + + ri:sAMAccountName + Login name + + + $user/name + + + + + name + + + + + + ri:cn + + 0 + + + + fullName + + + + + fullName + + + + + + ri:sn + + 0 + + + + familyName + + + + + familyName + + + + + + ri:givenName + + + givenName + + + + + givenName + + + + + + ri:userPrincipalName + + + $user/name + + + + + + + + + ri:pwdLastSet + + + -1 + + + + + + ri:createTimeStamp + explicit + + + + ri:objectCategory + + + CN=Person,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com + + + + + + ri:showInAdvancedViewOnly + + + extension/showInAdvancedViewOnly + + + + + + ri:group + AD Group Membership + entitlement + group + objectToSubject + ri:member + ri:dn + ri:memberOf + ri:dn + + + + + + + + + + + + + + + + + + generic + ou-top + Top Org + true + ri:organizationalUnit + + ri:organizationalUnit + + + attributes/dn + OU=Org,DC=ad,DC=evolveum,DC=com + + + + + ri:dn + Distinguished Name + mr:distinguishedName + + + name + + + + + + + + + ri:ou + + 0 + + + + name + + + + + + + ri:objectCategory + + + CN=Organizational-Unit,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com + + + + + + + + + account + sub + Sub Account + false + ri:user + + ri:organizationalUnit + + + attributes/dn + CN=Users,DC=sub,DC=ad,DC=evolveum,DC=com + + + + + ri:dn + Distinguished Name + mr:distinguishedName + + + $user/fullName + + + + + + + + + ri:sAMAccountName + Login name + + + $user/name + + + + + name + + + + + + ri:cn + + 0 + + + + fullName + + + + + fullName + + + + + + ri:sn + + 0 + + + + familyName + + + + + familyName + + + + + + ri:givenName + + + givenName + + + + + givenName + + + + + + ri:userPrincipalName + + + $user/name + + + + + + + + + ri:pwdLastSet + + + -1 + + + + + + ri:createTimeStamp + explicit + + + + ri:nTSecurityDescriptor + + + 0 + + + + + ri:instanceType + + + 0 + + + + + ri:objectCategory + + + 0 + + + + CN=Person,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com + + + + + + + ri:group + AD Group Membership + entitlement + group + objectToSubject + ri:member + ri:dn + ri:memberOf + ri:dn + + + + + + + + + + + + + + + + + + generic + ou-sub + Sub Org + ri:organizationalUnit + + ri:domain + + + attributes/dn + DC=sub,DC=ad,DC=evolveum,DC=com + + + + + ri:dn + Distinguished Name + mr:distinguishedName + + + name + + + + + + + + + ri:ou + + 0 + + + + name + + + + + + + ri:objectCategory + + + CN=Organizational-Unit,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com + + + + + + + + + entitlement + group + AD Group + Groups in the parent (top) domain + true + ri:group + + ri:organizationalUnit + + + attributes/dn + CN=Users,DC=ad,DC=evolveum,DC=com + + + + + dn + mr:distinguishedName + + + $focus/name + + + + + + + + ri:cn + mr:stringIgnoreCase + + + $focus/name + + + + + name + + + + + ri:description + + strong + + description + + + + + description + + + + + + + + + true + + + + + + Account sync + ri:user + account + default + UserType + true + + + c:name + + $shadow/attributes/sAMAccountName + + + + + + linked + true + + + deleted + + + + unlinked + + + + unmatched + + + + + + + + diff --git a/testing/conntest/src/test/resources/ad-ldap-multidomain/role-meta-org.xml b/testing/conntest/src/test/resources/ad-ldap-multidomain/role-meta-org.xml new file mode 100644 index 00000000000..a8ea121408f --- /dev/null +++ b/testing/conntest/src/test/resources/ad-ldap-multidomain/role-meta-org.xml @@ -0,0 +1,54 @@ + + + + Org Metarole + + + + + entitlement + group + + + + + + + account + default + + ri:group + + + + + entitlement + group + + + + + + + 2 + + + diff --git a/testing/conntest/src/test/resources/ad-ldap-multidomain/role-pirate.xml b/testing/conntest/src/test/resources/ad-ldap-multidomain/role-pirate.xml new file mode 100644 index 00000000000..56a61fa3a0e --- /dev/null +++ b/testing/conntest/src/test/resources/ad-ldap-multidomain/role-pirate.xml @@ -0,0 +1,45 @@ + + + + Pirate + + + + + ri:group + false + + + + + + attributes/ri:cn + Pirates + + + true + + + + + + + \ No newline at end of file diff --git a/testing/conntest/src/test/resources/ad-ldap-multidomain/role-submissive.xml b/testing/conntest/src/test/resources/ad-ldap-multidomain/role-submissive.xml new file mode 100644 index 00000000000..a46a0d425c3 --- /dev/null +++ b/testing/conntest/src/test/resources/ad-ldap-multidomain/role-submissive.xml @@ -0,0 +1,31 @@ + + + + Submissive + Role that creates account in AD subdomain + + + + account + sub + + + diff --git a/testing/conntest/src/test/resources/ad-ldap-multidomain/user-subman.xml b/testing/conntest/src/test/resources/ad-ldap-multidomain/user-subman.xml new file mode 100644 index 00000000000..c0c2e7ffe34 --- /dev/null +++ b/testing/conntest/src/test/resources/ad-ldap-multidomain/user-subman.xml @@ -0,0 +1,44 @@ + + + + subman + + + enabled + + + Sub Man + Sub + Man + Subterra + + + + + sub.123 + + + + + diff --git a/testing/conntest/src/test/resources/common/system-configuration.xml b/testing/conntest/src/test/resources/common/system-configuration.xml index fce9b3ebcb8..b44049f52f1 100644 --- a/testing/conntest/src/test/resources/common/system-configuration.xml +++ b/testing/conntest/src/test/resources/common/system-configuration.xml @@ -1,6 +1,6 @@