use of com.evolveum.midpoint.security.api.ObjectSecurityConstraints in project midpoint by Evolveum.
the class ModelInteractionServiceImpl method getAssignableRoleSpecification.
@Override
public <F extends FocusType> RoleSelectionSpecification getAssignableRoleSpecification(PrismObject<F> focus, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, ConfigurationException {
OperationResult result = parentResult.createMinorSubresult(GET_ASSIGNABLE_ROLE_SPECIFICATION);
RoleSelectionSpecification spec = new RoleSelectionSpecification();
ObjectSecurityConstraints securityConstraints = securityEnforcer.compileSecurityConstraints(focus, null);
if (securityConstraints == null) {
return null;
}
AuthorizationDecisionType decision = securityConstraints.findItemDecision(new ItemPath(FocusType.F_ASSIGNMENT), ModelAuthorizationAction.MODIFY.getUrl(), AuthorizationPhaseType.REQUEST);
if (decision == AuthorizationDecisionType.ALLOW) {
getAllRoleTypesSpec(spec, result);
result.recordSuccess();
return spec;
}
if (decision == AuthorizationDecisionType.DENY) {
result.recordSuccess();
spec.setNoRoleTypes();
spec.setFilter(NoneFilter.createNone());
return spec;
}
decision = securityConstraints.getActionDecision(ModelAuthorizationAction.MODIFY.getUrl(), AuthorizationPhaseType.REQUEST);
if (decision == AuthorizationDecisionType.ALLOW) {
getAllRoleTypesSpec(spec, result);
result.recordSuccess();
return spec;
}
if (decision == AuthorizationDecisionType.DENY) {
result.recordSuccess();
spec.setNoRoleTypes();
spec.setFilter(NoneFilter.createNone());
return spec;
}
try {
ObjectFilter filter = securityEnforcer.preProcessObjectFilter(ModelAuthorizationAction.ASSIGN.getUrl(), AuthorizationPhaseType.REQUEST, AbstractRoleType.class, focus, AllFilter.createAll());
LOGGER.trace("assignableRoleSpec filter: {}", filter);
spec.setFilter(filter);
if (filter instanceof NoneFilter) {
result.recordSuccess();
spec.setNoRoleTypes();
return spec;
} else if (filter == null || filter instanceof AllFilter) {
getAllRoleTypesSpec(spec, result);
result.recordSuccess();
return spec;
} else if (filter instanceof OrFilter) {
Collection<RoleSelectionSpecEntry> allRoleTypeDvals = new ArrayList<>();
for (ObjectFilter subfilter : ((OrFilter) filter).getConditions()) {
Collection<RoleSelectionSpecEntry> roleTypeDvals = getRoleSelectionSpecEntries(subfilter);
if (roleTypeDvals == null || roleTypeDvals.isEmpty()) {
// This branch of the OR clause does not have any constraint for roleType
// therefore all role types are possible (regardless of other branches, this is OR)
spec = new RoleSelectionSpecification();
spec.setFilter(filter);
getAllRoleTypesSpec(spec, result);
result.recordSuccess();
return spec;
} else {
allRoleTypeDvals.addAll(roleTypeDvals);
}
}
addRoleTypeSpecEntries(spec, allRoleTypeDvals, result);
} else {
Collection<RoleSelectionSpecEntry> roleTypeDvals = getRoleSelectionSpecEntries(filter);
if (roleTypeDvals == null || roleTypeDvals.isEmpty()) {
getAllRoleTypesSpec(spec, result);
result.recordSuccess();
return spec;
} else {
addRoleTypeSpecEntries(spec, roleTypeDvals, result);
}
}
result.recordSuccess();
return spec;
} catch (SchemaException | ConfigurationException | ObjectNotFoundException e) {
result.recordFatalError(e);
throw e;
}
}
use of com.evolveum.midpoint.security.api.ObjectSecurityConstraints in project midpoint by Evolveum.
the class ModelInteractionServiceImpl method getEditObjectDefinition.
@Override
public <O extends ObjectType> PrismObjectDefinition<O> getEditObjectDefinition(PrismObject<O> object, AuthorizationPhaseType phase, Task task, OperationResult parentResult) throws SchemaException, ConfigurationException, ObjectNotFoundException {
OperationResult result = parentResult.createMinorSubresult(GET_EDIT_OBJECT_DEFINITION);
PrismObjectDefinition<O> objectDefinition = object.getDefinition().deepClone(true);
PrismObject<O> baseObject = object;
if (object.getOid() != null) {
// Re-read the object from the repository to make sure we have all the properties.
// the object from method parameters may be already processed by the security code
// and properties needed to evaluate authorizations may not be there
// MID-3126, see also MID-3435
baseObject = cacheRepositoryService.getObject(object.getCompileTimeClass(), object.getOid(), null, result);
}
// TODO: maybe we need to expose owner resolver in the interface?
ObjectSecurityConstraints securityConstraints = securityEnforcer.compileSecurityConstraints(baseObject, null);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Security constrains for {}:\n{}", object, securityConstraints == null ? "null" : securityConstraints.debugDump());
}
if (securityConstraints == null) {
// Nothing allowed => everything denied
result.setStatus(OperationResultStatus.NOT_APPLICABLE);
return null;
}
ObjectTemplateType objectTemplateType;
try {
objectTemplateType = schemaTransformer.determineObjectTemplate(object, phase, result);
} catch (ConfigurationException | ObjectNotFoundException e) {
result.recordFatalError(e);
throw e;
}
schemaTransformer.applyObjectTemplateToDefinition(objectDefinition, objectTemplateType, result);
schemaTransformer.applySecurityConstraints(objectDefinition, securityConstraints, phase);
if (object.canRepresent(ShadowType.class)) {
PrismObject<ShadowType> shadow = (PrismObject<ShadowType>) object;
String resourceOid = ShadowUtil.getResourceOid(shadow);
if (resourceOid != null) {
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(GetOperationOptions.createReadOnly());
PrismObject<ResourceType> resource;
try {
resource = provisioning.getObject(ResourceType.class, resourceOid, options, task, result);
} catch (CommunicationException | SecurityViolationException | ExpressionEvaluationException e) {
throw new ConfigurationException(e.getMessage(), e);
}
RefinedObjectClassDefinition refinedObjectClassDefinition = getEditObjectClassDefinition(shadow, resource, phase);
if (refinedObjectClassDefinition != null) {
((ComplexTypeDefinitionImpl) objectDefinition.getComplexTypeDefinition()).replaceDefinition(ShadowType.F_ATTRIBUTES, refinedObjectClassDefinition.toResourceAttributeContainerDefinition());
}
}
}
result.computeStatus();
return objectDefinition;
}
use of com.evolveum.midpoint.security.api.ObjectSecurityConstraints in project midpoint by Evolveum.
the class ModelInteractionServiceImpl method getEditObjectClassDefinition.
@Override
public RefinedObjectClassDefinition getEditObjectClassDefinition(PrismObject<ShadowType> shadow, PrismObject<ResourceType> resource, AuthorizationPhaseType phase) throws SchemaException {
Validate.notNull(resource, "Resource must not be null");
RefinedResourceSchema refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema(resource);
CompositeRefinedObjectClassDefinition rocd = refinedSchema.determineCompositeObjectClassDefinition(shadow);
if (rocd == null) {
LOGGER.debug("No object class definition for shadow {}, returning null");
return null;
}
LayerRefinedObjectClassDefinition layeredROCD = rocd.forLayer(LayerType.PRESENTATION);
// TODO: maybe we need to expose owner resolver in the interface?
ObjectSecurityConstraints securityConstraints = securityEnforcer.compileSecurityConstraints(shadow, null);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Security constrains for {}:\n{}", shadow, securityConstraints == null ? "null" : securityConstraints.debugDump());
}
if (securityConstraints == null) {
return null;
}
ItemPath attributesPath = new ItemPath(ShadowType.F_ATTRIBUTES);
AuthorizationDecisionType attributesReadDecision = schemaTransformer.computeItemDecision(securityConstraints, attributesPath, ModelAuthorizationAction.READ.getUrl(), securityConstraints.getActionDecision(ModelAuthorizationAction.READ.getUrl(), phase), phase);
AuthorizationDecisionType attributesAddDecision = schemaTransformer.computeItemDecision(securityConstraints, attributesPath, ModelAuthorizationAction.ADD.getUrl(), securityConstraints.getActionDecision(ModelAuthorizationAction.ADD.getUrl(), phase), phase);
AuthorizationDecisionType attributesModifyDecision = schemaTransformer.computeItemDecision(securityConstraints, attributesPath, ModelAuthorizationAction.MODIFY.getUrl(), securityConstraints.getActionDecision(ModelAuthorizationAction.MODIFY.getUrl(), phase), phase);
LOGGER.trace("Attributes container access read:{}, add:{}, modify:{}", attributesReadDecision, attributesAddDecision, attributesModifyDecision);
/*
* We are going to modify attribute definitions list.
* So let's make a (shallow) clone here, although it is probably not strictly necessary.
*/
layeredROCD = layeredROCD.clone();
for (LayerRefinedAttributeDefinition rAttrDef : layeredROCD.getAttributeDefinitions()) {
ItemPath attributePath = new ItemPath(ShadowType.F_ATTRIBUTES, rAttrDef.getName());
AuthorizationDecisionType attributeReadDecision = schemaTransformer.computeItemDecision(securityConstraints, attributePath, ModelAuthorizationAction.READ.getUrl(), attributesReadDecision, phase);
AuthorizationDecisionType attributeAddDecision = schemaTransformer.computeItemDecision(securityConstraints, attributePath, ModelAuthorizationAction.ADD.getUrl(), attributesAddDecision, phase);
AuthorizationDecisionType attributeModifyDecision = schemaTransformer.computeItemDecision(securityConstraints, attributePath, ModelAuthorizationAction.MODIFY.getUrl(), attributesModifyDecision, phase);
LOGGER.trace("Attribute {} access read:{}, add:{}, modify:{}", rAttrDef.getName(), attributeReadDecision, attributeAddDecision, attributeModifyDecision);
if (attributeReadDecision != AuthorizationDecisionType.ALLOW) {
((LayerRefinedAttributeDefinitionImpl) rAttrDef).setOverrideCanRead(false);
}
if (attributeAddDecision != AuthorizationDecisionType.ALLOW) {
((LayerRefinedAttributeDefinitionImpl) rAttrDef).setOverrideCanAdd(false);
}
if (attributeModifyDecision != AuthorizationDecisionType.ALLOW) {
((LayerRefinedAttributeDefinitionImpl) rAttrDef).setOverrideCanModify(false);
}
}
return layeredROCD;
}
use of com.evolveum.midpoint.security.api.ObjectSecurityConstraints in project midpoint by Evolveum.
the class Clockwork method authorizeElementContext.
private <F extends ObjectType, O extends ObjectType> ObjectSecurityConstraints authorizeElementContext(LensContext<F> context, LensElementContext<O> elementContext, OwnerResolver ownerResolver, boolean isFocus, Task task, OperationResult result) throws SecurityViolationException, SchemaException {
ObjectDelta<O> primaryDelta = elementContext.getPrimaryDelta();
// If there is no delta then there is no request to authorize
if (primaryDelta != null) {
primaryDelta = primaryDelta.clone();
PrismObject<O> object = elementContext.getObjectCurrent();
if (object == null) {
// This may happen when object is being added.
// But also in cases such as assignment of account and modification of
// the same account in one operation
object = elementContext.getObjectNew();
}
String operationUrl = ModelUtils.getOperationUrlFromDelta(primaryDelta);
ObjectSecurityConstraints securityConstraints = securityEnforcer.compileSecurityConstraints(object, ownerResolver);
if (securityConstraints == null) {
throw new AuthorizationException("Access denied");
}
if (isFocus) {
// Process assignments first. If the assignments are allowed then we
// have to ignore the assignment item in subsequent security checks
ContainerDelta<Containerable> assignmentDelta = primaryDelta.findContainerDelta(FocusType.F_ASSIGNMENT);
if (assignmentDelta != null) {
AuthorizationDecisionType assignmentItemDecision = securityConstraints.findItemDecision(new ItemPath(FocusType.F_ASSIGNMENT), operationUrl, getRequestAuthorizationPhase(context));
if (assignmentItemDecision == AuthorizationDecisionType.ALLOW) {
// Nothing to do, operation is allowed for all values
} else if (assignmentItemDecision == AuthorizationDecisionType.DENY) {
throw new AuthorizationException("Access denied");
} else {
AuthorizationDecisionType actionDecision = securityConstraints.getActionDecision(operationUrl, getRequestAuthorizationPhase(context));
if (actionDecision == AuthorizationDecisionType.ALLOW) {
// Nothing to do, operation is allowed for all values
} else if (actionDecision == AuthorizationDecisionType.DENY) {
throw new AuthorizationException("Access denied");
} else {
// No explicit decision for assignment modification yet
// process each assignment individually
DeltaSetTriple<EvaluatedAssignmentImpl<?>> evaluatedAssignmentTriple = context.getEvaluatedAssignmentTriple();
authorizeAssignmentRequest(context, ModelAuthorizationAction.ASSIGN.getUrl(), object, ownerResolver, evaluatedAssignmentTriple.getPlusSet(), true, result);
// We want to allow unassignment even if there are policies. Otherwise we would not be able to get
// rid of that assignment
authorizeAssignmentRequest(context, ModelAuthorizationAction.UNASSIGN.getUrl(), object, ownerResolver, evaluatedAssignmentTriple.getMinusSet(), false, result);
}
}
// authorization
if (primaryDelta.isAdd()) {
PrismObject<O> objectToAdd = primaryDelta.getObjectToAdd();
objectToAdd.removeContainer(FocusType.F_ASSIGNMENT);
} else if (primaryDelta.isModify()) {
primaryDelta.removeContainerModification(FocusType.F_ASSIGNMENT);
}
}
}
if (!primaryDelta.isDelete()) {
if (primaryDelta.isAdd()) {
PrismObject<O> objectToAdd = primaryDelta.getObjectToAdd();
PrismContainer<CredentialsType> credentialsContainer = objectToAdd.findContainer(UserType.F_CREDENTIALS);
if (credentialsContainer != null) {
for (Item<?, ?> item : credentialsContainer.getValue().getItems()) {
ContainerDelta<?> cdelta = new ContainerDelta(item.getPath(), (PrismContainerDefinition) item.getDefinition(), prismContext);
cdelta.addValuesToAdd(((PrismContainer) item).getValue().clone());
AuthorizationDecisionType cdecision = evaluateCredentialDecision(context, securityConstraints, cdelta);
LOGGER.trace("AUTZ: credential add {} decision: {}", item.getPath(), cdecision);
if (cdecision == AuthorizationDecisionType.ALLOW) {
// Remove it from primary delta, so it will not be evaluated later
objectToAdd.removeContainer(item.getPath());
} else if (cdecision == AuthorizationDecisionType.DENY) {
throw new AuthorizationException("Access denied");
} else {
// Do nothing. The access will be evaluated later in a normal way
}
}
}
} else {
// modify
Collection<? extends ItemDelta<?, ?>> credentialChanges = primaryDelta.findItemDeltasSubPath(new ItemPath(UserType.F_CREDENTIALS));
for (ItemDelta credentialChange : credentialChanges) {
AuthorizationDecisionType cdecision = evaluateCredentialDecision(context, securityConstraints, credentialChange);
LOGGER.trace("AUTZ: credential delta {} decision: {}", credentialChange.getPath(), cdecision);
if (cdecision == AuthorizationDecisionType.ALLOW) {
// Remove it from primary delta, so it will not be evaluated later
primaryDelta.removeModification(credentialChange);
} else if (cdecision == AuthorizationDecisionType.DENY) {
throw new AuthorizationException("Access denied");
} else {
// Do nothing. The access will be evaluated later in a normal way
}
}
}
}
if (primaryDelta != null && !primaryDelta.isEmpty()) {
// TODO: optimize, avoid evaluating the constraints twice
securityEnforcer.authorize(operationUrl, getRequestAuthorizationPhase(context), object, primaryDelta, null, ownerResolver, result);
}
return securityConstraints;
} else {
return null;
}
}
use of com.evolveum.midpoint.security.api.ObjectSecurityConstraints in project midpoint by Evolveum.
the class SchemaTransformer method applySchemasAndSecurity.
/**
* Validate the objects, apply security to the object definition, remove any non-visible properties (security),
* apply object template definitions and so on. This method is called for
* any object that is returned from the Model Service.
*/
public <O extends ObjectType> void applySchemasAndSecurity(PrismObject<O> object, GetOperationOptions rootOptions, AuthorizationPhaseType phase, Task task, OperationResult parentResult) throws SchemaException, SecurityViolationException, ConfigurationException, ObjectNotFoundException {
OperationResult result = parentResult.createMinorSubresult(SchemaTransformer.class.getName() + ".applySchemasAndSecurity");
validateObject(object, rootOptions, result);
PrismObjectDefinition<O> objectDefinition = object.deepCloneDefinition(true);
ObjectSecurityConstraints securityConstraints;
try {
securityConstraints = securityEnforcer.compileSecurityConstraints(object, null);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Security constrains for {}:\n{}", object, securityConstraints == null ? "null" : securityConstraints.debugDump());
}
if (securityConstraints == null) {
SecurityUtil.logSecurityDeny(object, "because no security constraints are defined (default deny)");
throw new AuthorizationException("Access denied");
}
} catch (SecurityViolationException | SchemaException | RuntimeException e) {
result.recordFatalError(e);
throw e;
}
if (phase == null) {
applySchemasAndSecurityPhase(object, securityConstraints, objectDefinition, rootOptions, AuthorizationPhaseType.REQUEST, task, result);
applySchemasAndSecurityPhase(object, securityConstraints, objectDefinition, rootOptions, AuthorizationPhaseType.EXECUTION, task, result);
} else {
applySchemasAndSecurityPhase(object, securityConstraints, objectDefinition, rootOptions, phase, task, result);
}
ObjectTemplateType objectTemplateType;
try {
objectTemplateType = determineObjectTemplate(object, AuthorizationPhaseType.REQUEST, result);
} catch (ConfigurationException | ObjectNotFoundException e) {
result.recordFatalError(e);
throw e;
}
applyObjectTemplateToObject(object, objectTemplateType, result);
result.computeStatus();
result.recordSuccessIfUnknown();
}
Aggregations