diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java
index 622c6095055..4cb633faf66 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java
@@ -109,7 +109,7 @@ public PrismContainerDefinition getItemDefinition() {
return container.getDefinition();
}
- public ContainerStatus getStatus() {
+ public ContainerStatus getStatus() {
return status;
}
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemWrapper.java
index 1bae8a7512b..c47a7c734b6 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemWrapper.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemWrapper.java
@@ -27,6 +27,7 @@
import com.evolveum.midpoint.prism.Revivable;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.util.DebugDumpable;
+import org.jetbrains.annotations.Nullable;
/**
* @author lazyman
@@ -90,7 +91,8 @@ default boolean isEnforceRequiredFields() {
ContainerWrapper cw = getParent();
return cw == null || cw.isEnforceRequiredFields();
}
-
+
+ @Nullable
ContainerWrapper getParent();
boolean isShowEmpty();
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PropertyOrReferenceWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PropertyOrReferenceWrapper.java
index 115204a5736..92876dc5ff6 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PropertyOrReferenceWrapper.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PropertyOrReferenceWrapper.java
@@ -41,7 +41,7 @@ public abstract class PropertyOrReferenceWrapper values;
@@ -83,8 +83,9 @@ public ID getItemDefinition() {
}
@Override
+ @Nullable
public ContainerWrapper getParent() {
- return container.getContainer();
+ return container != null ? container.getContainer() : null;
}
public boolean isVisible() {
@@ -96,7 +97,10 @@ public boolean isVisible() {
if (getItemDefinition().isDeprecated() && isEmpty()) {
return false;
}
-
+
+ if (container == null) {
+ return false; // TODO: ok ?
+ }
switch (container.getObjectStatus()) {
case ADDING :
return canAddDefault() || canAddAndShowEmpty();
@@ -204,7 +208,15 @@ public boolean hasChanged() {
return false;
}
private boolean isMetadataContainer() {
- return getParent().getItemDefinition().getTypeName().equals(MetadataType.COMPLEX_TYPE);
+ ContainerWrapper parent = getParent();
+ if (parent == null) {
+ return false;
+ }
+ ItemDefinition> definition = parent.getItemDefinition();
+ if (definition == null) {
+ return false;
+ }
+ return definition.getTypeName().equals(MetadataType.COMPLEX_TYPE);
}
@Override
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PropertyWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PropertyWrapper.java
index 55e324fcdbb..4c4849ebac5 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PropertyWrapper.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PropertyWrapper.java
@@ -23,9 +23,6 @@
import com.evolveum.midpoint.util.DebugDumpable;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.PrettyPrinter;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.PasswordType;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
import org.jetbrains.annotations.Nullable;
import java.io.Serializable;
@@ -77,13 +74,13 @@ public ValueWrapper createAddedValue() {
ValueWrapper wrapper;
if (SchemaConstants.T_POLY_STRING_TYPE.equals(definition.getTypeName())) {
- wrapper = new ValueWrapper(this, new PrismPropertyValue(new PolyString("")),
- new PrismPropertyValue(new PolyString("")), ValueStatus.ADDED);
+ wrapper = new ValueWrapper(this, new PrismPropertyValue<>(new PolyString("")),
+ new PrismPropertyValue<>(new PolyString("")), ValueStatus.ADDED);
// } else if (isUser() && isThisPropertyActivationEnabled()) {
// wrapper = new ValueWrapper(this, new PrismPropertyValue(null),
// new PrismPropertyValue(null), ValueStatus.ADDED);
} else {
- wrapper = new ValueWrapper(this, new PrismPropertyValue(null), ValueStatus.ADDED);
+ wrapper = new ValueWrapper(this, new PrismPropertyValue<>(null), ValueStatus.ADDED);
}
return wrapper;
@@ -102,22 +99,22 @@ public ValueWrapper createAddedValue() {
// return UserType.class.isAssignableFrom(object.getCompileTimeClass());
// }
- private boolean isThisPropertyActivationEnabled() {
- if (!new ItemPath(UserType.F_ACTIVATION).equivalent(container.getPath())) {
- return false;
- }
-
- if (!ActivationType.F_ADMINISTRATIVE_STATUS.equals(item.getElementName())) {
- return false;
- }
-
-// if (container.getContainer().getObject() == null || ContainerStatus.MODIFYING.equals(container.getContainer().getObject().getStatus())) {
-// //when modifying then we don't want to create "true" value for c:activation/c:enabled, only during add
+// private boolean isThisPropertyActivationEnabled() {
+// if (!new ItemPath(UserType.F_ACTIVATION).equivalent(container.getPath())) {
// return false;
// }
-
- return true;
- }
+//
+// if (!ActivationType.F_ADMINISTRATIVE_STATUS.equals(item.getElementName())) {
+// return false;
+// }
+//
+//// if (container.getContainer().getObject() == null || ContainerStatus.MODIFYING.equals(container.getContainer().getObject().getStatus())) {
+//// //when modifying then we don't want to create "true" value for c:activation/c:enabled, only during add
+//// return false;
+//// }
+//
+// return true;
+// }
@Override
public String toString() {
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ReferenceWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ReferenceWrapper.java
index 93e5e9841df..44cee963aaf 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ReferenceWrapper.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ReferenceWrapper.java
@@ -22,7 +22,7 @@
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.PrettyPrinter;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
+import org.jetbrains.annotations.Nullable;
import java.io.Serializable;
import java.util.ArrayList;
@@ -38,11 +38,11 @@ public class ReferenceWrapper extends PropertyOrReferenceWrapper targetTypes;
- public ReferenceWrapper(ContainerValueWrapper container, PrismReference reference, boolean readonly, ValueStatus status) {
+ public ReferenceWrapper(@Nullable ContainerValueWrapper container, PrismReference reference, boolean readonly, ValueStatus status) {
super(container, reference, readonly, status, null);
}
- public ReferenceWrapper(ContainerValueWrapper container, PrismReference reference, boolean readonly, ValueStatus status, ItemPath path) {
+ public ReferenceWrapper(@Nullable ContainerValueWrapper container, PrismReference reference, boolean readonly, ValueStatus status, ItemPath path) {
super(container, reference, readonly, status, path);
}
@@ -54,7 +54,7 @@ public List getValues() {
}
private List createValues() {
- List values = new ArrayList();
+ List values = new ArrayList<>();
for (PrismReferenceValue prismValue : item.getValues()) {
@@ -84,8 +84,7 @@ public List getTargetTypes() {
@Override
public ValueWrapper createAddedValue() {
PrismReferenceValue prv = new PrismReferenceValue();
- ValueWrapper wrapper = new ValueWrapper(this, prv, ValueStatus.ADDED);
- return wrapper;
+ return new ValueWrapper(this, prv, ValueStatus.ADDED);
}
public ObjectFilter getFilter() {
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 extends QName> 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-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 {
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 extends ObjectType> 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-api/src/main/java/com/evolveum/midpoint/provisioning/api/ItemComparisonResult.java b/provisioning/provisioning-api/src/main/java/com/evolveum/midpoint/provisioning/api/ItemComparisonResult.java
new file mode 100644
index 00000000000..d498218157d
--- /dev/null
+++ b/provisioning/provisioning-api/src/main/java/com/evolveum/midpoint/provisioning/api/ItemComparisonResult.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.evolveum.midpoint.provisioning.api;
+
+/**
+ * @author semancik
+ *
+ */
+public enum ItemComparisonResult {
+
+ /**
+ * Value matches. Stored value is different.
+ */
+ MATCH,
+
+ /**
+ * Value mismatch. Stored value is the same.
+ */
+ MISMATCH,
+
+ /**
+ * Cannot compare. Comparison is not applicable.
+ */
+ NOT_APPLICABLE
+
+}
diff --git a/provisioning/provisioning-api/src/main/java/com/evolveum/midpoint/provisioning/api/ProvisioningService.java b/provisioning/provisioning-api/src/main/java/com/evolveum/midpoint/provisioning/api/ProvisioningService.java
index 7b64985d77f..186ddfa1d89 100644
--- a/provisioning/provisioning-api/src/main/java/com/evolveum/midpoint/provisioning/api/ProvisioningService.java
+++ b/provisioning/provisioning-api/src/main/java/com/evolveum/midpoint/provisioning/api/ProvisioningService.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.
@@ -24,8 +24,10 @@
import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition;
import com.evolveum.midpoint.prism.Objectable;
import com.evolveum.midpoint.prism.PrismObject;
+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.path.ItemPath;
import com.evolveum.midpoint.prism.query.ObjectPaging;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.schema.GetOperationOptions;
@@ -59,7 +61,7 @@
*
* Status: public
* Stability: STABLE, only compatible changes are expected
- * @version 3.4
+ * @version 3.7.1
* @author Radovan Semancik
*
*
@@ -73,13 +75,9 @@
* Supported object types:
*
* - Resource
- * - ResourceObjectShadow and all sub-types
+ * - Shadow
* - Connector
*
- * Supported extra data types:
- *
- * - Resource Objects (Resource Schema)
- *
*
*
* TODO: better documentation
@@ -502,6 +500,15 @@ ConstraintsCheckingResult checkConstraints(RefinedObjectClassDefinition shadowDe
void enterConstraintsCheckerCache();
void exitConstraintsCheckerCache();
+
+ /**
+ * Compare value on the resource with the provided value. This method is used to compare resource attributes
+ * or passwords, e.g. for the purposes of password policy.
+ * Note: comparison may be quite an expensive and heavy weight operation, e.g. it may try authenticating the user
+ * on the resource.
+ */
+ ItemComparisonResult compare(Class type, String oid, ItemPath path, T expectedValue, Task task, OperationResult result)
+ throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException, EncryptionException;
void shutdown();
diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ErrorHandlerFactory.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ErrorHandlerFactory.java
index 05cb5bff605..3fd0bb32013 100644
--- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ErrorHandlerFactory.java
+++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ErrorHandlerFactory.java
@@ -63,7 +63,7 @@ public class ErrorHandlerFactory {
- public ErrorHandler createErrorHandler(Exception ex){
+ public ErrorHandler createErrorHandler(Throwable ex) {
if (ex instanceof CommunicationException){
return communicationExceptionHandler;
}
@@ -85,6 +85,12 @@ public ErrorHandler createErrorHandler(Exception ex){
if (ex instanceof SecurityViolationException){
return securityViolationHandler;
}
+ if (ex instanceof RuntimeException) {
+ throw (RuntimeException)ex;
+ }
+ if (ex instanceof Error) {
+ throw (Error)ex;
+ }
throw new SystemException(ex != null ? ex.getClass().getName() +": "+ ex.getMessage() : "Unexpected error:", ex);
}
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..f3da89e65d0 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,10 @@
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.path.ItemPath;
import com.evolveum.midpoint.prism.query.NoneFilter;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.ObjectPaging;
@@ -46,6 +47,7 @@
import com.evolveum.midpoint.provisioning.api.ConstraintViolationConfirmer;
import com.evolveum.midpoint.provisioning.api.ConstraintsCheckingResult;
import com.evolveum.midpoint.provisioning.api.GenericConnectorException;
+import com.evolveum.midpoint.provisioning.api.ItemComparisonResult;
import com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions;
import com.evolveum.midpoint.provisioning.api.ProvisioningService;
import com.evolveum.midpoint.provisioning.impl.ShadowCacheFactory.Mode;
@@ -68,7 +70,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 +83,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 +91,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 +246,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 +321,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 +375,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 +649,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();
@@ -758,9 +714,9 @@ public void deleteObject(Class type, String oid, Provi
} catch (ExpressionEvaluationException e) {
ProvisioningUtil.recordFatalError(LOGGER, result, "Couldn't delete object: expression errror: " + e.getMessage(), e);
throw e;
- } catch (RuntimeException e){
+ } catch (RuntimeException | Error e) {
ProvisioningUtil.recordFatalError(LOGGER, result, "Couldn't delete object: " + e.getMessage(), e);
- throw new SystemException(e);
+ throw e;
}
} else if (object.canRepresent(ResourceType.class)) {
@@ -923,6 +879,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 +893,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();
@@ -1344,4 +1304,42 @@ private PrismObject getRepoObject(Class type, Strin
}
}
+ @Override
+ public ItemComparisonResult compare(Class type, String oid, ItemPath path,
+ T expectedValue, Task task, OperationResult parentResult)
+ throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException, EncryptionException {
+ Validate.notNull(oid, "Oid of object to get must not be null.");
+ Validate.notNull(parentResult, "Operation result must not be null.");
+
+ if (!ShadowType.class.isAssignableFrom(type)) {
+ throw new UnsupportedOperationException("Only shadow compare is supported");
+ }
+
+ // Result type for this operation
+ OperationResult result = parentResult.createMinorSubresult(ProvisioningService.class.getName() + ".compare");
+ result.addParam(OperationResult.PARAM_OID, oid);
+ result.addParam(OperationResult.PARAM_TYPE, type);
+
+ ItemComparisonResult comparisonResult;
+ try {
+
+ PrismObject repositoryObject = getRepoObject(type, oid, null, result);
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("Retrieved repository object:\n{}", repositoryObject.debugDump());
+ }
+
+ comparisonResult = getShadowCache(Mode.STANDARD).compare((PrismObject) (repositoryObject), path, expectedValue, task, result);
+
+ } catch (ObjectNotFoundException | CommunicationException | SchemaException | ConfigurationException | SecurityViolationException | ExpressionEvaluationException | EncryptionException | RuntimeException | Error e) {
+ ProvisioningUtil.recordFatalError(LOGGER, result, null, e);
+ throw e;
+ }
+
+
+ result.computeStatus();
+ result.cleanupResult();
+
+ return comparisonResult;
+ }
+
}
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..34d099e78b3 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,8 @@
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.crypto.Protector;
import com.evolveum.midpoint.prism.delta.*;
import com.evolveum.midpoint.prism.match.MatchingRuleRegistry;
import com.evolveum.midpoint.prism.path.IdItemPathSegment;
@@ -67,6 +69,7 @@
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ReadCapabilityType;
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;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
@@ -106,41 +109,19 @@ public abstract class ShadowCache {
@Qualifier("cacheRepositoryService")
private RepositoryService repositoryService;
- @Autowired(required = true)
- private ErrorHandlerFactory errorHandlerFactory;
-
- @Autowired(required = true)
- private ResourceManager resourceManager;
-
- @Autowired(required = true)
- private Clock clock;
-
- @Autowired(required = true)
- private PrismContext prismContext;
-
- @Autowired(required = true)
- private ResourceObjectConverter resouceObjectConverter;
-
- @Autowired(required = true)
- private MatchingRuleRegistry matchingRuleRegistry;
-
- @Autowired(required = true)
- protected ShadowManager shadowManager;
-
- @Autowired(required = true)
- private ChangeNotificationDispatcher operationListener;
-
- @Autowired(required = true)
- private AccessChecker accessChecker;
-
- @Autowired(required = true)
- private TaskManager taskManager;
-
- @Autowired(required = true)
- private ChangeNotificationDispatcher changeNotificationDispatcher;
-
- @Autowired(required = true)
- private ProvisioningContextFactory ctxFactory;
+ @Autowired private ErrorHandlerFactory errorHandlerFactory;
+ @Autowired private ResourceManager resourceManager;
+ @Autowired private Clock clock;
+ @Autowired private PrismContext prismContext;
+ @Autowired private ResourceObjectConverter resouceObjectConverter;
+ @Autowired private MatchingRuleRegistry matchingRuleRegistry;
+ @Autowired protected ShadowManager shadowManager;
+ @Autowired private ChangeNotificationDispatcher operationListener;
+ @Autowired private AccessChecker accessChecker;
+ @Autowired private TaskManager taskManager;
+ @Autowired private ChangeNotificationDispatcher changeNotificationDispatcher;
+ @Autowired private ProvisioningContextFactory ctxFactory;
+ @Autowired private Protector protector;
private static final Trace LOGGER = TraceManager.getTrace(ShadowCache.class);
@@ -167,7 +148,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 +344,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 +532,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 +749,7 @@ public abstract void afterModifyOnResource(
ProvisioningOperationState>>> opState,
OperationResult parentResult)
throws SchemaException, ObjectNotFoundException, ConfigurationException,
- CommunicationException, ExpressionEvaluationException;
+ CommunicationException, ExpressionEvaluationException, EncryptionException;
public abstract Collection extends ItemDelta> beforeModifyOnResource(PrismObject shadow,
ProvisioningOperationOptions options, Collection extends ItemDelta> modifications)
@@ -778,7 +759,7 @@ public String modifyShadow(PrismObject repoShadow,
Collection extends ItemDelta> 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 +1088,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 +1569,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 +1784,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 +1809,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 +1996,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 +2090,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 +2270,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 +2499,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 +2930,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?
}
@@ -2961,4 +2942,63 @@ private boolean isPropagationTriggered(PendingOperationType pendingOperation, Du
return XmlTypeConverter.isAfterInterval(requestTimestamp, operationGroupingInterval, now);
}
+ public ItemComparisonResult compare(PrismObject repositoryShadow, ItemPath path, T expectedValue, Task task, OperationResult parentResult)
+ throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException, EncryptionException {
+
+ if (!path.equals(SchemaConstants.PATH_PASSWORD_VALUE)) {
+ throw new UnsupportedOperationException("Only password comparison is supported");
+ }
+
+ ProvisioningContext ctx = ctxFactory.create(repositoryShadow, task, parentResult);
+ try {
+ ctx.assertDefinition();
+ applyAttributesDefinition(ctx, repositoryShadow);
+ } catch (ObjectNotFoundException | SchemaException | CommunicationException
+ | ConfigurationException | ExpressionEvaluationException e) {
+ throw e;
+ }
+
+ ResourceType resource = ctx.getResource();
+
+ PasswordCompareStrategyType passwordCompareStrategy = getPasswordCompareStrategy(ctx.getObjectClassDefinition());
+ if (passwordCompareStrategy == PasswordCompareStrategyType.ERROR) {
+ throw new UnsupportedOperationException("Password comparison is not supported on "+resource);
+ }
+
+ PrismProperty repoProperty = repositoryShadow.findProperty(path);
+ if (repoProperty == null) {
+ if (passwordCompareStrategy == PasswordCompareStrategyType.CACHED) {
+ if (expectedValue == null) {
+ return ItemComparisonResult.MATCH;
+ } else {
+ return ItemComparisonResult.MISMATCH;
+ }
+ } else {
+ // AUTO
+ return ItemComparisonResult.NOT_APPLICABLE;
+ }
+ }
+
+ ProtectedStringType repoProtectedString = (ProtectedStringType) repoProperty.getRealValue();
+ ProtectedStringType expectedProtectedString = new ProtectedStringType();
+ if (expectedValue instanceof ProtectedStringType) {
+ expectedProtectedString = (ProtectedStringType)expectedValue;
+ } else {
+ expectedProtectedString = new ProtectedStringType();
+ expectedProtectedString.setClearValue((String) expectedValue);
+ }
+ if (protector.compare(repoProtectedString, expectedProtectedString)) {
+ return ItemComparisonResult.MATCH;
+ } else {
+ return ItemComparisonResult.MISMATCH;
+ }
+ }
+
+ private PasswordCompareStrategyType getPasswordCompareStrategy(RefinedObjectClassDefinition objectClassDefinition) {
+ ResourcePasswordDefinitionType passwordDefinition = objectClassDefinition.getPasswordDefinition();
+ if (passwordDefinition == null) {
+ return null;
+ }
+ return passwordDefinition.getCompareStrategy();
+ }
}
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 extends ItemDelta> 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 extends ItemDelta> 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 extends ItemDelta> modifications,
OperationResult parentResult)
- throws SchemaException, ObjectNotFoundException, ConfigurationException, CommunicationException, ExpressionEvaluationException {
+ throws SchemaException, ObjectNotFoundException, ConfigurationException, CommunicationException, ExpressionEvaluationException, EncryptionException {
Collection extends ItemDelta> 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 extends ItemDelta> extractRepoShadowChanges(ProvisioningContext ctx, PrismObject shadow, Collection extends ItemDelta> 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 extends ItemDelta> 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 extends ItemDelta> 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