/** * Simple access control decision similar to that used by spring security. * It is practically applicable only for simple (non-parametric) cases such as access to GUI pages. * However, it supports authorization hierarchies. Therefore the ordering of elements in * required actions is important. */ @Override public AccessDecision decideAccess(MidPointPrincipal principal, List<String> requiredActions, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException { AccessDecision finalDecision = AccessDecision.DEFAULT; for(String requiredAction: requiredActions) { AccessDecision decision = isAuthorizedInternal(principal, requiredAction, null, AuthorizationParameters.EMPTY, null, null, task, result); if (AccessDecision.DENY.equals(decision)) { return AccessDecision.DENY; } if (AccessDecision.ALLOW.equals(decision)) { finalDecision = AccessDecision.ALLOW; } } return finalDecision; }
for (PrismContainerValue<?> subValue: subValues) { AccessDecision subdecision = determineContainerDecision(subValue, itemDecisionFunction, removingContainer, decisionContextDesc); containerDecision = AccessDecision.combine(containerDecision, subdecision); decision = AccessDecision.combine(decision, containerDecision); decision = AccessDecision.combine(decision, itemDecision);
private AccessDecision subitemDecide(ItemPath nameOnlyItemPath, boolean removingContainer, ObjectSecurityConstraints securityConstraints, String operationUrl, AuthorizationPhaseType phase, ItemPath subitemRootPath) { if (removingContainer && isInList(nameOnlyItemPath, AuthorizationConstants.OPERATIONAL_ITEMS_ALLOWED_FOR_CONTAINER_DELETE)) { return null; } if (AuthorizationPhaseType.EXECUTION.equals(phase) && isInList(nameOnlyItemPath, AuthorizationConstants.EXECUTION_ITEMS_ALLOWED_BY_DEFAULT)) { return null; } if (subitemRootPath != null && !subitemRootPath.isSubPathOrEquivalent(nameOnlyItemPath)) { // LOGGER.trace("subitem decision: {} <=> {} (not under root) : {}", subitemRootPath, nameOnlyItemPath, null); return null; } AuthorizationDecisionType authorizationDecisionType = securityConstraints.findItemDecision(nameOnlyItemPath, operationUrl, phase); AccessDecision decision = AccessDecision.translate(authorizationDecisionType); // LOGGER.trace("subitem decision: {} <=> {} : {}", subitemRootPath, nameOnlyItemPath, decision); return decision; }
for (PrismContainerValue<C> cval: valuesToAdd) { AccessDecision subdecision = determineContainerDecision(cval, itemDecitionFunction, false, "delta add"); decision = AccessDecision.combine(decision, subdecision); decision = AccessDecision.combine(decision, subdecision); for (PrismContainerValue<C> cval: valuesToReplace) { AccessDecision subdecision = determineContainerDecision(cval, itemDecitionFunction, false, "delta replace"); decision = AccessDecision.combine(decision, subdecision); for (PrismContainerValue<C> cval: oldCvals) { AccessDecision subdecision = determineContainerDecision(cval, itemDecitionFunction, true, "delta replace (removed current value)"); decision = AccessDecision.combine(decision, subdecision);
@Override public <C extends Containerable> AccessDecision determineSubitemDecision( ObjectSecurityConstraints securityConstraints, PrismContainerValue<C> containerValue, String operationUrl, AuthorizationPhaseType phase, ItemPath subitemRootPath, PlusMinusZero plusMinusZero, String decisionContextDesc) { boolean removingContainer = false; if (plusMinusZero == PlusMinusZero.MINUS) { removingContainer = true; } return determineContainerDecision(containerValue, (nameOnlyItemPath, lRemovingContainer) -> { if (lRemovingContainer && isInList(nameOnlyItemPath, AuthorizationConstants.OPERATIONAL_ITEMS_ALLOWED_FOR_CONTAINER_DELETE)) { return null; } if (AuthorizationPhaseType.EXECUTION.equals(phase) && isInList(nameOnlyItemPath, AuthorizationConstants.EXECUTION_ITEMS_ALLOWED_BY_DEFAULT)) { return null; } if (subitemRootPath != null && !subitemRootPath.isSubPathOrEquivalent(nameOnlyItemPath)) { // LOGGER.trace("subitem decision: {} <=> {} (not under root) : {}", subitemRootPath, nameOnlyItemPath, null); return null; } AuthorizationDecisionType authorizationDecisionType = securityConstraints.findItemDecision(nameOnlyItemPath, operationUrl, phase); AccessDecision decision = AccessDecision.translate(authorizationDecisionType); // LOGGER.trace("subitem decision: {} <=> {} : {}", subitemRootPath, nameOnlyItemPath, decision); return decision; }, removingContainer, decisionContextDesc); } }
@Override public <O extends ObjectType, T extends ObjectType> boolean isAuthorized(String operationUrl, AuthorizationPhaseType phase, AuthorizationParameters<O,T> params, OwnerResolver ownerResolver, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException { AccessDecision decision = isAuthorizedInternal(getMidPointPrincipal(), operationUrl, phase, params, ownerResolver, null, task, result); return decision.equals(AccessDecision.ALLOW); }
private <O extends ObjectType, T extends ObjectType> AccessDecision isAuthorizedInternal(MidPointPrincipal midPointPrincipal, String operationUrl, AuthorizationPhaseType phase, AuthorizationParameters<O,T> params, OwnerResolver ownerResolver, Consumer<Authorization> applicableAutzConsumer, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException { if (phase == null) { AccessDecision requestPhaseDecision = isAuthorizedPhase(midPointPrincipal, operationUrl, AuthorizationPhaseType.REQUEST, params, ownerResolver, applicableAutzConsumer, task, result); if (!requestPhaseDecision.equals(AccessDecision.ALLOW)) { return requestPhaseDecision; } return isAuthorizedPhase(midPointPrincipal, operationUrl, AuthorizationPhaseType.EXECUTION, params, ownerResolver, applicableAutzConsumer, task, result); } else { return isAuthorizedPhase(midPointPrincipal, operationUrl, phase, params, ownerResolver, applicableAutzConsumer, task, result); } }
@Override public MidPointPrincipal createDonorPrincipal(MidPointPrincipal attorneyPrincipal, String attorneyAuthorizationAction, PrismObject<UserType> donor, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException { if (attorneyPrincipal.getAttorney() != null) { throw new UnsupportedOperationException("Transitive attorney is not supported yet"); } AuthorizationLimitationsCollector limitationsCollector = new AuthorizationLimitationsCollector(); AuthorizationParameters<UserType, ObjectType> autzParams = AuthorizationParameters.Builder.buildObject(donor); AccessDecision decision = isAuthorizedInternal(attorneyPrincipal, attorneyAuthorizationAction, null, autzParams, null, limitationsCollector, task, result); if (!decision.equals(AccessDecision.ALLOW)) { failAuthorization(attorneyAuthorizationAction, null, autzParams, result); } MidPointPrincipal donorPrincipal = securityContextManager.getUserProfileService().getPrincipal(donor, limitationsCollector, result); donorPrincipal.setAttorney(attorneyPrincipal.getUser()); // chain principals so we can easily drop the power of attorney and return back to original identity donorPrincipal.setPreviousPrincipal(attorneyPrincipal); return donorPrincipal; }