List of usage examples for org.springframework.security.core GrantedAuthority getClass
@HotSpotIntrinsicCandidate public final native Class<?> getClass();
From source file:com.evolveum.midpoint.security.impl.SecurityEnforcerImpl.java
@Override public <O extends ObjectType> ObjectSecurityConstraints compileSecurityConstraints(PrismObject<O> object, OwnerResolver ownerResolver) throws SchemaException { MidPointPrincipal principal = getMidPointPrincipal(); if (object == null) { throw new IllegalArgumentException("Cannot compile security constraints of null object"); }//from w w w . j a v a 2s . c o m if (principal == null) { // No need to log, the getMidPointPrincipal() already logs the reason return null; } LOGGER.trace("AUTZ: evaluating security constraints principal={}, object={}", principal, object); ObjectSecurityConstraintsImpl objectSecurityConstraints = new ObjectSecurityConstraintsImpl(); Collection<Authorization> authorities = principal.getAuthorities(); if (authorities != null) { for (GrantedAuthority authority : authorities) { if (authority instanceof Authorization) { Authorization autz = (Authorization) authority; String autzHumanReadableDesc = autz.getHumanReadableDesc(); LOGGER.trace("Evaluating {}", autzHumanReadableDesc); // skip action applicability evaluation. We are interested in all actions // object if (isApplicable(autz.getObject(), object, principal, ownerResolver, "object", autzHumanReadableDesc)) { LOGGER.trace(" {} applicable for object {} (continuing evaluation)", autzHumanReadableDesc, object); } else { LOGGER.trace( " {} not applicable for object {}, none of the object specifications match (breaking evaluation)", autzHumanReadableDesc, object); continue; } // skip target applicability evaluation. We do not have a target here List<String> actions = autz.getAction(); AuthorizationPhaseType phase = autz.getPhase(); AuthorizationDecisionType decision = autz.getDecision(); if (decision == null || decision == AuthorizationDecisionType.ALLOW) { Collection<ItemPath> items = getItems(autz); if (items == null || items.isEmpty()) { applyDecision(objectSecurityConstraints.getActionDecisionMap(), actions, phase, AuthorizationDecisionType.ALLOW); } else { for (ItemPath item : items) { applyItemDecision(objectSecurityConstraints.getItemConstraintMap(), item, actions, phase, AuthorizationDecisionType.ALLOW); } } } else { Collection<ItemPath> items = getItems(autz); if (items == null || items.isEmpty()) { applyDecision(objectSecurityConstraints.getActionDecisionMap(), actions, phase, AuthorizationDecisionType.DENY); } else { for (ItemPath item : items) { applyItemDecision(objectSecurityConstraints.getItemConstraintMap(), item, actions, phase, AuthorizationDecisionType.DENY); } } } } else { LOGGER.warn("Unknown authority type {} in user {}", authority.getClass(), principal.getUsername()); } } } if (LOGGER.isTraceEnabled()) { LOGGER.trace("AUTZ: evaluated security constraints principal={}, object={}:\n{}", principal, object, objectSecurityConstraints.debugDump()); } return objectSecurityConstraints; }
From source file:com.evolveum.midpoint.security.impl.SecurityEnforcerImpl.java
private <O extends ObjectType, T extends ObjectType> boolean isAuthorizedInternal( MidPointPrincipal midPointPrincipal, String operationUrl, AuthorizationPhaseType phase, PrismObject<O> object, ObjectDelta<O> delta, PrismObject<T> target, OwnerResolver ownerResolver) throws SchemaException { if (AuthorizationConstants.AUTZ_NO_ACCESS_URL.equals(operationUrl)) { return false; }/* w ww. j a v a 2s . com*/ if (phase == null) { throw new IllegalArgumentException("No phase"); } boolean allow = false; LOGGER.trace("AUTZ: evaluating authorization principal={}, op={}, phase={}, object={}, delta={}, target={}", new Object[] { midPointPrincipal, operationUrl, phase, object, delta, target }); final Collection<ItemPath> allowedItems = new ArrayList<>(); Collection<Authorization> authorities = midPointPrincipal.getAuthorities(); if (authorities != null) { for (GrantedAuthority authority : authorities) { if (authority instanceof Authorization) { Authorization autz = (Authorization) authority; String autzHumanReadableDesc = autz.getHumanReadableDesc(); LOGGER.trace("Evaluating {}", autzHumanReadableDesc); // First check if the authorization is applicable. // action if (!autz.getAction().contains(operationUrl) && !autz.getAction().contains(AuthorizationConstants.AUTZ_ALL_URL)) { LOGGER.trace(" {} not applicable for operation {}", autzHumanReadableDesc, operationUrl); continue; } // phase if (autz.getPhase() == null) { LOGGER.trace(" {} is applicable for all phases (continuing evaluation)", autzHumanReadableDesc); } else { if (autz.getPhase() != phase) { LOGGER.trace(" {} is not applicable for phases {} (breaking evaluation)", autzHumanReadableDesc, phase); continue; } else { LOGGER.trace(" {} is applicable for phases {} (continuing evaluation)", autzHumanReadableDesc, phase); } } // object if (isApplicable(autz.getObject(), object, midPointPrincipal, ownerResolver, "object", autzHumanReadableDesc)) { LOGGER.trace(" {} applicable for object {} (continuing evaluation)", autzHumanReadableDesc, object); } else { LOGGER.trace( " {} not applicable for object {}, none of the object specifications match (breaking evaluation)", autzHumanReadableDesc, object); continue; } // target if (isApplicable(autz.getTarget(), target, midPointPrincipal, ownerResolver, "target", autzHumanReadableDesc)) { LOGGER.trace(" {} applicable for target {} (continuing evaluation)", autzHumanReadableDesc, object); } else { LOGGER.trace( " {} not applicable for target {}, none of the target specifications match (breaking evaluation)", autzHumanReadableDesc, object); continue; } // authority is applicable to this situation. now we can process the decision. AuthorizationDecisionType decision = autz.getDecision(); if (decision == null || decision == AuthorizationDecisionType.ALLOW) { // if there is more than one role which specify // different authz (e.g one role specify allow for whole // objet, the other role specify allow only for some // attributes. this ended with allow for whole object (MID-2018) Collection<ItemPath> allowed = getItems(autz); if (allow && allowedItems.isEmpty()) { LOGGER.trace(" {}: ALLOW operation {} (but continue evaluation)", autzHumanReadableDesc, operationUrl); } else if (allow && allowed.isEmpty()) { allowedItems.clear(); } else { allowedItems.addAll(allowed); } LOGGER.trace(" {}: ALLOW operation {} (but continue evaluation)", autzHumanReadableDesc, operationUrl); allow = true; // Do NOT break here. Other authorization statements may still deny the operation } else { // item if (isApplicableItem(autz, object, delta)) { LOGGER.trace(" {}: Deny authorization applicable for items (continuing evaluation)", autzHumanReadableDesc); } else { LOGGER.trace(" {} not applicable for items (breaking evaluation)", autzHumanReadableDesc); continue; } LOGGER.trace(" {}: DENY operation {}", autzHumanReadableDesc, operationUrl); allow = false; // Break right here. Deny cannot be overridden by allow. This decision cannot be changed. break; } } else { LOGGER.warn("Unknown authority type {} in user {}", authority.getClass(), midPointPrincipal.getUsername()); } } } if (allow) { // Still check allowedItems. We may still deny the operation. if (allowedItems.isEmpty()) { // This means all items are allowed. No need to check anything LOGGER.trace(" Empty list of allowed items, operation allowed"); } else { // all items in the object and delta must be allowed final MutableBoolean itemDecision = new MutableBoolean(true); if (delta != null) { // If there is delta then consider only the delta. Visitor visitor = new Visitor() { @Override public void visit(Visitable visitable) { ItemPath itemPath = getPath(visitable); if (itemPath != null && !itemPath.isEmpty()) { if (!isInList(itemPath, allowedItems)) { LOGGER.trace(" DENY operation because item {} in the delta is not allowed", itemPath); itemDecision.setValue(false); } } } }; delta.accept(visitor); } else if (object != null) { Visitor visitor = new Visitor() { @Override public void visit(Visitable visitable) { ItemPath itemPath = getPath(visitable); if (itemPath != null && !itemPath.isEmpty()) { if (!isInList(itemPath, allowedItems)) { LOGGER.trace(" DENY operation because item {} in the object is not allowed", itemPath); itemDecision.setValue(false); } } } }; object.accept(visitor); } allow = itemDecision.booleanValue(); } } if (LOGGER.isTraceEnabled()) { LOGGER.trace("AUTZ result: principal={}, operation={}: {}", new Object[] { midPointPrincipal, operationUrl, allow }); } return allow; }
From source file:com.evolveum.midpoint.security.enforcer.impl.SecurityEnforcerImpl.java
private <O extends ObjectType, T extends ObjectType> AccessDecision isAuthorizedPhase( 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 (AuthorizationConstants.AUTZ_NO_ACCESS_URL.equals(operationUrl)) { return AccessDecision.DENY; }// ww w . jav a 2 s . c o m if (phase == null) { throw new IllegalArgumentException("No phase"); } AccessDecision decision = AccessDecision.DEFAULT; if (LOGGER.isTraceEnabled()) { LOGGER.trace("AUTZ: evaluating authorization principal={}, op={}, phase={}, {}", getUsername(midPointPrincipal), operationUrl, phase, params.shortDump()); } final AutzItemPaths allowedItems = new AutzItemPaths(); Collection<Authorization> authorities = getAuthorities(midPointPrincipal); if (authorities != null) { for (GrantedAuthority authority : authorities) { if (authority instanceof Authorization) { Authorization autz = (Authorization) authority; String autzHumanReadableDesc = autz.getHumanReadableDesc(); LOGGER.trace(" Evaluating {}", autzHumanReadableDesc); // First check if the authorization is applicable. // action if (!autz.getAction().contains(operationUrl) && !autz.getAction().contains(AuthorizationConstants.AUTZ_ALL_URL)) { LOGGER.trace(" {} not applicable for operation {}", autzHumanReadableDesc, operationUrl); continue; } // phase if (autz.getPhase() == null) { LOGGER.trace(" {} is applicable for all phases (continuing evaluation)", autzHumanReadableDesc); } else { if (autz.getPhase() != phase) { LOGGER.trace(" {} is not applicable for phases {} (breaking evaluation)", autzHumanReadableDesc, phase); continue; } else { LOGGER.trace(" {} is applicable for phases {} (continuing evaluation)", autzHumanReadableDesc, phase); } } // relation if (!isApplicableRelation(autz, params.getRelation())) { LOGGER.trace(" {} not applicable for relation {}", autzHumanReadableDesc, params.getRelation()); continue; } // object if (isApplicable(autz.getObject(), params.getObject(), midPointPrincipal, ownerResolver, "object", autzHumanReadableDesc, task, result)) { LOGGER.trace(" {} applicable for object {} (continuing evaluation)", autzHumanReadableDesc, params.getObject()); } else { LOGGER.trace( " {} not applicable for object {}, none of the object specifications match (breaking evaluation)", autzHumanReadableDesc, params.getObject()); continue; } // target if (isApplicable(autz.getTarget(), params.getTarget(), midPointPrincipal, ownerResolver, "target", autzHumanReadableDesc, task, result)) { LOGGER.trace(" {} applicable for target {} (continuing evaluation)", autzHumanReadableDesc, params.getObject()); } else { LOGGER.trace( " {} not applicable for target {}, none of the target specifications match (breaking evaluation)", autzHumanReadableDesc, params.getObject()); continue; } if (applicableAutzConsumer != null) { applicableAutzConsumer.accept(autz); } // authority is applicable to this situation. now we can process the decision. AuthorizationDecisionType autzDecision = autz.getDecision(); if (autzDecision == null || autzDecision.equals(AuthorizationDecisionType.ALLOW)) { allowedItems.collectItems(autz); LOGGER.trace(" {}: ALLOW operation {} (but continue evaluation)", autzHumanReadableDesc, operationUrl); decision = AccessDecision.ALLOW; // Do NOT break here. Other authorization statements may still deny the operation } else { // item if (isApplicableItem(autz, params.getObject(), params.getDelta())) { LOGGER.trace(" {}: Deny authorization applicable for items (continuing evaluation)", autzHumanReadableDesc); } else { LOGGER.trace(" {} not applicable for items (breaking evaluation)", autzHumanReadableDesc); continue; } LOGGER.trace(" {}: DENY operation {}", autzHumanReadableDesc, operationUrl); decision = AccessDecision.DENY; // Break right here. Deny cannot be overridden by allow. This decision cannot be changed. break; } } else { LOGGER.warn("Unknown authority type {} in user {}", authority.getClass(), getUsername(midPointPrincipal)); } } } if (decision.equals(AccessDecision.ALLOW)) { // Still check allowedItems. We may still deny the operation. if (allowedItems.isAllItems()) { // This means all items are allowed. No need to check anything LOGGER.trace(" Empty list of allowed items, operation allowed"); } else { // all items in the object and delta must be allowed LOGGER.trace(" Checking for allowed items: {}", allowedItems); ItemDecisionFunction itemDecisionFunction = (itemPath, removingContainer) -> decideAllowedItems(itemPath, allowedItems, phase, removingContainer); AccessDecision itemsDecision = null; if (params.hasDelta()) { itemsDecision = determineDeltaDecision(params.getDelta(), params.getObject(), itemDecisionFunction); } else if (params.hasObject()) { itemsDecision = determineObjectDecision(params.getObject(), itemDecisionFunction); } if (itemsDecision != AccessDecision.ALLOW) { LOGGER.trace(" NOT ALLOWED operation because the item decision is {}", itemsDecision); decision = AccessDecision.DEFAULT; } } } if (LOGGER.isTraceEnabled()) { LOGGER.trace("AUTZ result: principal={}, operation={}: {}", getUsername(midPointPrincipal), prettyActionUrl(operationUrl), decision); } return decision; }
From source file:com.evolveum.midpoint.security.impl.SecurityEnforcerImpl.java
private <T extends ObjectType, O extends ObjectType> ObjectFilter preProcessObjectFilterInternal( MidPointPrincipal principal, String operationUrl, AuthorizationPhaseType phase, boolean includeNullPhase, Class<T> objectType, PrismObject<O> object, ObjectFilter origFilter) throws SchemaException { Collection<Authorization> authorities = principal.getAuthorities(); ObjectFilter securityFilterAllow = null; ObjectFilter securityFilterDeny = null; boolean hasAllowAll = false; if (authorities != null) { for (GrantedAuthority authority : authorities) { if (authority instanceof Authorization) { Authorization autz = (Authorization) authority; LOGGER.trace("Evaluating authorization {}", autz); // action if (!autz.getAction().contains(operationUrl) && !autz.getAction().contains(AuthorizationConstants.AUTZ_ALL_URL)) { LOGGER.trace(" Authorization not applicable for operation {}", operationUrl); continue; }/* w w w . ja v a 2s. c o m*/ // phase if (autz.getPhase() == phase || (includeNullPhase && autz.getPhase() == null)) { LOGGER.trace(" Authorization is applicable for phases {} (continuing evaluation)", phase); } else { LOGGER.trace(" Authorization is not applicable for phase {}", phase); continue; } // object or target ObjectFilter autzObjSecurityFilter = null; List<OwnedObjectSpecificationType> objectSpecTypes; if (object == null) { // object not present. Therefore we are looking for object here objectSpecTypes = autz.getObject(); } else { // object present. Therefore we are looking for target objectSpecTypes = autz.getTarget(); // .. but we need to decide whether this authorization is applicable to the object if (!isApplicableItem(autz, object, null)) { LOGGER.trace(" Authorization is not applicable for object {}", object); } } boolean applicable = true; if (objectSpecTypes != null && !objectSpecTypes.isEmpty()) { applicable = false; for (OwnedObjectSpecificationType objectSpecType : objectSpecTypes) { ObjectFilter objSpecSecurityFilter = null; TypeFilter objSpecTypeFilter = null; SearchFilterType specFilterType = objectSpecType.getFilter(); ObjectReferenceType specOrgRef = objectSpecType.getOrgRef(); QName specTypeQName = objectSpecType.getType(); PrismObjectDefinition<T> objectDefinition = null; // Type if (specTypeQName != null) { specTypeQName = prismContext.getSchemaRegistry().qualifyTypeName(specTypeQName); PrismObjectDefinition<?> specObjectDef = prismContext.getSchemaRegistry() .findObjectDefinitionByType(specTypeQName); Class<?> specObjectClass = specObjectDef.getCompileTimeClass(); if (!objectType.isAssignableFrom(specObjectClass)) { LOGGER.trace( " Authorization not applicable for object because of type mismatch, authorization {}, query {}", new Object[] { specObjectClass, objectType }); continue; } else { LOGGER.trace( " Authorization is applicable for object because of type match, authorization {}, query {}", new Object[] { specObjectClass, objectType }); // The spec type is a subclass of requested type. So it might be returned from the search. // We need to use type filter. objSpecTypeFilter = TypeFilter.createType(specTypeQName, null); // and now we have a more specific object definition to use later in filter processing objectDefinition = (PrismObjectDefinition<T>) specObjectDef; } } // Owner if (objectSpecType.getOwner() != null) { LOGGER.trace( " Authorization not applicable for object because it has owner specification (this is not applicable for search)"); continue; } applicable = true; // Special List<SpecialObjectSpecificationType> specSpecial = objectSpecType.getSpecial(); if (specSpecial != null && !specSpecial.isEmpty()) { if (specFilterType != null || specOrgRef != null) { throw new SchemaException( "Both filter/org and special object specification specified in authorization"); } ObjectFilter specialFilter = null; for (SpecialObjectSpecificationType special : specSpecial) { if (special == SpecialObjectSpecificationType.SELF) { String principalOid = principal.getOid(); specialFilter = ObjectQueryUtil.filterOr(specialFilter, InOidFilter.createInOid(principalOid)); } else { throw new SchemaException( "Unsupported special object specification specified in authorization: " + special); } } objSpecSecurityFilter = specTypeQName != null ? TypeFilter.createType(specTypeQName, specialFilter) : specialFilter; } else { LOGGER.trace(" specials empty: {}", specSpecial); } // Filter if (specFilterType != null) { if (objectDefinition == null) { objectDefinition = prismContext.getSchemaRegistry() .findObjectDefinitionByCompileTimeClass(objectType); } ObjectFilter specFilter = QueryJaxbConvertor.createObjectFilter(objectDefinition, specFilterType, prismContext); if (specFilter != null) { ObjectQueryUtil.assertNotRaw(specFilter, "Filter in authorization object has undefined items. Maybe a 'type' specification is missing in the authorization?"); ObjectQueryUtil.assertPropertyOnly(specFilter, "Filter in authorization object is not property-only filter"); } LOGGER.trace(" applying property filter " + specFilter); objSpecSecurityFilter = ObjectQueryUtil.filterAnd(objSpecSecurityFilter, specFilter); } else { LOGGER.trace(" filter empty"); } // Org if (specOrgRef != null) { OrgFilter orgFilter = OrgFilter.createOrg(specOrgRef.getOid()); objSpecSecurityFilter = ObjectQueryUtil.filterAnd(objSpecSecurityFilter, orgFilter); LOGGER.trace(" applying org filter " + orgFilter); } else { LOGGER.trace(" org empty"); } if (objSpecTypeFilter != null) { objSpecTypeFilter.setFilter(objSpecSecurityFilter); objSpecSecurityFilter = objSpecTypeFilter; } autzObjSecurityFilter = ObjectQueryUtil.filterOr(autzObjSecurityFilter, objSpecSecurityFilter); } } else { LOGGER.trace( " No object specification in authorization (authorization is universaly applicable)"); autzObjSecurityFilter = AllFilter.createAll(); } if (applicable) { // authority is applicable to this situation. now we can process the decision. AuthorizationDecisionType decision = autz.getDecision(); if (decision == null || decision == AuthorizationDecisionType.ALLOW) { // allow if (ObjectQueryUtil.isAll(autzObjSecurityFilter)) { // this is "allow all" authorization. hasAllowAll = true; } else { securityFilterAllow = ObjectQueryUtil.filterOr(securityFilterAllow, autzObjSecurityFilter); } } else { // deny if (ObjectQueryUtil.isAll(autzObjSecurityFilter)) { // This is "deny all". We cannot have anything stronger than that. // There is no point in continuing the evaluation. LOGGER.trace("AUTZ search pre-process: principal={}, operation={}: deny all", new Object[] { principal.getUsername(), operationUrl }); return NoneFilter.createNone(); } securityFilterDeny = ObjectQueryUtil.filterOr(securityFilterDeny, autzObjSecurityFilter); } } } else { LOGGER.warn("Unknown authority type {} in user {}", authority.getClass(), principal.getUsername()); } } } ObjectFilter origWithAllowFilter; if (hasAllowAll) { origWithAllowFilter = origFilter; } else if (securityFilterAllow == null) { // Nothing has been allowed. This means default deny. LOGGER.trace("AUTZ search pre-process: principal={}, operation={}: default deny", new Object[] { principal.getUsername(), operationUrl }); return NoneFilter.createNone(); } else { origWithAllowFilter = ObjectQueryUtil.filterAnd(origFilter, securityFilterAllow); } if (securityFilterDeny == null) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("AUTZ search pre-process: principal={}, operation={}: allow:\n{}", new Object[] { principal.getUsername(), operationUrl, origWithAllowFilter == null ? "null" : origWithAllowFilter.debugDump() }); } return origWithAllowFilter; } else { ObjectFilter secFilter = ObjectQueryUtil.filterAnd(origWithAllowFilter, NotFilter.createNot(securityFilterDeny)); if (LOGGER.isTraceEnabled()) { LOGGER.trace("AUTZ search pre-process: principal={}, operation={}: allow (with deny clauses):\n{}", new Object[] { principal.getUsername(), operationUrl, secFilter == null ? "null" : secFilter.debugDump() }); } return secFilter; } }
From source file:com.evolveum.midpoint.security.enforcer.impl.SecurityEnforcerImpl.java
private <T extends ObjectType, O extends ObjectType> ObjectFilter preProcessObjectFilterInternal( MidPointPrincipal principal, String operationUrl, AuthorizationPhaseType phase, boolean includeNullPhase, Class<T> objectType, PrismObject<O> object, boolean includeSpecial, ObjectFilter origFilter, String limitAuthorizationAction, String desc, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException { Collection<Authorization> authorities = getAuthorities(principal); ObjectFilter securityFilterAllow = null; ObjectFilter securityFilterDeny = null; QueryAutzItemPaths queryItemsSpec = new QueryAutzItemPaths(); queryItemsSpec.addRequiredItems(origFilter); // MID-3916 if (LOGGER.isTraceEnabled()) { LOGGER.trace(" phase={}, initial query items spec {}", phase, queryItemsSpec.shortDump()); }//from ww w . j ava 2 s . c o m boolean hasAllowAll = false; if (authorities != null) { for (GrantedAuthority authority : authorities) { if (authority instanceof Authorization) { Authorization autz = (Authorization) authority; String autzHumanReadableDesc = autz.getHumanReadableDesc(); LOGGER.trace(" Evaluating {}", autzHumanReadableDesc); // action if (!autz.getAction().contains(operationUrl) && !autz.getAction().contains(AuthorizationConstants.AUTZ_ALL_URL)) { LOGGER.trace(" Authorization not applicable for operation {}", operationUrl); continue; } // phase if (autz.getPhase() == phase || (includeNullPhase && autz.getPhase() == null)) { LOGGER.trace(" Authorization is applicable for phases {} (continuing evaluation)", phase); } else { LOGGER.trace(" Authorization is not applicable for phase {}", phase); continue; } if (!isApplicableLimitations(autz, limitAuthorizationAction)) { LOGGER.trace( " Authorization is limited to other action, not applicable for operation {}", operationUrl); continue; } // object or target String objectTargetSpec; ObjectFilter autzObjSecurityFilter = null; List<OwnedObjectSelectorType> objectSpecTypes; if (object == null) { // object not present. Therefore we are looking for object here objectSpecTypes = autz.getObject(); objectTargetSpec = "object"; } else { // object present. Therefore we are looking for target objectSpecTypes = autz.getTarget(); objectTargetSpec = "target"; // .. but we need to decide whether this authorization is applicable to the object if (isApplicable(autz.getObject(), object, principal, null, "object", autzHumanReadableDesc, task, result)) { LOGGER.trace(" Authorization is applicable for object {}", object); } else { LOGGER.trace(" Authorization is not applicable for object {}", object); continue; } } boolean applicable = true; if (objectSpecTypes == null || objectSpecTypes.isEmpty()) { LOGGER.trace( " No {} specification in authorization (authorization is universaly applicable)", objectTargetSpec); autzObjSecurityFilter = AllFilter.createAll(); } else { applicable = false; for (OwnedObjectSelectorType objectSpecType : objectSpecTypes) { ObjectFilter objSpecSecurityFilter = null; TypeFilter objSpecTypeFilter = null; SearchFilterType specFilterType = objectSpecType.getFilter(); ObjectReferenceType specOrgRef = objectSpecType.getOrgRef(); OrgRelationObjectSpecificationType specOrgRelation = objectSpecType.getOrgRelation(); RoleRelationObjectSpecificationType specRoleRelation = objectSpecType.getRoleRelation(); QName specTypeQName = objectSpecType.getType(); PrismObjectDefinition<T> objectDefinition = null; // Type if (specTypeQName != null) { specTypeQName = prismContext.getSchemaRegistry().qualifyTypeName(specTypeQName); PrismObjectDefinition<?> specObjectDef = prismContext.getSchemaRegistry() .findObjectDefinitionByType(specTypeQName); if (specObjectDef == null) { throw new SchemaException("Unknown object type " + specTypeQName + " in " + autzHumanReadableDesc); } Class<?> specObjectClass = specObjectDef.getCompileTimeClass(); if (!objectType.isAssignableFrom(specObjectClass)) { LOGGER.trace( " Authorization not applicable for object because of type mismatch, authorization {}, query {}", new Object[] { specObjectClass, objectType }); continue; } else { LOGGER.trace( " Authorization is applicable for object because of type match, authorization {}, query {}", new Object[] { specObjectClass, objectType }); // The spec type is a subclass of requested type. So it might be returned from the search. // We need to use type filter. objSpecTypeFilter = TypeFilter.createType(specTypeQName, null); // and now we have a more specific object definition to use later in filter processing objectDefinition = (PrismObjectDefinition<T>) specObjectDef; } } // Owner if (objectSpecType.getOwner() != null) { if (objectDefinition == null) { objectDefinition = prismContext.getSchemaRegistry() .findObjectDefinitionByCompileTimeClass(objectType); } // TODO: MID-3899 if (AbstractRoleType.class.isAssignableFrom(objectType)) { objSpecSecurityFilter = applyOwnerFilterOwnerRef( new ItemPath(AbstractRoleType.F_OWNER_REF), objSpecSecurityFilter, principal, objectDefinition); } else if (TaskType.class.isAssignableFrom(objectType)) { objSpecSecurityFilter = applyOwnerFilterOwnerRef( new ItemPath(TaskType.F_OWNER_REF), objSpecSecurityFilter, principal, objectDefinition); } else { LOGGER.trace( " Authorization not applicable for object because it has owner specification (this is not applicable for search)"); continue; } } // // Delegator // if (objectSpecType.getDelegator() != null) { // if (objectDefinition == null) { // objectDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(objectType); // } // // TODO: MID-3899 // if (UserType.class.isAssignableFrom(objectType)) { TODO // objSpecSecurityFilter = applyOwnerFilterOwnerRef(new ItemPath(AbstractRoleType.F_OWNER_REF), objSpecSecurityFilter, principal, objectDefinition); // } else if (TaskType.class.isAssignableFrom(objectType)) { // objSpecSecurityFilter = applyOwnerFilterOwnerRef(new ItemPath(TaskType.F_OWNER_REF), objSpecSecurityFilter, principal, objectDefinition); // } else { // LOGGER.trace(" Authorization not applicable for object because it has owner specification (this is not applicable for search)"); // continue; // } // } applicable = true; // Special List<SpecialObjectSpecificationType> specSpecial = objectSpecType.getSpecial(); if (specSpecial != null && !specSpecial.isEmpty()) { if (!includeSpecial) { LOGGER.trace(" Skipping authorization, because specials are present: {}", specSpecial); applicable = false; } if (specFilterType != null || specOrgRef != null || specOrgRelation != null || specRoleRelation != null) { throw new SchemaException( "Both filter/org/role and special object specification specified in authorization"); } ObjectFilter specialFilter = null; for (SpecialObjectSpecificationType special : specSpecial) { if (special == SpecialObjectSpecificationType.SELF) { String principalOid = principal.getOid(); specialFilter = ObjectQueryUtil.filterOr(specialFilter, InOidFilter.createInOid(principalOid)); } else { throw new SchemaException( "Unsupported special object specification specified in authorization: " + special); } } objSpecSecurityFilter = specTypeQName != null ? TypeFilter.createType(specTypeQName, specialFilter) : specialFilter; } else { LOGGER.trace(" specials empty: {}", specSpecial); } // Filter if (specFilterType != null) { if (objectDefinition == null) { objectDefinition = prismContext.getSchemaRegistry() .findObjectDefinitionByCompileTimeClass(objectType); } ObjectFilter specFilter = parseAndEvaluateFilter(principal, objectDefinition, specFilterType, objectTargetSpec, autzHumanReadableDesc, task, result); if (specFilter != null) { ObjectQueryUtil.assertNotRaw(specFilter, "Filter in authorization object has undefined items. Maybe a 'type' specification is missing in the authorization?"); ObjectQueryUtil.assertPropertyOnly(specFilter, "Filter in authorization object is not property-only filter"); } LOGGER.trace(" applying property filter {}", specFilter); objSpecSecurityFilter = ObjectQueryUtil.filterAnd(objSpecSecurityFilter, specFilter); } else { LOGGER.trace(" filter empty"); } // Org if (specOrgRef != null) { ObjectFilter orgFilter = QueryBuilder.queryFor(ObjectType.class, prismContext) .isChildOf(specOrgRef.getOid()).buildFilter(); objSpecSecurityFilter = ObjectQueryUtil.filterAnd(objSpecSecurityFilter, orgFilter); LOGGER.trace(" applying org filter {}", orgFilter); } else { LOGGER.trace(" org empty"); } // orgRelation if (specOrgRelation != null) { ObjectFilter objSpecOrgRelationFilter = null; QName subjectRelation = specOrgRelation.getSubjectRelation(); for (ObjectReferenceType subjectParentOrgRef : principal.getUser() .getParentOrgRef()) { if (MiscSchemaUtil.compareRelation(subjectRelation, subjectParentOrgRef.getRelation())) { S_FilterEntryOrEmpty q = QueryBuilder.queryFor(ObjectType.class, prismContext); S_AtomicFilterExit q2; if (specOrgRelation.getScope() == null || specOrgRelation.getScope() == OrgScopeType.ALL_DESCENDANTS) { q2 = q.isChildOf(subjectParentOrgRef.getOid()); } else if (specOrgRelation.getScope() == OrgScopeType.DIRECT_DESCENDANTS) { q2 = q.isDirectChildOf(subjectParentOrgRef.getOid()); } else if (specOrgRelation.getScope() == OrgScopeType.ALL_ANCESTORS) { q2 = q.isParentOf(subjectParentOrgRef.getOid()); } else { throw new UnsupportedOperationException( "Unknown orgRelation scope " + specOrgRelation.getScope()); } if (BooleanUtils.isTrue(specOrgRelation.isIncludeReferenceOrg())) { q2 = q2.or().id(subjectParentOrgRef.getOid()); } objSpecOrgRelationFilter = ObjectQueryUtil .filterOr(objSpecOrgRelationFilter, q2.buildFilter()); } } if (objSpecOrgRelationFilter == null) { objSpecOrgRelationFilter = NoneFilter.createNone(); } objSpecSecurityFilter = ObjectQueryUtil.filterAnd(objSpecSecurityFilter, objSpecOrgRelationFilter); LOGGER.trace(" applying orgRelation filter {}", objSpecOrgRelationFilter); } else { LOGGER.trace(" orgRelation empty"); } // roleRelation if (specRoleRelation != null) { ObjectFilter objSpecRoleRelationFilter = processRoleRelationFilter(principal, autz, specRoleRelation, queryItemsSpec, origFilter); if (objSpecRoleRelationFilter == null) { if (autz.maySkipOnSearch()) { LOGGER.trace( " not applying roleRelation filter {} because it is not efficient and maySkipOnSearch is set", objSpecRoleRelationFilter); applicable = false; } else { objSpecRoleRelationFilter = NoneFilter.createNone(); } } if (objSpecRoleRelationFilter != null) { objSpecSecurityFilter = ObjectQueryUtil.filterAnd(objSpecSecurityFilter, objSpecRoleRelationFilter); LOGGER.trace(" applying roleRelation filter {}", objSpecRoleRelationFilter); } } else { LOGGER.trace(" roleRelation empty"); } if (objSpecTypeFilter != null) { objSpecTypeFilter.setFilter(objSpecSecurityFilter); objSpecSecurityFilter = objSpecTypeFilter; } traceFilter("objSpecSecurityFilter", objectSpecType, objSpecSecurityFilter); autzObjSecurityFilter = ObjectQueryUtil.filterOr(autzObjSecurityFilter, objSpecSecurityFilter); } } traceFilter("autzObjSecurityFilter", autz, autzObjSecurityFilter); if (applicable) { autzObjSecurityFilter = ObjectQueryUtil.simplify(autzObjSecurityFilter); // authority is applicable to this situation. now we can process the decision. AuthorizationDecisionType decision = autz.getDecision(); if (decision == null || decision == AuthorizationDecisionType.ALLOW) { // allow if (ObjectQueryUtil.isAll(autzObjSecurityFilter)) { // this is "allow all" authorization. hasAllowAll = true; } else { securityFilterAllow = ObjectQueryUtil.filterOr(securityFilterAllow, autzObjSecurityFilter); } if (!ObjectQueryUtil.isNone(autzObjSecurityFilter)) { queryItemsSpec.collectItems(autz); } } else { // deny if (autz.hasItemSpecification()) { // This is a tricky situation. We have deny authorization, but it only denies access to // some items. Therefore we need to find the objects and then filter out the items. // Therefore do not add this authorization into the filter. } else { if (ObjectQueryUtil.isAll(autzObjSecurityFilter)) { // This is "deny all". We cannot have anything stronger than that. // There is no point in continuing the evaluation. if (LOGGER.isTraceEnabled()) { LOGGER.trace("AUTZ {} done: principal={}, operation={}, phase={}: deny all", desc, getUsername(principal), prettyActionUrl(operationUrl), phase); } NoneFilter secFilter = NoneFilter.createNone(); traceFilter("secFilter", null, secFilter); return secFilter; } securityFilterDeny = ObjectQueryUtil.filterOr(securityFilterDeny, autzObjSecurityFilter); } } } traceFilter("securityFilterAllow", autz, securityFilterAllow); traceFilter("securityFilterDeny", autz, securityFilterDeny); } else { LOGGER.warn("Unknown authority type {} in user {}", authority.getClass(), getUsername(principal)); } } } traceFilter("securityFilterAllow", null, securityFilterAllow); traceFilter("securityFilterDeny", null, securityFilterDeny); if (LOGGER.isTraceEnabled()) { LOGGER.trace(" Final items: {}", queryItemsSpec.shortDump()); } List<ItemPath> unsatisfiedItems = queryItemsSpec.evaluateUnsatisfierItems(); if (!unsatisfiedItems.isEmpty()) { if (LOGGER.isTraceEnabled()) { LOGGER.trace( "AUTZ {} done: principal={}, operation={}, phase={}: deny because items {} are not allowed", desc, getUsername(principal), prettyActionUrl(operationUrl), phase, unsatisfiedItems); } NoneFilter secFilter = NoneFilter.createNone(); traceFilter("secFilter", null, secFilter); return secFilter; } ObjectFilter origWithAllowFilter; if (hasAllowAll) { origWithAllowFilter = origFilter; } else if (securityFilterAllow == null) { // Nothing has been allowed. This means default deny. if (LOGGER.isTraceEnabled()) { LOGGER.trace("AUTZ {} done: principal={}, operation={}, phase={}: default deny", desc, getUsername(principal), prettyActionUrl(operationUrl), phase); } NoneFilter secFilter = NoneFilter.createNone(); traceFilter("secFilter", null, secFilter); return secFilter; } else { origWithAllowFilter = ObjectQueryUtil.filterAnd(origFilter, securityFilterAllow); } if (securityFilterDeny == null) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("AUTZ {} done: principal={}, operation={}, phase={}: allow\n Filter:\n{}", desc, getUsername(principal), prettyActionUrl(operationUrl), phase, origWithAllowFilter == null ? "null" : origWithAllowFilter.debugDump(2)); } traceFilter("origWithAllowFilter", null, origWithAllowFilter); return origWithAllowFilter; } else { ObjectFilter secFilter = ObjectQueryUtil.filterAnd(origWithAllowFilter, NotFilter.createNot(securityFilterDeny)); if (LOGGER.isTraceEnabled()) { LOGGER.trace( "AUTZ {} done: principal={}, operation={}, phase={}: allow (with deny clauses)\n Filter:\n{}", desc, getUsername(principal), prettyActionUrl(operationUrl), phase, secFilter == null ? "null" : secFilter.debugDump(2)); } traceFilter("secFilter", null, secFilter); return secFilter; } }