From 61631df7e0bf8c187de56e433d462d38707f7bbd Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 18 Jan 2018 14:46:02 +0100 Subject: [PATCH 1/4] Add some notes --- .../common/expression/script/ScriptExpressionFactory.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionFactory.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionFactory.java index 164d3ab7e7f..97077675f05 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionFactory.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionFactory.java @@ -94,7 +94,8 @@ public ScriptExpression createScriptExpression(ScriptExpressionEvaluatorType exp expression.setOutputDefinition(outputDefinition); expression.setObjectResolver(objectResolver); expression.setFunctions(new ArrayList<>(functions)); - + + // TODO make this code synchronized and ensure that searchIterative below is executed under privileged account if (customFunctionLibraryCache != null) { expression.getFunctions().addAll(customFunctionLibraryCache.values()); } else { From cf0bea6a55c40a5ef42ae81a505a4ba1840ad428 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Thu, 18 Jan 2018 15:41:45 +0100 Subject: [PATCH 2/4] Provisioning password value caching (MID-4397) --- ...ositeRefinedObjectClassDefinitionImpl.java | 24 ++- .../xml/ns/public/common/common-core-3.xsd | 111 ++++++++++ .../test/AbstractModelIntegrationTest.java | 181 ++++------------- .../impl/ProvisioningServiceImpl.java | 88 +++----- .../impl/ResourceEventListenerImpl.java | 13 +- .../provisioning/impl/ShadowCache.java | 33 +-- .../impl/ShadowCacheProvisioner.java | 7 +- .../provisioning/impl/ShadowManager.java | 135 ++++++++---- .../impl/dummy/AbstractBasicDummyTest.java | 101 +++++---- .../impl/dummy/AbstractDummyTest.java | 6 +- .../provisioning/impl/dummy/TestDummy.java | 192 ++++++++++-------- .../impl/dummy/TestDummyCaching.java | 12 ++ .../dummy/dummy-caching/resource-dummy.xml | 10 +- .../test/AbstractIntegrationTest.java | 111 ++++++++++ 14 files changed, 622 insertions(+), 402 deletions(-) diff --git a/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/CompositeRefinedObjectClassDefinitionImpl.java b/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/CompositeRefinedObjectClassDefinitionImpl.java index ce19c21779e..9dd8284fc71 100644 --- a/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/CompositeRefinedObjectClassDefinitionImpl.java +++ b/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/CompositeRefinedObjectClassDefinitionImpl.java @@ -38,6 +38,7 @@ import javax.xml.namespace.QName; import java.util.*; import java.util.function.Consumer; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -585,10 +586,25 @@ public Collection getNamesOfAttributesWithInboundExpressions() } @Override - public ResourcePasswordDefinitionType getPasswordDefinition() { // TODO what if there is a conflict? - return getRefinedObjectClassDefinitionsStream() - .map(def -> def.getPasswordDefinition()) - .findFirst().orElse(null); + public ResourcePasswordDefinitionType getPasswordDefinition() { + return findInDefinitions(def -> def.getPasswordDefinition()); + } + + private T findInDefinitions(Function transform) { + if (structuralObjectClassDefinition != null) { + T val = transform.apply(structuralObjectClassDefinition); + if (val != null) { + return val; + } + } + // TODO what if there is a conflict? + for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition: auxiliaryObjectClassDefinitions) { + T val = transform.apply(auxiliaryObjectClassDefinition); + if (val != null) { + return val; + } + } + return null; } @Override diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd index c48b28d1daf..6bd4ec3bfb1 100755 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd @@ -5840,6 +5840,60 @@ + + + + The way how an resource password is compared with the current password. + + + + 3.7.1 + + + + + + + Auto-detect comparison method. If no way of comparison + is possible then an error is indicated. + Note: Currently this strategy will end with an error if there + is no cached password value. + + + + + + + + + + There is no way to compare password. Any operation to that + tries to compare the password on the resource should end + up with an error. + + + + + + + + + + Compare password with the value cached in the shadow. + This setting assumes that passwords for all accounts are + properly cached. Therefore if there is no password value + in the shadow then we assume that there is no resource password. + + + + + + + + + + + @@ -5860,6 +5914,19 @@ + + + + The way how an resource password is compared with the current password. + This strategy is used when midPoint needs to compare candidate password + with existing resource passowrd. E.g. used in password policies that state + that passwords on several resources cannot be the same. + + + 3.7.1 + + + @@ -5887,6 +5954,23 @@ + + + + Password caching policy. + Currently, password storage format (encrypted, hashed) will be the same + as the global password storage format used for the entire system. + Definition of a specific password storage format might be added later. + + + 3.7.1 + + + + @@ -12009,6 +12093,16 @@ + + + + Specifies which projection should be used in case that projection origin is selected. + + + 3.7.1 + + + @@ -12063,6 +12157,23 @@ + + + + One of object's projecion is the origin. + E.g. in case of user password specific projection + linked to the user will be scanned. + If this origin type is selected then also + the projectionDiscriminator must be specified. + Note: Currently the only supported value is + resource password. + + + + 3.7.1 + + + diff --git a/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java b/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java index cbe3679a5f7..aefd254d2dc 100644 --- a/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java +++ b/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java @@ -527,142 +527,6 @@ protected void assertAdministrativeStatus(PrismObject obje assert status == expected : "status property is "+status+", expected "+expected+" in "+object; } - protected ObjectDelta createModifyUserReplaceDelta(String userOid, QName propertyName, Object... newRealValue) { - return createModifyUserReplaceDelta(userOid, new ItemPath(propertyName), newRealValue); - } - - protected ObjectDelta createModifyUserReplaceDelta(String userOid, ItemPath propertyName, Object... newRealValue) { - return ObjectDelta.createModificationReplaceProperty(UserType.class, userOid, propertyName, prismContext, newRealValue); - } - - protected ObjectDelta createModifyUserAddDelta(String userOid, ItemPath propertyName, Object... newRealValue) { - return ObjectDelta.createModificationAddProperty(UserType.class, userOid, propertyName, prismContext, newRealValue); - } - - protected ObjectDelta createModifyUserDeleteDelta(String userOid, ItemPath propertyName, Object... newRealValue) { - return ObjectDelta.createModificationDeleteProperty(UserType.class, userOid, propertyName, prismContext, newRealValue); - } - - protected ObjectDelta createModifyUserAddAccount(String userOid, PrismObject resource) throws SchemaException { - PrismObject account = getAccountShadowDefinition().instantiate(); - ObjectReferenceType resourceRef = new ObjectReferenceType(); - resourceRef.setOid(resource.getOid()); - account.asObjectable().setResourceRef(resourceRef); - RefinedResourceSchema refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema(resource); - account.asObjectable().setObjectClass(refinedSchema.getDefaultRefinedDefinition(ShadowKindType.ACCOUNT).getObjectClassDefinition().getTypeName()); - - ObjectDelta userDelta = ObjectDelta.createEmptyModifyDelta(UserType.class, userOid, prismContext); - PrismReferenceValue accountRefVal = new PrismReferenceValue(); - accountRefVal.setObject(account); - ReferenceDelta accountDelta = ReferenceDelta.createModificationAdd(UserType.F_LINK_REF, getUserDefinition(), accountRefVal); - userDelta.addModification(accountDelta); - - return userDelta; - } - - protected ObjectDelta createModifyUserDeleteAccount(String userOid, PrismObject resource) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { - String accountOid = getLinkRefOid(userOid, resource.getOid()); - PrismObject account = getShadowModel(accountOid); - - ObjectDelta userDelta = ObjectDelta.createEmptyModifyDelta(UserType.class, userOid, prismContext); - PrismReferenceValue accountRefVal = new PrismReferenceValue(); - accountRefVal.setObject(account); - ReferenceDelta accountDelta = ReferenceDelta.createModificationDelete(UserType.F_LINK_REF, getUserDefinition(), accountRefVal); - userDelta.addModification(accountDelta); - - return userDelta; - } - - protected ObjectDelta createModifyUserUnlinkAccount(String userOid, PrismObject resource) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { - String accountOid = getLinkRefOid(userOid, resource.getOid()); - - ObjectDelta userDelta = ObjectDelta.createEmptyModifyDelta(UserType.class, userOid, prismContext); - PrismReferenceValue accountRefVal = new PrismReferenceValue(); - accountRefVal.setOid(accountOid); - ReferenceDelta accountDelta = ReferenceDelta.createModificationDelete(UserType.F_LINK_REF, getUserDefinition(), accountRefVal); - userDelta.addModification(accountDelta); - - return userDelta; - } - - protected ObjectDelta createModifyAccountShadowEmptyDelta(String accountOid) { - return ObjectDelta.createEmptyModifyDelta(ShadowType.class, accountOid, prismContext); - } - - protected ObjectDelta createModifyAccountShadowReplaceAttributeDelta(String accountOid, - PrismObject resource, String attributeName, Object... newRealValue) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException { - return createModifyAccountShadowReplaceAttributeDelta(accountOid, resource, getAttributeQName(resource, attributeName), newRealValue); - } - - protected ObjectDelta createModifyAccountShadowReplaceAttributeDelta(String accountOid, - PrismObject resource, QName attributeName, Object... newRealValue) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException { - return createModifyAccountShadowReplaceDelta(accountOid, resource, new ItemPath(ShadowType.F_ATTRIBUTES, attributeName), newRealValue); - } - - protected ObjectDelta createModifyAccountShadowReplaceDelta(String accountOid, PrismObject resource, ItemPath itemPath, Object... newRealValue) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException { - if (ShadowType.F_ATTRIBUTES.equals(ItemPath.getName(itemPath.first()))) { - PropertyDelta attributeDelta = createAttributeReplaceDelta(resource, ((NameItemPathSegment)itemPath.last()).getName(), newRealValue); - ObjectDelta accountDelta = ObjectDelta.createModifyDelta(accountOid, attributeDelta, ShadowType.class, prismContext); - return accountDelta; - } else { - ObjectDelta accountDelta = ObjectDelta.createModificationReplaceProperty( - ShadowType.class, accountOid, itemPath, prismContext, newRealValue); - return accountDelta; - } - } - - protected PropertyDelta createAttributeReplaceDelta(PrismObject resource, String attributeLocalName, T... newRealValue) throws SchemaException { - return createAttributeReplaceDelta(resource, getAttributeQName(resource, attributeLocalName), newRealValue); - } - - protected PropertyDelta createAttributeReplaceDelta(PrismObject resource, QName attributeQName, T... newRealValue) throws SchemaException { - PrismPropertyDefinition attributeDefinition = getAttributeDefinition(resource, attributeQName); - if (attributeDefinition == null) { - throw new SchemaException("No definition for attribute "+ attributeQName+ " in " + resource); - } - return PropertyDelta.createModificationReplaceProperty(new ItemPath(ShadowType.F_ATTRIBUTES, attributeQName), - attributeDefinition, newRealValue); - } - - protected PropertyDelta createAttributeAddDelta(PrismObject resource, String attributeLocalName, T... newRealValue) throws SchemaException { - return createAttributeAddDelta(resource, getAttributeQName(resource, attributeLocalName), newRealValue); - } - - protected PropertyDelta createAttributeAddDelta(PrismObject resource, QName attributeQName, T... newRealValue) throws SchemaException { - PrismPropertyDefinition attributeDefinition = getAttributeDefinition(resource, attributeQName); - if (attributeDefinition == null) { - throw new SchemaException("No definition for attribute "+ attributeQName+ " in " + resource); - } - return PropertyDelta.createModificationAddProperty(new ItemPath(ShadowType.F_ATTRIBUTES, attributeQName), - attributeDefinition, newRealValue); - } - - protected PropertyDelta createAttributeDeleteDelta(PrismObject resource, String attributeLocalName, T... newRealValue) throws SchemaException { - return createAttributeDeleteDelta(resource, getAttributeQName(resource, attributeLocalName), newRealValue); - } - - protected PropertyDelta createAttributeDeleteDelta(PrismObject resource, QName attributeQName, T... newRealValue) throws SchemaException { - PrismPropertyDefinition attributeDefinition = getAttributeDefinition(resource, attributeQName); - if (attributeDefinition == null) { - throw new SchemaException("No definition for attribute "+ attributeQName+ " in " + resource); - } - return PropertyDelta.createModificationDeleteProperty(new ItemPath(ShadowType.F_ATTRIBUTES, attributeQName), - attributeDefinition, newRealValue); - } - - protected ResourceAttributeDefinition getAttributeDefinition(PrismObject resource, QName attributeName) throws SchemaException { - RefinedResourceSchema refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema(resource); - if (refinedSchema == null) { - throw new SchemaException("No refined schema for "+resource); - } - RefinedObjectClassDefinition accountDefinition = refinedSchema.getDefaultRefinedDefinition(ShadowKindType.ACCOUNT); - return accountDefinition.findAttributeDefinition(attributeName); - } - - protected ObjectDelta createModifyAccountShadowAddDelta(String accountOid, ItemPath propertyName, Object... newRealValue) { - return ObjectDelta.createModificationAddProperty(ShadowType.class, accountOid, propertyName, prismContext, newRealValue); - } - protected void modifyUserReplace(String userOid, QName propertyName, Task task, OperationResult result, Object... newRealValue) throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, ObjectAlreadyExistsException, PolicyViolationException, SecurityViolationException { @@ -2650,16 +2514,51 @@ protected void assertShadowModel(PrismObject accountShadow, String o assertShadowCommon(accountShadow, oid, username, resourceType, objectClass, nameMatchingRule, false); IntegrationTestTools.assertProvisioningShadow(accountShadow, resourceType, RefinedAttributeDefinition.class, objectClass); } + + + protected ObjectDelta createModifyUserAddAccount(String userOid, PrismObject resource) throws SchemaException { + PrismObject account = getAccountShadowDefinition().instantiate(); + ObjectReferenceType resourceRef = new ObjectReferenceType(); + resourceRef.setOid(resource.getOid()); + account.asObjectable().setResourceRef(resourceRef); + RefinedResourceSchema refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema(resource); + account.asObjectable().setObjectClass(refinedSchema.getDefaultRefinedDefinition(ShadowKindType.ACCOUNT).getObjectClassDefinition().getTypeName()); + + ObjectDelta userDelta = ObjectDelta.createEmptyModifyDelta(UserType.class, userOid, prismContext); + PrismReferenceValue accountRefVal = new PrismReferenceValue(); + accountRefVal.setObject(account); + ReferenceDelta accountDelta = ReferenceDelta.createModificationAdd(UserType.F_LINK_REF, getUserDefinition(), accountRefVal); + userDelta.addModification(accountDelta); + + return userDelta; + } + + protected ObjectDelta createModifyUserDeleteAccount(String userOid, PrismObject resource) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + String accountOid = getLinkRefOid(userOid, resource.getOid()); + PrismObject account = getShadowModel(accountOid); + + ObjectDelta userDelta = ObjectDelta.createEmptyModifyDelta(UserType.class, userOid, prismContext); + PrismReferenceValue accountRefVal = new PrismReferenceValue(); + accountRefVal.setObject(account); + ReferenceDelta accountDelta = ReferenceDelta.createModificationDelete(UserType.F_LINK_REF, getUserDefinition(), accountRefVal); + userDelta.addModification(accountDelta); - protected QName getAttributeQName(PrismObject resource, String attributeLocalName) { - String resourceNamespace = ResourceTypeUtil.getResourceNamespace(resource); - return new QName(resourceNamespace, attributeLocalName); + return userDelta; } - protected ItemPath getAttributePath(PrismObject resource, String attributeLocalName) { - return new ItemPath(ShadowType.F_ATTRIBUTES, getAttributeQName(resource, attributeLocalName)); + protected ObjectDelta createModifyUserUnlinkAccount(String userOid, PrismObject resource) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + String accountOid = getLinkRefOid(userOid, resource.getOid()); + + ObjectDelta userDelta = ObjectDelta.createEmptyModifyDelta(UserType.class, userOid, prismContext); + PrismReferenceValue accountRefVal = new PrismReferenceValue(); + accountRefVal.setOid(accountOid); + ReferenceDelta accountDelta = ReferenceDelta.createModificationDelete(UserType.F_LINK_REF, getUserDefinition(), accountRefVal); + userDelta.addModification(accountDelta); + + return userDelta; } + // TASKS protected void waitForTaskFinish(Task task, boolean checkSubresult) throws Exception { diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningServiceImpl.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningServiceImpl.java index f0bd2560388..f3c90d0c267 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningServiceImpl.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningServiceImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2017 Evolveum + * Copyright (c) 2010-2018 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,9 +36,9 @@ import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.prism.crypto.EncryptionException; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.prism.delta.PropertyDelta; import com.evolveum.midpoint.prism.query.NoneFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectPaging; @@ -68,7 +68,6 @@ import com.evolveum.midpoint.schema.statistics.ConnectorOperationalStatus; import com.evolveum.midpoint.schema.util.ObjectQueryUtil; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; -import com.evolveum.midpoint.schema.util.ResourceTypeUtil; import com.evolveum.midpoint.schema.util.SchemaDebugUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.DebugUtil; @@ -82,7 +81,6 @@ import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.CachingMetadataType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnectorHostType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnectorType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FailedOperationTypeType; @@ -91,7 +89,6 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ProvisioningScriptType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowCheckType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; /** @@ -247,23 +244,10 @@ public PrismObject getObject(Class type, String oid result.computeStatus(); } throw e; - } catch (CommunicationException e) { + } catch (CommunicationException | SchemaException | ConfigurationException | SecurityViolationException | RuntimeException | Error e) { ProvisioningUtil.recordFatalError(LOGGER, result, "Error getting object OID=" + oid + ": " + e.getMessage(), e); throw e; - } catch (SchemaException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Error getting object OID=" + oid + ": " + e.getMessage(), e); - throw e; - } catch (ConfigurationException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Error getting object OID=" + oid + ": " + e.getMessage(), e); - throw e; - } catch (SecurityViolationException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Error getting object OID=" + oid + ": " + e.getMessage(), e); - throw e; - } catch (SystemException e) { - // Do NOT wrap this into SystemException again - ProvisioningUtil.recordFatalError(LOGGER, result, "Error getting object OID=" + oid + ": " + e.getMessage(), e); - throw e; - } catch (RuntimeException e){ + } catch (EncryptionException e){ ProvisioningUtil.recordFatalError(LOGGER, result, "Error getting object OID=" + oid + ": " + e.getMessage(), e); throw new SystemException(e); } @@ -335,6 +319,9 @@ public String addObject(PrismObject object, OperationP } catch (ExpressionEvaluationException ex) { ProvisioningUtil.recordFatalError(LOGGER, result, "Couldn't add object. Expression error: " + ex.getMessage(), ex); throw ex; + } catch (EncryptionException e) { + ProvisioningUtil.recordFatalError(LOGGER, result, null, e); + throw new SystemException(e.getMessage(), e); } catch (RuntimeException | Error ex){ ProvisioningUtil.recordFatalError(LOGGER, result, "Couldn't add object. Runtime error: " + ex.getMessage(), ex); throw ex; @@ -386,34 +373,16 @@ public int synchronize(ResourceShadowDiscriminator shadowCoordinates, Task task, processedChanges = getShadowCache(Mode.STANDARD).synchronize(shadowCoordinates, tokenProperty, task, result); LOGGER.debug("Synchronization of {} done, token {}, {} changes", resource, tokenProperty, processedChanges); - } catch (ObjectNotFoundException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Synchronization error: object not found: " + e.getMessage(), e); - throw e; - } catch (CommunicationException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Synchronization error: communication problem: " + e.getMessage(), e); + } catch (ObjectNotFoundException | CommunicationException | SchemaException | SecurityViolationException | ConfigurationException | ExpressionEvaluationException | RuntimeException | Error e) { + ProvisioningUtil.recordFatalError(LOGGER, result, null, e); throw e; - } catch (ObjectAlreadyExistsException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Synchronization error: object already exists problem: " + e.getMessage(), e); + } catch (ObjectAlreadyExistsException | EncryptionException e) { + ProvisioningUtil.recordFatalError(LOGGER, result, null, e); throw new SystemException(e); } catch (GenericFrameworkException e) { ProvisioningUtil.recordFatalError(LOGGER, result, "Synchronization error: generic connector framework error: " + e.getMessage(), e); throw new GenericConnectorException(e.getMessage(), e); - } catch (SchemaException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Synchronization error: schema problem: " + e.getMessage(), e); - throw e; - } catch (SecurityViolationException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Synchronization error: security violation: " + e.getMessage(), e); - throw e; - } catch (ConfigurationException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Synchronization error: configuration problem: " + e.getMessage(), e); - throw e; - } catch (RuntimeException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Synchronization error: unexpected problem: " + e.getMessage(), e); - throw e; - } catch (ExpressionEvaluationException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Synchronization error: expression error: " + e.getMessage(), e); - throw e; } result.recordSuccess(); @@ -678,34 +647,19 @@ public String modifyObject(Class type, String oid, result.computeStatus(); } - } catch (CommunicationException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Couldn't modify object: communication problem: " + e.getMessage(), e); + } catch (CommunicationException | SchemaException | ObjectNotFoundException | ConfigurationException | SecurityViolationException + | ExpressionEvaluationException | RuntimeException | Error e) { + ProvisioningUtil.recordFatalError(LOGGER, result, null, e); throw e; } catch (GenericFrameworkException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Couldn't modify object: generic error in the connector: " + e.getMessage(), - e); + ProvisioningUtil.recordFatalError(LOGGER, result, null, e); throw new CommunicationException(e.getMessage(), e); - } catch (SchemaException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Couldn't modify object: schema problem: " + e.getMessage(), e); - throw e; - } catch (ObjectNotFoundException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Couldn't modify object: object doesn't exist: " + e.getMessage(), e); - throw e; - } catch (RuntimeException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Couldn't modify object: unexpected problem: " + e.getMessage(), e); - throw new SystemException("Internal error: " + e.getMessage(), e); - } catch (ConfigurationException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Couldn't modify object: configuration problem: " + e.getMessage(), e); - throw e; - } catch (SecurityViolationException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Couldn't modify object: security violation: " + e.getMessage(), e); - throw e; + } catch (EncryptionException e) { + ProvisioningUtil.recordFatalError(LOGGER, result, null, e); + throw new SystemException(e.getMessage(), e); } catch (ObjectAlreadyExistsException e) { ProvisioningUtil.recordFatalError(LOGGER, result, "Couldn't modify object: object after modification would conflict with another existing object: " + e.getMessage(), e); throw e; - } catch (ExpressionEvaluationException e) { - ProvisioningUtil.recordFatalError(LOGGER, result, "Couldn't modify object: expression errror: " + e.getMessage(), e); - throw e; } result.cleanupResult(); @@ -923,6 +877,10 @@ public void refreshShadow(PrismObject shadow, ProvisioningOperationO | SecurityViolationException | ObjectAlreadyExistsException | ExpressionEvaluationException | RuntimeException | Error e) { ProvisioningUtil.recordFatalError(LOGGER, result, "Couldn't refresh shadow: " + e.getClass().getSimpleName() + ": "+ e.getMessage(), e); throw e; + + } catch (EncryptionException e) { + ProvisioningUtil.recordFatalError(LOGGER, result, null, e); + throw new SystemException(e.getMessage(), e); } result.computeStatus(); @@ -933,7 +891,7 @@ public void refreshShadow(PrismObject shadow, ProvisioningOperationO private void refreshShadowLegacy(PrismObject shadow, ProvisioningOperationOptions options, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, - ObjectAlreadyExistsException, SecurityViolationException, GenericFrameworkException, ExpressionEvaluationException { + ObjectAlreadyExistsException, SecurityViolationException, GenericFrameworkException, ExpressionEvaluationException, EncryptionException { ShadowType shadowType = shadow.asObjectable(); diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceEventListenerImpl.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceEventListenerImpl.java index 4b7883efdbc..0d37fe53cf4 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceEventListenerImpl.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceEventListenerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2017 Evolveum + * Copyright (c) 2010-2018 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ //import com.evolveum.midpoint.model.ModelWebService; import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.crypto.EncryptionException; import com.evolveum.midpoint.provisioning.api.ChangeNotificationDispatcher; import com.evolveum.midpoint.provisioning.api.GenericConnectorException; import com.evolveum.midpoint.provisioning.api.ResourceEventDescription; @@ -45,6 +46,7 @@ import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SecurityViolationException; +import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; @@ -116,10 +118,13 @@ public void notifyEvent(ResourceEventDescription eventDescription, Task task, Op ObjectClassComplexTypeDefinition objectClassDefinition = ShadowUtil.getObjectClassDefinition(shadow); change.setObjectClassDefinition(objectClassDefinition); - ShadowType shadowType = shadow.asObjectable(); - LOGGER.trace("Start to precess change: {}", change.toString()); - shadowCache.processChange(ctx, change, null, parentResult); + try { + shadowCache.processChange(ctx, change, null, parentResult); + } catch (EncryptionException e) { + // TODO: better handling + throw new SystemException(e.getMessage(), e); + } LOGGER.trace("Change after processing {} . Start synchronizing.", change.toString()); shadowCache.processSynchronization(ctx, change, parentResult); diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java index 696cea9f2b0..dde9f113816 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java @@ -21,6 +21,7 @@ import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; import com.evolveum.midpoint.common.refinery.ShadowDiscriminatorObjectDelta; import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.crypto.EncryptionException; import com.evolveum.midpoint.prism.delta.*; import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; import com.evolveum.midpoint.prism.path.IdItemPathSegment; @@ -167,7 +168,7 @@ public PrismContext getPrismContext() { public PrismObject getShadow(String oid, PrismObject repositoryShadow, Collection> options, Task task, OperationResult parentResult) throws ObjectNotFoundException, CommunicationException, SchemaException, - ConfigurationException, SecurityViolationException, ExpressionEvaluationException { + ConfigurationException, SecurityViolationException, ExpressionEvaluationException, EncryptionException { Validate.notNull(oid, "Object id must not be null."); @@ -363,7 +364,7 @@ public PrismObject getShadow(String oid, PrismObject rep private PrismObject processNoFetchGet(ProvisioningContext ctx, PrismObject repositoryShadow, Collection> options, OperationResult parentResult) - throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException, EncryptionException { ResourceType resource = ctx.getResource(); ShadowType repositoryShadowType = repositoryShadow.asObjectable(); @@ -551,13 +552,13 @@ public abstract String afterAddOnResource( ProvisioningOperationState>> opState, OperationResult parentResult) throws SchemaException, ObjectAlreadyExistsException, - ObjectNotFoundException, ConfigurationException, CommunicationException, ExpressionEvaluationException; + ObjectNotFoundException, ConfigurationException, CommunicationException, ExpressionEvaluationException, EncryptionException; public String addShadow(PrismObject shadowToAdd, OperationProvisioningScriptsType scripts, ResourceType resource, ProvisioningOperationOptions options, Task task, OperationResult parentResult) throws CommunicationException, GenericFrameworkException, ObjectAlreadyExistsException, SchemaException, ObjectNotFoundException, - ConfigurationException, SecurityViolationException, ExpressionEvaluationException { + ConfigurationException, SecurityViolationException, ExpressionEvaluationException, EncryptionException { Validate.notNull(shadowToAdd, "Object to add must not be null."); InternalMonitor.recordCount(InternalCounters.SHADOW_CHANGE_OPERATION_COUNT); @@ -768,7 +769,7 @@ public abstract void afterModifyOnResource( ProvisioningOperationState>>> opState, OperationResult parentResult) throws SchemaException, ObjectNotFoundException, ConfigurationException, - CommunicationException, ExpressionEvaluationException; + CommunicationException, ExpressionEvaluationException, EncryptionException; public abstract Collection beforeModifyOnResource(PrismObject shadow, ProvisioningOperationOptions options, Collection modifications) @@ -778,7 +779,7 @@ public String modifyShadow(PrismObject repoShadow, Collection modifications, OperationProvisioningScriptsType scripts, ProvisioningOperationOptions options, Task task, OperationResult parentResult) throws CommunicationException, GenericFrameworkException, ObjectNotFoundException, - SchemaException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException { + SchemaException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException, EncryptionException { Validate.notNull(repoShadow, "Object to modify must not be null."); Validate.notNull(modifications, "Object modification must not be null."); @@ -1107,7 +1108,7 @@ private void notifyAfterDelete( } - public PrismObject refreshShadow(PrismObject repoShadow, Task task, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + public PrismObject refreshShadow(PrismObject repoShadow, Task task, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException, EncryptionException { ShadowType shadowType = repoShadow.asObjectable(); List pendingOperations = shadowType.getPendingOperation(); if (pendingOperations.isEmpty()) { @@ -1588,7 +1589,7 @@ public SearchResultMetadata searchObjectsIterative(final ProvisioningContext ctx LOGGER.error("Configuration error: {}", e.getMessage(), e); return false; } catch (ObjectNotFoundException | ObjectAlreadyExistsException | CommunicationException - | SecurityViolationException | GenericConnectorException | ExpressionEvaluationException e) { + | SecurityViolationException | GenericConnectorException | ExpressionEvaluationException | EncryptionException e) { objResult.recordFatalError(e.getMessage(), e); LOGGER.error("{}", e.getMessage(), e); return false; @@ -1803,7 +1804,7 @@ private void validateShadow(PrismObject shadow, boolean requireOid) private PrismObject lookupOrCreateShadowInRepository(ProvisioningContext ctx, PrismObject resourceShadow, boolean unknownIntent, OperationResult parentResult) throws SchemaException, ConfigurationException, ObjectNotFoundException, - CommunicationException, SecurityViolationException, GenericConnectorException, ExpressionEvaluationException { + CommunicationException, SecurityViolationException, GenericConnectorException, ExpressionEvaluationException, EncryptionException { PrismObject repoShadow = shadowManager.lookupShadowInRepository(ctx, resourceShadow, parentResult); @@ -1828,7 +1829,7 @@ private PrismObject lookupOrCreateShadowInRepository(ProvisioningCon private PrismObject createShadowInRepository(ProvisioningContext ctx, PrismObject resourceShadow, boolean unknownIntent, OperationResult parentResult) throws SchemaException, ConfigurationException, ObjectNotFoundException, - CommunicationException, SecurityViolationException, GenericConnectorException, ExpressionEvaluationException { + CommunicationException, SecurityViolationException, GenericConnectorException, ExpressionEvaluationException, EncryptionException { PrismObject repoShadow; PrismObject conflictingShadow = shadowManager.lookupConflictingShadowBySecondaryIdentifiers(ctx, @@ -2015,7 +2016,7 @@ public boolean handle(PrismObject shadow, OperationResult objResult) public int synchronize(ResourceShadowDiscriminator shadowCoordinates, PrismProperty lastToken, Task task, OperationResult parentResult) throws ObjectNotFoundException, CommunicationException, GenericFrameworkException, SchemaException, ConfigurationException, - SecurityViolationException, ObjectAlreadyExistsException, ExpressionEvaluationException { + SecurityViolationException, ObjectAlreadyExistsException, ExpressionEvaluationException, EncryptionException { InternalMonitor.recordCount(InternalCounters.PROVISIONING_ALL_EXT_OPERATION_COUNT); @@ -2109,7 +2110,7 @@ public int synchronize(ResourceShadowDiscriminator shadowCoordinates, PrismPrope return processedChanges; } catch (SchemaException | CommunicationException | GenericFrameworkException | ConfigurationException | - ObjectNotFoundException | ObjectAlreadyExistsException | ExpressionEvaluationException | RuntimeException | Error ex) { + ObjectNotFoundException | ObjectAlreadyExistsException | ExpressionEvaluationException | EncryptionException | RuntimeException | Error ex) { parentResult.recordFatalError(ex); throw ex; } @@ -2289,7 +2290,7 @@ private void deleteShadowFromRepoIfNeeded(Change change, OperationResult parentR void processChange(ProvisioningContext ctx, Change change, PrismObject oldShadow, OperationResult parentResult) throws SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ObjectNotFoundException, - GenericConnectorException, ObjectAlreadyExistsException, ExpressionEvaluationException { + GenericConnectorException, ObjectAlreadyExistsException, ExpressionEvaluationException, EncryptionException { if (oldShadow == null) { oldShadow = shadowManager.findOrAddShadowFromChange(ctx, change, parentResult); @@ -2518,13 +2519,13 @@ private ProvisioningContext reapplyDefinitions(ProvisioningContext ctx, /** * Make sure that the shadow is complete, e.g. that all the mandatory fields * are filled (e.g name, resourceRef, ...) Also transforms the shadow with - * respect to simulated capabilities. + * respect to simulated capabilities. */ private PrismObject completeShadow(ProvisioningContext ctx, PrismObject resourceShadow, PrismObject repoShadow, OperationResult parentResult) throws SchemaException, ConfigurationException, ObjectNotFoundException, - CommunicationException, SecurityViolationException, GenericConnectorException, ExpressionEvaluationException { + CommunicationException, SecurityViolationException, GenericConnectorException, ExpressionEvaluationException, EncryptionException { PrismObject resultShadow = repoShadow.clone(); @@ -2949,7 +2950,7 @@ public void propagateOperations(PrismObject resource, PrismObject< throw new IllegalStateException("Delta from outer space: "+operationDelta); } - // TODO: change operation status, set async references, etc. modify exists/dead flags --- delegate to shadow manager? + // do we need to modify exists/dead flags? } diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCacheProvisioner.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCacheProvisioner.java index 81b93e31678..f6eafa2cbfd 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCacheProvisioner.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCacheProvisioner.java @@ -22,6 +22,7 @@ import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismPropertyValue; +import com.evolveum.midpoint.prism.crypto.EncryptionException; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.PropertyDelta; @@ -44,14 +45,14 @@ public class ShadowCacheProvisioner extends ShadowCache { private static final Trace LOGGER = TraceManager.getTrace(ShadowCacheProvisioner.class); - + @Override public String afterAddOnResource( ProvisioningContext ctx, PrismObject shadowToAdd, ProvisioningOperationState>> opState, OperationResult parentResult) - throws SchemaException, ObjectAlreadyExistsException, ObjectNotFoundException, ConfigurationException, CommunicationException, ExpressionEvaluationException { + throws SchemaException, ObjectAlreadyExistsException, ObjectNotFoundException, ConfigurationException, CommunicationException, ExpressionEvaluationException, EncryptionException { return shadowManager.addNewActiveRepositoryShadow(ctx, shadowToAdd, opState, parentResult); } @@ -63,7 +64,7 @@ public void afterModifyOnResource( Collection modifications, ProvisioningOperationState>>> opState, OperationResult parentResult) - throws SchemaException, ObjectNotFoundException, ConfigurationException, CommunicationException, ExpressionEvaluationException { + throws SchemaException, ObjectNotFoundException, ConfigurationException, CommunicationException, ExpressionEvaluationException, EncryptionException { shadowManager.modifyShadow(ctx, shadow, modifications, opState, parentResult); } diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowManager.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowManager.java index ba298e186ff..fe884872c8a 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowManager.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2017 Evolveum + * Copyright (c) 2010-2018 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,12 +20,10 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; -import java.util.function.Predicate; import javax.xml.namespace.QName; import org.apache.commons.lang.BooleanUtils; -import org.jfree.util.Log; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @@ -47,6 +45,8 @@ import com.evolveum.midpoint.prism.PrismPropertyDefinition; import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.crypto.EncryptionException; +import com.evolveum.midpoint.prism.crypto.Protector; import com.evolveum.midpoint.prism.delta.ChangeType; import com.evolveum.midpoint.prism.delta.ContainerDelta; import com.evolveum.midpoint.prism.delta.ItemDelta; @@ -70,7 +70,6 @@ import com.evolveum.midpoint.repo.api.ModificationPrecondition; import com.evolveum.midpoint.repo.api.OptimisticLockingRunner; import com.evolveum.midpoint.repo.api.PreconditionViolationException; -import com.evolveum.midpoint.repo.api.RepositoryOperation; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.repo.api.VersionPrecondition; import com.evolveum.midpoint.schema.DeltaConvertor; @@ -83,7 +82,6 @@ import com.evolveum.midpoint.schema.result.AsynchronousOperationResult; import com.evolveum.midpoint.schema.result.AsynchronousOperationReturnValue; import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.result.OperationResultStatus; import com.evolveum.midpoint.schema.util.MiscSchemaUtil; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.schema.util.ResourceTypeUtil; @@ -105,6 +103,7 @@ import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.CachingMetadataType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.CachingPolicyType; import com.evolveum.midpoint.xml.ns._public.common.common_3.CachingStategyType; import com.evolveum.midpoint.xml.ns._public.common.common_3.CredentialsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FailedOperationTypeType; @@ -115,12 +114,14 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.RecordPendingOperationsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceConsistencyType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectAssociationDirectionType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourcePasswordDefinitionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; 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.ChangeTypeType; import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; +import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; /** * Responsibilities: @@ -143,17 +144,11 @@ public class ShadowManager { @Qualifier("cacheRepositoryService") private RepositoryService repositoryService; - @Autowired(required = true) - private Clock clock; - - @Autowired(required = true) - private PrismContext prismContext; - - @Autowired(required = true) - private TaskManager taskManager; - - @Autowired(required = true) - private MatchingRuleRegistry matchingRuleRegistry; + @Autowired private Clock clock; + @Autowired private PrismContext prismContext; + @Autowired private TaskManager taskManager; + @Autowired private MatchingRuleRegistry matchingRuleRegistry; + @Autowired private Protector protector; private static final Trace LOGGER = TraceManager.getTrace(ShadowManager.class); @@ -207,7 +202,6 @@ public PrismObject lookupShadowInRepository(ProvisioningContext ctx, LOGGER.trace("Searching for shadow using filter:\n{}", query.debugDump()); } -// PagingType paging = new PagingType(); // TODO: check for errors List> results = repositoryService.searchObjects(ShadowType.class, query, null, parentResult); @@ -418,7 +412,7 @@ private List> getNormalizedValue(PrismProperty attr // beware, may return null if an shadow that was to be marked as DEAD, was deleted in the meantime public PrismObject findOrAddShadowFromChange(ProvisioningContext ctx, Change change, OperationResult parentResult) throws SchemaException, CommunicationException, - ConfigurationException, SecurityViolationException, ObjectNotFoundException, ExpressionEvaluationException { + ConfigurationException, SecurityViolationException, ObjectNotFoundException, ExpressionEvaluationException, EncryptionException { // Try to locate existing shadow in the repository List> accountList = searchShadowByIdenifiers(ctx, change, parentResult); @@ -490,7 +484,7 @@ public PrismObject findOrAddShadowFromChange(ProvisioningContext ctx public PrismObject findOrAddShadowFromChangeGlobalContext(ProvisioningContext globalCtx, Change change, OperationResult parentResult) throws SchemaException, CommunicationException, - ConfigurationException, SecurityViolationException, ObjectNotFoundException, ExpressionEvaluationException { + ConfigurationException, SecurityViolationException, ObjectNotFoundException, ExpressionEvaluationException, EncryptionException { // Try to locate existing shadow in the repository List> accountList = searchShadowByIdenifiers(globalCtx, change, parentResult); @@ -563,7 +557,7 @@ public PrismObject findOrAddShadowFromChangeGlobalContext(Provisioni private PrismObject createNewShadowFromChange(ProvisioningContext ctx, Change change, OperationResult parentResult) throws SchemaException, CommunicationException, ConfigurationException, - SecurityViolationException, ObjectNotFoundException, ExpressionEvaluationException { + SecurityViolationException, ObjectNotFoundException, ExpressionEvaluationException, EncryptionException { PrismObject shadow = change.getCurrentShadow(); @@ -754,7 +748,7 @@ private void processQueryMatchingRuleFilter(ObjectFilter filter, RefinedObje // Used when new resource object is discovered public PrismObject addDiscoveredRepositoryShadow(ProvisioningContext ctx, - PrismObject resourceShadow, OperationResult parentResult) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ObjectAlreadyExistsException, ExpressionEvaluationException { + PrismObject resourceShadow, OperationResult parentResult) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ObjectAlreadyExistsException, ExpressionEvaluationException, EncryptionException { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Adding new shadow from resource object: {}", resourceShadow.debugDump()); } @@ -769,7 +763,7 @@ public PrismObject addDiscoveredRepositoryShadow(ProvisioningContext return repoShadow; } - public String addNewProposedShadow(ProvisioningContext ctx, PrismObject shadow, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException, ObjectAlreadyExistsException, SecurityViolationException { + public String addNewProposedShadow(ProvisioningContext ctx, PrismObject shadow, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException, ObjectAlreadyExistsException, SecurityViolationException, EncryptionException { ResourceConsistencyType consistency = ctx.getResource().getConsistency(); if (consistency == null) { return null; @@ -808,14 +802,14 @@ public void handlePropesedShadowError(ProvisioningContext ctx, PrismObject shadowToAdd, ProvisioningOperationState>> opState, OperationResult parentResult) - throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ObjectAlreadyExistsException, ExpressionEvaluationException { + throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ObjectAlreadyExistsException, ExpressionEvaluationException, EncryptionException { if (opState.getExistingShadowOid() != null) { // We know that we have proposed shadow updateProposedShadowAfterAdd(ctx, shadowToAdd, opState, parentResult); @@ -1257,7 +1251,7 @@ private void addPropertyDelta(Collection repoDeltas, ItemPath containerPath, * Create a copy of a shadow that is suitable for repository storage. */ private PrismObject createRepositoryShadow(ProvisioningContext ctx, PrismObject shadow) - throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ExpressionEvaluationException { + throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ExpressionEvaluationException, EncryptionException { ResourceAttributeContainer attributesContainer = ShadowUtil.getAttributesContainer(shadow); @@ -1313,12 +1307,12 @@ private PrismObject createRepositoryShadow(ProvisioningContext ctx, setKindIfNecessary(repoShadowType, ctx.getObjectClassDefinition()); // setIntentIfNecessary(repoShadowType, objectClassDefinition); - // Store only password meta-data in repo + // Store only password meta-data in repo - unless there is explicit caching CredentialsType creds = repoShadowType.getCredentials(); if (creds != null) { PasswordType passwordType = creds.getPassword(); if (passwordType != null) { - ProvisioningUtil.cleanupShadowPassword(passwordType); + preparePasswordForStorage(passwordType, ctx.getObjectClassDefinition()); PrismObject owner = null; if (ctx.getTask() != null) { owner = ctx.getTask().getOwner(); @@ -1358,13 +1352,42 @@ private PrismObject createRepositoryShadow(ProvisioningContext ctx, return repoShadow; } + private void preparePasswordForStorage(PasswordType passwordType, + RefinedObjectClassDefinition objectClassDefinition) throws SchemaException, EncryptionException { + ProtectedStringType passwordValue = passwordType.getValue(); + if (passwordValue == null) { + return; + } + CachingStategyType cachingStategy = getPasswordCachingStrategy(objectClassDefinition); + if (cachingStategy != null && cachingStategy != CachingStategyType.NONE) { + if (!passwordValue.isHashed()) { + protector.hash(passwordValue); + } + return; + } else { + ProvisioningUtil.cleanupShadowPassword(passwordType); + } + } + + private CachingStategyType getPasswordCachingStrategy(RefinedObjectClassDefinition objectClassDefinition) { + ResourcePasswordDefinitionType passwordDefinition = objectClassDefinition.getPasswordDefinition(); + if (passwordDefinition == null) { + return null; + } + CachingPolicyType passwordCachingPolicy = passwordDefinition.getCaching(); + if (passwordCachingPolicy == null) { + return null; + } + return passwordCachingPolicy.getCachingStategy(); + } + public void modifyShadow( ProvisioningContext ctx, PrismObject oldRepoShadow, Collection modifications, ProvisioningOperationState>>> opState, OperationResult parentResult) - throws SchemaException, ObjectNotFoundException, ConfigurationException, CommunicationException, ExpressionEvaluationException { + throws SchemaException, ObjectNotFoundException, ConfigurationException, CommunicationException, ExpressionEvaluationException, EncryptionException { PendingOperationType existingPendingOperation = null; if (ResourceTypeUtil.getRecordPendingOperations(ctx.getResource()) == RecordPendingOperationsType.ALL) { @@ -1400,11 +1423,11 @@ public void modifyShadow( /** * Really modifies shadow attributes. It applies the changes. It is used for synchronous operations and also for - * applying the results of completed asynchronous operations. + * applying the results of completed asynchronous operations. */ public void modifyShadowAttributes(ProvisioningContext ctx, PrismObject shadow, Collection modifications, OperationResult parentResult) - throws SchemaException, ObjectNotFoundException, ConfigurationException, CommunicationException, ExpressionEvaluationException { + throws SchemaException, ObjectNotFoundException, ConfigurationException, CommunicationException, ExpressionEvaluationException, EncryptionException { Collection shadowChanges = extractRepoShadowChanges(ctx, shadow, modifications); if (shadowChanges != null && !shadowChanges.isEmpty()) { LOGGER.trace( @@ -1453,7 +1476,7 @@ private boolean isResourceModification(ItemDelta itemDelta) { @SuppressWarnings("rawtypes") private Collection extractRepoShadowChanges(ProvisioningContext ctx, PrismObject shadow, Collection objectChange) - throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ExpressionEvaluationException { + throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ExpressionEvaluationException, EncryptionException { RefinedObjectClassDefinition objectClassDefinition = ctx.getObjectClassDefinition(); CachingStategyType cachingStrategy = ProvisioningUtil.getCachingStrategy(ctx); @@ -1488,14 +1511,51 @@ private Collection extractRepoShadowChanges(ProvisioningCon ProvisioningUtil.cleanupShadowActivation(valueToReplace.asContainerable()); } } else if (SchemaConstants.PATH_PASSWORD.equivalent(itemDelta.getParentPath())) { + addPasswordDelta(repoChanges, itemDelta, objectClassDefinition); continue; } normalizeDelta(itemDelta, objectClassDefinition); repoChanges.add(itemDelta); } + + return repoChanges; } + private void addPasswordDelta(Collection repoChanges, ItemDelta requestedPasswordDelta, RefinedObjectClassDefinition objectClassDefinition) throws SchemaException, EncryptionException { + if (!(requestedPasswordDelta.getPath().equivalent(SchemaConstants.PATH_PASSWORD_VALUE))) { + return; + } + CachingStategyType cachingStategy = getPasswordCachingStrategy(objectClassDefinition); + if (cachingStategy == null || cachingStategy == CachingStategyType.NONE) { + return; + } + PropertyDelta passwordValueDelta = (PropertyDelta)requestedPasswordDelta; + hashValues(passwordValueDelta.getValuesToAdd()); + hashValues(passwordValueDelta.getValuesToReplace()); + repoChanges.add(requestedPasswordDelta); + if (!(requestedPasswordDelta.getPath().equivalent(SchemaConstants.PATH_PASSWORD_VALUE))) { + return; + } + } + + + private void hashValues(Collection> pvals) throws SchemaException, EncryptionException { + if (pvals == null) { + return; + } + for (PrismPropertyValue pval: pvals) { + ProtectedStringType psVal = pval.getValue(); + if (psVal == null) { + return; + } + if (psVal.isHashed()) { + return; + } + protector.hash(psVal); + } + } + @SuppressWarnings("unchecked") public Collection updateShadow(ProvisioningContext ctx, PrismObject resourceShadow, Collection aprioriDeltas, OperationResult result) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ExpressionEvaluationException { @@ -1586,7 +1646,6 @@ public PrismObject updateShadow(ProvisioningContext ctx, PrismObject normalizedRealValue = matchingRule.normalize(pval.getValue()); } attrAddDelta.addValueToAdd(new PrismPropertyValue(normalizedRealValue)); - LOGGER.trace("CURRENT ATTR:\n{}\nATTR DELTA:\n{}", currentResourceAttrProperty.debugDump(1), attrAddDelta.debugDump(1)); } shadowDelta.addModification(attrAddDelta); } else { @@ -1599,7 +1658,6 @@ public PrismObject updateShadow(ProvisioningContext ctx, PrismObject currentResourceNormalizedRealValue = matchingRule.normalize(currentResourceRealValue); } if (!currentResourceNormalizedRealValue.equals(oldRepoAttributeProperty.getRealValue())) { - LOGGER.trace("CURRENT ATTR:\n{}\ncurrentResourceNormalizedRealValue: {}", currentResourceAttrProperty.debugDump(1), currentResourceNormalizedRealValue); shadowDelta.addModificationReplaceProperty(currentResourceAttrProperty.getPath(), currentResourceNormalizedRealValue); } } else { @@ -1611,10 +1669,10 @@ public PrismObject updateShadow(ProvisioningContext ctx, PrismObject } } PropertyDelta attrDiff = oldRepoAttributeProperty.diff(normalizedCurrentResourceAttrProperty); - LOGGER.trace("DIFF:\n{}\n-\n{}\n=:\n{}", - oldRepoAttributeProperty==null?null:oldRepoAttributeProperty.debugDump(1), - normalizedCurrentResourceAttrProperty==null?null:normalizedCurrentResourceAttrProperty.debugDump(1), - attrDiff==null?null:attrDiff.debugDump(1)); +// LOGGER.trace("DIFF:\n{}\n-\n{}\n=:\n{}", +// oldRepoAttributeProperty==null?null:oldRepoAttributeProperty.debugDump(1), +// normalizedCurrentResourceAttrProperty==null?null:normalizedCurrentResourceAttrProperty.debugDump(1), +// attrDiff==null?null:attrDiff.debugDump(1)); if (attrDiff != null && !attrDiff.isEmpty()) { attrDiff.setParentPath(new ItemPath(ShadowType.F_ATTRIBUTES)); shadowDelta.addModification(attrDiff); @@ -1675,7 +1733,7 @@ public PrismObject updateShadow(ProvisioningContext ctx, PrismObject } else { throw new ConfigurationException("Unknown caching strategy "+cachingStrategy); } - + if (!shadowDelta.isEmpty()) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Updating repo shadow {} with delta:\n{}", oldRepoShadow, shadowDelta.debugDump(1)); @@ -1697,6 +1755,7 @@ public PrismObject updateShadow(ProvisioningContext ctx, PrismObject return oldRepoShadow; } } + private void compareUpdateProperty(ObjectDelta shadowDelta, ItemPath itemPath, PrismObject currentResourceShadow, PrismObject oldRepoShadow) { diff --git a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractBasicDummyTest.java b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractBasicDummyTest.java index 23c20be4876..7a039dc3835 100644 --- a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractBasicDummyTest.java +++ b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractBasicDummyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2017 Evolveum + * Copyright (c) 2010-2018 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,6 @@ package com.evolveum.midpoint.provisioning.impl.dummy; import static com.evolveum.midpoint.test.IntegrationTestTools.assertProvisioningAccountShadow; -import static com.evolveum.midpoint.test.IntegrationTestTools.display; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertNotNull; @@ -111,6 +110,8 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.CapabilitiesType; import com.evolveum.midpoint.xml.ns._public.common.common_3.CapabilityCollectionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnectorType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.CredentialsType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PasswordType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; @@ -121,6 +122,7 @@ import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ReadCapabilityType; import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ScriptCapabilityType; import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.TestConnectionCapabilityType; +import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; /** * The test of Provisioning service on the API level. The test is using dummy @@ -160,7 +162,7 @@ public static void assertCleanShutdown() throws Exception { @Test public void test000Integrity() throws Exception { final String TEST_NAME = "test000Integrity"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); display("Dummy resource instance", dummyResource.toString()); @@ -194,7 +196,7 @@ public void test000Integrity() throws Exception { @Test public void test010ListConnectors() throws Exception { final String TEST_NAME = "test010ListConnectors"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN OperationResult result = new OperationResult(AbstractBasicDummyTest.class.getName() + "." + TEST_NAME); @@ -245,7 +247,7 @@ public void test010ListConnectors() throws Exception { @Test public void test012ConnectorRediscovery() { final String TEST_NAME = "test012ConnectorRediscovery"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN OperationResult result = new OperationResult(AbstractBasicDummyTest.class.getName() + "." + TEST_NAME); @@ -253,9 +255,7 @@ public void test012ConnectorRediscovery() { Set discoverLocalConnectors = connectorManager.discoverLocalConnectors(result); // THEN - result.computeStatus(); - display("discoverLocalConnectors result", result); - TestUtil.assertSuccess("discoverLocalConnectors failed", result); + assertSuccess("discoverLocalConnectors failed", result); assertTrue("Rediscovered something", discoverLocalConnectors.isEmpty()); } @@ -266,7 +266,7 @@ public void test012ConnectorRediscovery() { @Test public void test015ListResourcesNoFetch() throws Exception { final String TEST_NAME = "test015ListResourcesNoFetch"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(AbstractBasicDummyTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); @@ -276,9 +276,7 @@ public void test015ListResourcesNoFetch() throws Exception { SearchResultList> resources = provisioningService.searchObjects(ResourceType.class, null, options, task, result); // THEN - result.computeStatus(); - display("searchObjects result", result); - TestUtil.assertSuccess(result); + assertSuccess(result); assertFalse("No resources found", resources.isEmpty()); for (PrismObject resource : resources) { @@ -311,7 +309,7 @@ public void test015ListResourcesNoFetch() throws Exception { @Test public void test020Connection() throws Exception { final String TEST_NAME = "test020Connection"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); @@ -387,7 +385,7 @@ public void test020Connection() throws Exception { @Test public void test021Configuration() throws Exception { final String TEST_NAME = "test021Configuration"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN OperationResult result = new OperationResult(AbstractBasicDummyTest.class.getName() + "." + TEST_NAME); @@ -442,7 +440,7 @@ protected void assertConfigurationProperty(PrismProperty confProp) { @Test public void test022ParsedSchema() throws Exception { final String TEST_NAME = "test022ParsedSchema"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN // THEN @@ -470,7 +468,7 @@ public void test022ParsedSchema() throws Exception { @Test public void test023RefinedSchema() throws Exception { final String TEST_NAME = "test023RefinedSchema"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN // WHEN @@ -556,7 +554,7 @@ public void test023RefinedSchema() throws Exception { @Test public void test024ParsedSchemaAgain() throws Exception { final String TEST_NAME = "test024ParsedSchemaAgain"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN // THEN @@ -576,7 +574,7 @@ public void test024ParsedSchemaAgain() throws Exception { @Test public void test028Capabilities() throws Exception { final String TEST_NAME = "test028Capabilities"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN OperationResult result = new OperationResult(AbstractBasicDummyTest.class.getName() @@ -658,7 +656,7 @@ protected void assertNativeCredentialsCapability(CredentialsCapabilityType capCr @Test public void test029CapabilitiesRepo() throws Exception { final String TEST_NAME = "test029CapabilitiesRepo"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN OperationResult result = new OperationResult(AbstractBasicDummyTest.class.getName() @@ -856,7 +854,7 @@ public void test031ResourceAndConnectorCachingForceFresh() throws Exception { @Test public void test040ApplyDefinitionShadow() throws Exception { final String TEST_NAME = "test040ApplyDefinitionShadow"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = createTask(TEST_NAME); @@ -882,7 +880,7 @@ public void test040ApplyDefinitionShadow() throws Exception { @Test public void test041ApplyDefinitionAddShadowDelta() throws Exception { final String TEST_NAME = "test041ApplyDefinitionAddShadowDelta"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = createTask(TEST_NAME); @@ -909,7 +907,7 @@ public void test041ApplyDefinitionAddShadowDelta() throws Exception { @Test public void test042ApplyDefinitionResource() throws Exception { final String TEST_NAME = "test042ApplyDefinitionResource"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = createTask(TEST_NAME); @@ -939,7 +937,7 @@ public void test042ApplyDefinitionResource() throws Exception { @Test public void test043ApplyDefinitionAddResourceDelta() throws Exception { final String TEST_NAME = "test043ApplyDefinitionAddResourceDelta"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = createTask(TEST_NAME); @@ -996,7 +994,7 @@ public void test050SelfTest() throws Exception { @Test public void test080TestAttributesToReturn() throws Exception { final String TEST_NAME = "test080TestAttributesToReturn"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(); @@ -1024,7 +1022,7 @@ public void test080TestAttributesToReturn() throws Exception { @Test public void test090ConnectorStatsAfterSomeUse() throws Exception { final String TEST_NAME = "test090ConnectorStatsAfterSomeUse"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); @@ -1137,7 +1135,7 @@ public void test100AddAccountWill() throws Exception { assertEquals("Username is wrong", transformNameFromResource(ACCOUNT_WILL_USERNAME), dummyAccount.getName()); assertEquals("Fullname is wrong", "Will Turner", dummyAccount.getAttributeValue("fullname")); assertTrue("The account is not enabled", dummyAccount.isEnabled()); - assertEquals("Wrong password", "3lizab3th", dummyAccount.getPassword()); + assertEquals("Wrong password", ACCOUNT_WILL_PASSWORD, dummyAccount.getPassword()); // Check if the shadow is still in the repo (e.g. that the consistency or sync haven't removed it) PrismObject shadowFromRepo = repositoryService.getObject(ShadowType.class, @@ -1151,7 +1149,7 @@ public void test100AddAccountWill() throws Exception { // MID-3860 assertShadowPasswordMetadata(shadowFromRepo, true, start, end, null, null); - assertNoShadowPassword(shadowFromRepo); + assertRepoShadowCredentials(shadowFromRepo, ACCOUNT_WILL_PASSWORD); lastPasswordModifyStart = start; lastPasswordModifyEnd = end; @@ -1193,7 +1191,7 @@ protected void checkRepoAccountShadowWill(PrismObject accountRepo, X @Test public void test102GetAccount() throws Exception { final String TEST_NAME = "test102GetAccount"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN OperationResult result = new OperationResult(AbstractBasicDummyTest.class.getName() + "." + TEST_NAME); @@ -1234,7 +1232,7 @@ public void test102GetAccount() throws Exception { @Test public void test103GetAccountNoFetch() throws Exception { final String TEST_NAME="test103GetAccountNoFetch"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN OperationResult result = new OperationResult(AbstractBasicDummyTest.class.getName() + "."+TEST_NAME); @@ -1252,9 +1250,8 @@ public void test103GetAccountNoFetch() throws Exception { // THEN XMLGregorianCalendar endTs = clock.currentTimeXMLGregorianCalendar(); - result.computeStatus(); display("getObject result", result); - TestUtil.assertSuccess(result); + assertSuccess(result); assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 0); display("Retrieved account shadow", shadow); @@ -1273,7 +1270,7 @@ public void test103GetAccountNoFetch() throws Exception { @Test public void test105ApplyDefinitionModifyDelta() throws Exception { final String TEST_NAME = "test105ApplyDefinitionModifyDelta"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = createTask(TEST_NAME); @@ -1288,12 +1285,9 @@ public void test105ApplyDefinitionModifyDelta() throws Exception { provisioningService.applyDefinition(accountDelta, task, result); // THEN - result.computeStatus(); - display("applyDefinition result", result); - TestUtil.assertSuccess(result); + assertSuccess(result); accountDelta.checkConsistence(true, true, true); - TestUtil.assertSuccess("applyDefinition(modify delta) result", result); assertSteadyResource(); } @@ -1306,7 +1300,7 @@ public void test105ApplyDefinitionModifyDelta() throws Exception { @Test public void test106GetModifiedAccount() throws Exception { final String TEST_NAME = "test106GetModifiedAccount"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN OperationResult result = new OperationResult(AbstractBasicDummyTest.class.getName() + "." + TEST_NAME); rememberCounter(InternalCounters.SHADOW_FETCH_OPERATION_COUNT); @@ -1319,14 +1313,12 @@ public void test106GetModifiedAccount() throws Exception { XMLGregorianCalendar startTs = clock.currentTimeXMLGregorianCalendar(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); PrismObject shadow = provisioningService.getObject(ShadowType.class, ACCOUNT_WILL_OID, null, null, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - display("getObject result", result); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 1); XMLGregorianCalendar endTs = clock.currentTimeXMLGregorianCalendar(); @@ -1350,6 +1342,7 @@ public void test106GetModifiedAccount() throws Exception { assertRepoShadowCachedAttributeValue(shadowRepo, DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_WEAPON_NAME, "sword", "love"); assertRepoShadowCachedAttributeValue(shadowRepo, DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_LOOT_NAME, 42); assertRepoShadowCacheActivation(shadowRepo, ActivationStatusType.DISABLED); + assertRepoShadowCredentials(shadowRepo, ACCOUNT_WILL_PASSWORD); checkConsistency(shadow); @@ -1361,7 +1354,7 @@ public void test106GetModifiedAccount() throws Exception { @Test public void test999Shutdown() throws Exception { final String TEST_NAME = "test999Shutdown"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // WHEN provisioningService.shutdown(); @@ -1446,5 +1439,27 @@ protected void assertRepoShadowCacheActivation(PrismObject shadowRep ActivationStatusType administrativeStatus = activationType.getAdministrativeStatus(); assertNull("Unexpected activation administrativeStatus in repo shadow "+shadowRepo+": "+administrativeStatus, administrativeStatus); } + + protected void assertRepoShadowCredentials(PrismObject shadowRepo, String expectedPassword) throws SchemaException, EncryptionException { + CredentialsType credentials = shadowRepo.asObjectable().getCredentials(); + if (expectedPassword == null && credentials == null) { + return; + } + assertNotNull("Missing credentendials in repo shadow "+shadowRepo, credentials); + PasswordType passwordType = credentials.getPassword(); + if (expectedPassword == null && passwordType == null) { + return; + } + assertNotNull("Missing password credential in repo shadow "+shadowRepo, passwordType); + // TODO: assert password meta-data + assertRepoShadowPasswordValue(shadowRepo, passwordType, expectedPassword); + } + + protected void assertRepoShadowPasswordValue(PrismObject shadowRepo, PasswordType passwordType, + String expectedPassword) throws SchemaException, EncryptionException { + ProtectedStringType passwordValue = passwordType.getValue(); + assertNull("Unexpected password value in repo shadow "+shadowRepo, passwordValue); + } + } diff --git a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractDummyTest.java b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractDummyTest.java index 2fc1b20e4fb..677fa18f142 100644 --- a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractDummyTest.java +++ b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractDummyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2017 Evolveum + * Copyright (c) 2010-2018 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ */ package com.evolveum.midpoint.provisioning.impl.dummy; -import static com.evolveum.midpoint.test.IntegrationTestTools.display; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertNull; @@ -104,6 +103,8 @@ public abstract class AbstractDummyTest extends AbstractProvisioningIntegrationT protected static final File ACCOUNT_WILL_FILE = new File(TEST_DIR, "account-will.xml"); protected static final String ACCOUNT_WILL_OID = "c0c010c0-d34d-b44f-f11d-33322212dddd"; protected static final String ACCOUNT_WILL_USERNAME = "Will"; + protected static final String ACCOUNT_WILL_PASSWORD = "3lizab3th"; + protected static final String ACCOUNT_WILL_PASSWORD_NEW = "3lizab3th123"; protected static final XMLGregorianCalendar ACCOUNT_WILL_ENABLE_TIMESTAMP = XmlTypeConverter.createXMLGregorianCalendar(2013, 5, 30, 12, 30, 42); protected static final File ACCOUNT_ELIZABETH_FILE = new File(TEST_DIR, "account-elizabeth.xml"); @@ -119,6 +120,7 @@ public abstract class AbstractDummyTest extends AbstractProvisioningIntegrationT protected static final File ACCOUNT_MORGAN_FILE = new File(TEST_DIR, "account-morgan.xml"); protected static final String ACCOUNT_MORGAN_OID = "c0c010c0-d34d-b44f-f11d-444400008888"; protected static final String ACCOUNT_MORGAN_NAME = "morgan"; + protected static final String ACCOUNT_MORGAN_PASSWORD = "sh1verM3T1mb3rs"; protected static final File ACCOUNT_LECHUCK_FILE = new File(TEST_DIR, "account-lechuck.xml"); protected static final String ACCOUNT_LECHUCK_OID = "c0c010c0-d34d-b44f-f11d-444400009aa9"; diff --git a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummy.java b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummy.java index cc07c092c89..578aaf321d0 100644 --- a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummy.java +++ b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummy.java @@ -225,7 +225,7 @@ public void test101AddAccountWithoutName() throws Exception { assertNotNull("No dummy account", dummyAccount); assertEquals("Fullname is wrong", "Captain Morgan", dummyAccount.getAttributeValue("fullname")); assertTrue("The account is not enabled", dummyAccount.isEnabled()); - assertEquals("Wrong password", "sh1verM3T1mb3rs", dummyAccount.getPassword()); + assertEquals("Wrong password", ACCOUNT_MORGAN_PASSWORD, dummyAccount.getPassword()); // Check if the shadow is in the repo PrismObject shadowFromRepo = repositoryService.getObject(ShadowType.class, @@ -234,6 +234,8 @@ public void test101AddAccountWithoutName() throws Exception { display("Repository shadow", shadowFromRepo.debugDump()); checkRepoAccountShadow(shadowFromRepo); + // MID-4397 + assertRepoShadowCredentials(shadowFromRepo, ACCOUNT_MORGAN_PASSWORD); checkConsistency(account.asPrismObject()); @@ -428,9 +430,7 @@ public void test109ModifiedAccountCleanup() throws Exception { PrismObject shadow = provisioningService.getObject(ShadowType.class, ACCOUNT_WILL_OID, null, null, result); // THEN - result.computeStatus(); - display("getObject result", result); - TestUtil.assertSuccess(result); + assertSuccess(result); assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 1); XMLGregorianCalendar endTs = clock.currentTimeXMLGregorianCalendar(); @@ -518,9 +518,7 @@ public boolean handle(PrismObject object, OperationResult parentResu // THEN XMLGregorianCalendar endTs = clock.currentTimeXMLGregorianCalendar(); - result.computeStatus(); - display("searchObjectsIterative result", result); - TestUtil.assertSuccess(result); + assertSuccess(result); assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 1); assertEquals(4, foundObjects.size()); @@ -586,10 +584,7 @@ public void test111SeachIterativeNoFetch() throws Exception { final XMLGregorianCalendar startTs = clock.currentTimeXMLGregorianCalendar(); final List> foundObjects = new ArrayList>(); - ResultHandler handler = new ResultHandler() { - - @Override - public boolean handle(PrismObject shadow, OperationResult parentResult) { + ResultHandler handler = (shadow, parentResult) -> { foundObjects.add(shadow); assertTrue(shadow.canRepresent(ShadowType.class)); @@ -606,8 +601,8 @@ public boolean handle(PrismObject shadow, OperationResult parentResu } return true; - } - }; + }; + Collection> options = SelectorOptions.createCollection(GetOperationOptions.createNoFetch()); @@ -617,9 +612,7 @@ public boolean handle(PrismObject shadow, OperationResult parentResu provisioningService.searchObjectsIterative(ShadowType.class, query, options, handler, null, result); // THEN - result.computeStatus(); - display("searchObjectsIterative result", result); - TestUtil.assertSuccess(result); + assertSuccess(result); assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 0); display("Found shadows", foundObjects); @@ -644,19 +637,16 @@ public void test112SeachIterativeKindIntent() throws Exception { display("query", query); final List> foundObjects = new ArrayList>(); - ResultHandler handler = new ResultHandler() { - - @Override - public boolean handle(PrismObject object, OperationResult parentResult) { - foundObjects.add(object); - return true; - } - }; rememberCounter(InternalCounters.SHADOW_FETCH_OPERATION_COUNT); // WHEN - provisioningService.searchObjectsIterative(ShadowType.class, query, null, handler, null, result); + provisioningService.searchObjectsIterative(ShadowType.class, query, null, + (object, parentResult) -> { + foundObjects.add(object); + return true; + }, + null, result); // THEN result.computeStatus(); @@ -690,7 +680,7 @@ private int countProtected(List> shadows) @Test public void test113SearchAllShadowsInRepository() throws Exception { - TestUtil.displayTestTitle("test113SearchAllShadowsInRepository"); + displayTestTitle("test113SearchAllShadowsInRepository"); // GIVEN OperationResult result = new OperationResult(TestDummy.class.getName() + ".test113SearchAllShadowsInRepository"); @@ -702,9 +692,7 @@ public void test113SearchAllShadowsInRepository() throws Exception { query, null, result); // THEN - result.computeStatus(); - display("searchObjects result", result); - TestUtil.assertSuccess(result); + assertSuccess(result); display("Found " + allShadows.size() + " shadows"); display("Found shadows", allShadows); @@ -748,7 +736,7 @@ public void test114SearchAllAccounts() throws Exception { @Test public void test115CountAllAccounts() throws Exception { - TestUtil.displayTestTitle("test115CountAllAccounts"); + displayTestTitle("test115CountAllAccounts"); // GIVEN OperationResult result = new OperationResult(TestDummy.class.getName() + ".test115countAllShadows"); @@ -798,7 +786,7 @@ public void test116SearchNullQueryResource() throws Exception { @Test public void test117CountNullQueryResource() throws Exception { - TestUtil.displayTestTitle("test117CountNullQueryResource"); + displayTestTitle("test117CountNullQueryResource"); // GIVEN OperationResult result = new OperationResult(TestDummy.class.getName() + ".test117CountNullQueryResource"); @@ -916,17 +904,13 @@ public void test119SearchAllAccountsMaxStaleness() throws Exception { assertSteadyResource(); } - - @Test - public void test123ModifyObjectReplace() throws Exception { - final String TEST_NAME = "test123ModifyObjectReplace"; + public void test120ModifyObjectReplace() throws Exception { + final String TEST_NAME = "test120ModifyObjectReplace"; displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDummy.class.getName() - + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); - syncServiceMock.reset(); ObjectDelta delta = ObjectDelta.createModificationReplaceProperty(ShadowType.class, @@ -935,13 +919,13 @@ public void test123ModifyObjectReplace() throws Exception { delta.checkConsistence(); // WHEN + displayWhen(TEST_NAME); provisioningService.modifyObject(ShadowType.class, delta.getOid(), delta.getModifications(), new OperationProvisioningScriptsType(), null, task, result); // THEN - result.computeStatus(); - display("modifyObject result", result); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); delta.checkConsistence(); assertDummyAccountAttributeValues(transformNameFromResource(ACCOUNT_WILL_USERNAME), willIcfUid, @@ -953,13 +937,12 @@ public void test123ModifyObjectReplace() throws Exception { } @Test - public void test124ModifyObjectAddPirate() throws Exception { - TestUtil.displayTestTitle("test124ModifyObjectAddPirate"); + public void test121ModifyObjectAddPirate() throws Exception { + final String TEST_NAME = "test121ModifyObjectAddPirate"; + displayTestTitle(TEST_NAME); - Task syncTask = taskManager.createTaskInstance(TestDummy.class.getName() - + ".test124ModifyObjectAddPirate"); - OperationResult result = new OperationResult(TestOpenDj.class.getName() - + ".test124ModifyObjectAddPirate"); + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); syncServiceMock.reset(); ObjectDelta delta = ObjectDelta.createModificationAddProperty(ShadowType.class, @@ -970,13 +953,13 @@ public void test124ModifyObjectAddPirate() throws Exception { delta.checkConsistence(); // WHEN + displayWhen(TEST_NAME); provisioningService.modifyObject(ShadowType.class, delta.getOid(), delta.getModifications(), - new OperationProvisioningScriptsType(), null, syncTask, result); + new OperationProvisioningScriptsType(), null, task, result); // THEN - result.computeStatus(); - display("modifyObject result", result); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); delta.checkConsistence(); // check if attribute was changed @@ -989,13 +972,12 @@ public void test124ModifyObjectAddPirate() throws Exception { } @Test - public void test125ModifyObjectAddCaptain() throws Exception { - TestUtil.displayTestTitle("test125ModifyObjectAddCaptain"); + public void test122ModifyObjectAddCaptain() throws Exception { + final String TEST_NAME = "test122ModifyObjectAddCaptain"; + displayTestTitle(TEST_NAME); - Task syncTask = taskManager.createTaskInstance(TestDummy.class.getName() - + ".test125ModifyObjectAddCaptain"); - OperationResult result = new OperationResult(TestOpenDj.class.getName() - + ".test125ModifyObjectAddCaptain"); + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); syncServiceMock.reset(); ObjectDelta delta = ObjectDelta.createModificationAddProperty(ShadowType.class, @@ -1006,13 +988,13 @@ public void test125ModifyObjectAddCaptain() throws Exception { delta.checkConsistence(); // WHEN + displayWhen(TEST_NAME); provisioningService.modifyObject(ShadowType.class, delta.getOid(), delta.getModifications(), - new OperationProvisioningScriptsType(), null, syncTask, result); + new OperationProvisioningScriptsType(), null, task, result); // THEN - result.computeStatus(); - display("modifyObject result", result); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); delta.checkConsistence(); // check if attribute was changed @@ -1025,13 +1007,12 @@ public void test125ModifyObjectAddCaptain() throws Exception { } @Test - public void test126ModifyObjectDeletePirate() throws Exception { - TestUtil.displayTestTitle("test126ModifyObjectDeletePirate"); + public void test123ModifyObjectDeletePirate() throws Exception { + final String TEST_NAME = "test123ModifyObjectDeletePirate"; + displayTestTitle(TEST_NAME); - Task syncTask = taskManager.createTaskInstance(TestDummy.class.getName() - + ".test126ModifyObjectDeletePirate"); - OperationResult result = new OperationResult(TestOpenDj.class.getName() - + ".test126ModifyObjectDeletePirate"); + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); syncServiceMock.reset(); ObjectDelta delta = ObjectDelta.createModificationDeleteProperty(ShadowType.class, @@ -1040,13 +1021,13 @@ public void test126ModifyObjectDeletePirate() throws Exception { delta.checkConsistence(); // WHEN + displayWhen(TEST_NAME); provisioningService.modifyObject(ShadowType.class, delta.getOid(), delta.getModifications(), - new OperationProvisioningScriptsType(), null, syncTask, result); + new OperationProvisioningScriptsType(), null, task, result); // THEN - result.computeStatus(); - display("modifyObject result", result); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); delta.checkConsistence(); // check if attribute was changed @@ -1063,12 +1044,11 @@ public void test126ModifyObjectDeletePirate() throws Exception { * unless the mechanism to compensate for this works properly. */ @Test - public void test127ModifyObjectAddCaptainAgain() throws Exception { - final String TEST_NAME = "test127ModifyObjectAddCaptainAgain"; + public void test124ModifyAccountWillAddCaptainAgain() throws Exception { + final String TEST_NAME = "test124ModifyAccountWillAddCaptainAgain"; displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDummy.class.getName() - + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); syncServiceMock.reset(); @@ -1078,13 +1058,13 @@ public void test127ModifyObjectAddCaptainAgain() throws Exception { delta.checkConsistence(); // WHEN + displayWhen(TEST_NAME); provisioningService.modifyObject(ShadowType.class, delta.getOid(), delta.getModifications(), new OperationProvisioningScriptsType(), null, task, result); // THEN - result.computeStatus(); - display("modifyObject result", result); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); delta.checkConsistence(); // check if attribute was changed @@ -1096,16 +1076,58 @@ public void test127ModifyObjectAddCaptainAgain() throws Exception { assertSteadyResource(); } + /** + * MID-4397 + */ + @Test + public void test125ModifyAccountWillPassword() throws Exception { + final String TEST_NAME = "test125ModifyAccountWillPassword"; + displayTestTitle(TEST_NAME); + + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + syncServiceMock.reset(); + + ObjectDelta delta = createAccountPaswordDelta(ACCOUNT_WILL_OID, ACCOUNT_WILL_PASSWORD_NEW); + display("ObjectDelta", delta); + + // WHEN + displayWhen(TEST_NAME); + provisioningService.modifyObject(ShadowType.class, delta.getOid(), delta.getModifications(), + new OperationProvisioningScriptsType(), null, task, result); + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); + + // Check if the account was created in the dummy resource + DummyAccount dummyAccount = getDummyAccountAssert(transformNameFromResource(ACCOUNT_WILL_USERNAME), willIcfUid); + assertNotNull("No dummy account", dummyAccount); + assertEquals("Wrong password", ACCOUNT_WILL_PASSWORD_NEW, dummyAccount.getPassword()); + + // Check if the shadow is in the repo + PrismObject repoShadow = repositoryService.getObject(ShadowType.class, + ACCOUNT_WILL_OID, null, result); + assertNotNull("Shadow was not created in the repository", repoShadow); + display("Repository shadow", repoShadow); + + checkRepoAccountShadow(repoShadow); + assertRepoShadowCredentials(repoShadow, ACCOUNT_WILL_PASSWORD_NEW); + + syncServiceMock.assertNotifySuccessOnly(); + + assertSteadyResource(); + } + /** * Set a null value to the (native) dummy attribute. The UCF layer should filter that out. */ @Test - public void test128NullAttributeValue() throws Exception { - final String TEST_NAME = "test128NullAttributeValue"; + public void test129NullAttributeValue() throws Exception { + final String TEST_NAME = "test129NullAttributeValue"; displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDummy.class.getName() - + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); syncServiceMock.reset(); @@ -1113,12 +1135,12 @@ public void test128NullAttributeValue() throws Exception { willDummyAccount.replaceAttributeValue(DUMMY_ACCOUNT_ATTRIBUTE_TITLE_NAME, null); // WHEN + displayWhen(TEST_NAME); PrismObject accountWill = provisioningService.getObject(ShadowType.class, ACCOUNT_WILL_OID, null, task, result); // THEN - result.computeStatus(); - display("getObject result", result); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); ResourceAttributeContainer attributesContainer = ShadowUtil.getAttributesContainer(accountWill); ResourceAttribute titleAttribute = attributesContainer.findAttribute(new QName(ResourceTypeUtil.getResourceNamespace(resourceType), DUMMY_ACCOUNT_ATTRIBUTE_TITLE_NAME)); diff --git a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummyCaching.java b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummyCaching.java index 2a30844c42d..6b66e17ea89 100644 --- a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummyCaching.java +++ b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummyCaching.java @@ -34,6 +34,7 @@ import com.evolveum.icf.dummy.resource.DummyAccount; import com.evolveum.midpoint.prism.Item; import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.crypto.EncryptionException; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.provisioning.impl.ProvisioningTestUtil; import com.evolveum.midpoint.schema.GetOperationOptions; @@ -51,10 +52,13 @@ 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.CachingMetadataType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.CredentialsStorageTypeType; import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PasswordType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; +import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; /** * Almost the same as TestDummy but this is using a caching configuration. @@ -296,6 +300,14 @@ protected void assertRepoShadowCacheActivation(PrismObject shadowRep assertEquals("Wrong activation administrativeStatus in repo shadow "+shadowRepo, expectedAdministrativeStatus, administrativeStatus); } + @Override + protected void assertRepoShadowPasswordValue(PrismObject shadowRepo, PasswordType passwordType, + String expectedPassword) throws SchemaException, EncryptionException { + ProtectedStringType protectedStringType = passwordType.getValue(); + assertNotNull("No password value in repo shadow "+shadowRepo, protectedStringType); + assertProtectedString("Wrong password value in repo shadow "+shadowRepo, expectedPassword, protectedStringType, CredentialsStorageTypeType.HASHING); + } + /** * We do not know what the timestamp should be. But some timestamp should be there. */ diff --git a/provisioning/provisioning-impl/src/test/resources/dummy/dummy-caching/resource-dummy.xml b/provisioning/provisioning-impl/src/test/resources/dummy/dummy-caching/resource-dummy.xml index 21da4387ab2..fed9bf551a5 100644 --- a/provisioning/provisioning-impl/src/test/resources/dummy/dummy-caching/resource-dummy.xml +++ b/provisioning/provisioning-impl/src/test/resources/dummy/dummy-caching/resource-dummy.xml @@ -1,6 +1,6 @@