Skip to content

Commit

Permalink
Shadow lifecycle - work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Mar 16, 2017
1 parent dba244b commit a0d945d
Show file tree
Hide file tree
Showing 19 changed files with 541 additions and 158 deletions.
Expand Up @@ -24,15 +24,17 @@
*/
public interface ProtectedData<T> {

abstract byte[] getClearBytes();
byte[] getClearBytes();

abstract void setClearBytes(byte[] bytes);
void setClearBytes(byte[] bytes);

abstract T getClearValue();
T getClearValue();

abstract void setClearValue(T data);
void setClearValue(T data);

abstract void destroyCleartext();
void destroyCleartext();

boolean canGetCleartext();

EncryptedDataType getEncryptedDataType();

Expand Down
Expand Up @@ -166,6 +166,11 @@ public T getClearValue() {
public void setClearValue(T clearValue) {
this.clearValue = clearValue;
}

@Override
public boolean canGetCleartext() {
return clearValue != null || encryptedDataType != null;
}

@Override
public void destroyCleartext() {
Expand Down
Expand Up @@ -216,6 +216,7 @@ public abstract class SchemaConstants {
public static final ItemPath PATH_CREDENTIALS_PASSWORD_FAILED_LOGINS = new ItemPath(
UserType.F_CREDENTIALS, CredentialsType.F_PASSWORD, PasswordType.F_FAILED_LOGINS);
public static final ItemPath PATH_LINK_REF = new ItemPath(FocusType.F_LINK_REF);
public static final ItemPath PATH_LIFECYCLE_STATE = new ItemPath(ObjectType.F_LIFECYCLE_STATE);

public static final String NS_PROVISIONING = NS_MIDPOINT_PUBLIC + "/provisioning";
public static final String NS_PROVISIONING_LIVE_SYNC = NS_PROVISIONING + "/liveSync-3";
Expand Down
Expand Up @@ -23,11 +23,15 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentSelectorType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CredentialsType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.OrderConstraintsType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.PasswordType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType;

/**
* @author semancik
Expand Down Expand Up @@ -147,4 +151,19 @@ public static ShadowKindType determineConstructionKind(AssignmentType assignment

throw new IllegalArgumentException("Construction not defined in the assigment.");
}

public static ProtectedStringType getPasswordValue(UserType user) {
if (user == null) {
return null;
}
CredentialsType creds = user.getCredentials();
if (creds == null) {
return null;
}
PasswordType passwd = creds.getPassword();
if (passwd == null) {
return null;
}
return passwd.getValue();
}
}
Expand Up @@ -4183,6 +4183,18 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="lifecycle" minOccurs="0" type="tns:ResourceObjectLifecycleDefinitionType">
<xsd:annotation>
<xsd:documentation>
Definition of resource object lifecycle handling. It defines
how the initial lifecycle state is determined, constraints for lifecycle
transitions, etc.
</xsd:documentation>
<xsd:appinfo>
<a:since>3.6</a:since>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="pagedSearches" minOccurs="0" type="xsd:anyType">
<xsd:annotation>
<xsd:documentation>
Expand Down Expand Up @@ -5078,6 +5090,39 @@
</xsd:element>
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="ResourceObjectLifecycleDefinitionType">
<xsd:annotation>
<xsd:documentation>
Definition of resource object lifecycle handling. It defines
how the initial lifecycle state is determined, constraints for lifecycle
transitions, etc.
</xsd:documentation>
<xsd:appinfo>
<a:since>3.6</a:since>
</xsd:appinfo>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="lifecycleState" type="tns:ResourceBidirectionalMappingType" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
Lifecycle state mapping. This mapping influences how shadow lifecycle state and focus
lifecycle state are mapped.
Default outbound lifecycleState mapping is somehow smart algorithm that will consider
presence of the focus password, resource password capability, operation and so on.
It is defined to work well with hashed passwords.
Default inbound lifecycle mapping is empty: no mapping at all. In midPoint 3.6 the inbound
lifecycle mapping is not implemented.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- TODO: validation for each individual lifecycle state.
References to forms for each state. The forms may be used both for validation and
for entering the missing properties.
We need to align this with similar method to control lifecycle transitions
for all other objects -->
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="ResourceBidirectionalMappingType">
<xsd:sequence>
Expand Down Expand Up @@ -12621,6 +12666,7 @@
<xsd:element name="projectionValues" type="tns:PartialProcessingTypeType" minOccurs="0" default="automatic"/>
<xsd:element name="projectionCredentials" type="tns:PartialProcessingTypeType" minOccurs="0" default="automatic"/>
<xsd:element name="projectionReconciliation" type="tns:PartialProcessingTypeType" minOccurs="0" default="automatic"/>
<xsd:element name="projectionLifecycle" type="tns:PartialProcessingTypeType" minOccurs="0" default="automatic"/>
<xsd:element name="approvals" type="tns:PartialProcessingTypeType" minOccurs="0" default="automatic"/>
<xsd:element name="execution" type="tns:PartialProcessingTypeType" minOccurs="0" default="automatic"/>
<xsd:element name="notification" type="tns:PartialProcessingTypeType" minOccurs="0" default="automatic"/>
Expand Down
Expand Up @@ -1037,4 +1037,10 @@ List<UserType> getMembers(String orgOid)
List<ObjectReferenceType> getMembersAsReferences(String orgOid)
throws SchemaException, SecurityViolationException, CommunicationException, ConfigurationException,
ObjectNotFoundException;

/**
* Default function used to compute projection lifecycle. It is provided here so it can be explicitly
* invoked from a custom expression and then the result can be changed for special cases.
*/
<F extends FocusType> String computeProjectionLifecycle(F focus, ShadowType shadow, ResourceType resource);
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2013 Evolveum
* Copyright (c) 2010-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -104,8 +104,8 @@ public <T, V extends PrismValue> List<V> evaluate(ScriptExpressionEvaluatorType
try {
InternalMonitor.recordScriptExecution();
evalRawResult = compiledScript.eval(bindings);
} catch (ScriptException e) {
throw new ExpressionEvaluationException(e.getMessage() + " " + contextDescription, e);
} catch (Throwable e) {
throw new ExpressionEvaluationException(e.getMessage() + " in " + contextDescription, e);
}

if (outputDefinition == null) {
Expand Down Expand Up @@ -172,8 +172,8 @@ public <T> Object evaluateReportScript(String codeString, ExpressionVariables va
try {
InternalMonitor.recordScriptExecution();
evalRawResult = compiledScript.eval(bindings);
} catch (ScriptException e) {
throw new ExpressionEvaluationException(e.getMessage() + " " + contextDescription, e);
} catch (Throwable e) {
throw new ExpressionEvaluationException(e.getMessage() + " in " + contextDescription, e);
}


Expand All @@ -190,7 +190,7 @@ private CompiledScript createCompiledScript(String codeString, String contextDes
InternalMonitor.recordScriptCompile();
compiledScript = ((Compilable)scriptEngine).compile(codeString);
} catch (ScriptException e) {
throw new ExpressionEvaluationException(e.getMessage() + " " + contextDescription, e);
throw new ExpressionEvaluationException(e.getMessage() + " in " + contextDescription, e);
}
scriptCache.put(codeString, compiledScript);
return compiledScript;
Expand All @@ -201,7 +201,7 @@ private <T> T convertScalarResult(Class<T> expectedType, Object rawValue, String
T convertedValue = ExpressionUtil.convertValue(expectedType, rawValue, protector, prismContext);
return convertedValue;
} catch (IllegalArgumentException e) {
throw new ExpressionEvaluationException(e.getMessage()+" in "+contextDescription, e);
throw new ExpressionEvaluationException(e.getMessage() + " in " + contextDescription, e);
}
}

Expand Down
Expand Up @@ -44,6 +44,7 @@
import com.evolveum.midpoint.schema.ResourceShadowDiscriminator;
import com.evolveum.midpoint.schema.ResultHandler;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.*;
import com.evolveum.midpoint.task.api.Task;
Expand All @@ -60,6 +61,9 @@
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.CredentialsCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.PasswordCapabilityType;

import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -1241,4 +1245,33 @@ public List<UserType> getMembers(String orgOid) throws SchemaException, ObjectNo
.build();
return searchObjects(UserType.class, query, null);
}

@Override
public <F extends FocusType> String computeProjectionLifecycle(F focus, ShadowType shadow, ResourceType resource) {
if (focus == null || shadow == null) {
return null;
}
if (!(focus instanceof UserType)) {
return null;
}
if (shadow.getKind() != null && shadow.getKind() != ShadowKindType.ACCOUNT) {
return null;
}
ProtectedStringType passwordPs = FocusTypeUtil.getPasswordValue((UserType)focus);
if (passwordPs != null && passwordPs.canGetCleartext()) {
return null;
}
CredentialsCapabilityType credentialsCapabilityType = ResourceTypeUtil.getEffectiveCapability(resource, CredentialsCapabilityType.class);
if (credentialsCapabilityType == null) {
return null;
}
PasswordCapabilityType passwordCapabilityType = credentialsCapabilityType.getPassword();
if (passwordCapabilityType == null) {
return null;
}
if (passwordCapabilityType.isEnabled() == Boolean.FALSE) {
return null;
}
return SchemaConstants.LIFECYCLE_PROPOSED;
}
}
Expand Up @@ -1205,16 +1205,34 @@ public static void processRuleWithException(EvaluatedPolicyRule rule, EvaluatedP

}


public static void partialExecute(String componentName, ProjectorComponentRunnable runnable, Supplier<PartialProcessingTypeType> optionSupplier)
throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException,
PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException {
partialExecute(componentName, runnable, optionSupplier, null);
}

public static void partialExecute(String componentName, ProjectorComponentRunnable runnable,
Supplier<PartialProcessingTypeType> optionSupplier, OperationResult result)
throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException,
PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException {
PartialProcessingTypeType option = optionSupplier.get();
if (option == PartialProcessingTypeType.SKIP) {
LOGGER.debug("Skipping projector component {} because partial execution option is set to {}", componentName, option);
} else {
LOGGER.trace("Projector component started: {}", componentName);
runnable.run();
LOGGER.trace("Projector component finished: {}", componentName);
try {
runnable.run();
LOGGER.trace("Projector component finished: {}", componentName);
} catch (SchemaException | ObjectNotFoundException | CommunicationException | ConfigurationException | SecurityViolationException
| PolicyViolationException | ExpressionEvaluationException | ObjectAlreadyExistsException | RuntimeException | Error e) {
LOGGER.trace("Projector component error: {}: {}: {}", componentName, e.getClass().getSimpleName(), e.getMessage());
if (result != null) {
result.recordFatalError(e);
}
throw e;
}

}
}

Expand Down

0 comments on commit a0d945d

Please sign in to comment.