use of com.evolveum.midpoint.repo.api.query.ObjectFilterExpressionEvaluator in project midpoint by Evolveum.
the class SecurityEnforcerImpl method parseAndEvaluateFilter.
private <O extends ObjectType> ObjectFilter parseAndEvaluateFilter(MidPointPrincipal principal, PrismObjectDefinition<O> objectDefinition, SearchFilterType specFilterType, String objectTargetDesc, String autzHumanReadableDesc, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException {
ObjectFilter specFilter = prismContext.getQueryConverter().createObjectFilter(objectDefinition, specFilterType);
if (specFilter == null) {
return null;
}
ObjectFilterExpressionEvaluator filterEvaluator = createFilterEvaluator(principal, objectTargetDesc, autzHumanReadableDesc, task, result);
return filterEvaluator.evaluate(specFilter);
}
use of com.evolveum.midpoint.repo.api.query.ObjectFilterExpressionEvaluator in project midpoint by Evolveum.
the class SecurityEnforcerImpl method isApplicable.
/**
* @param otherSelfOids Which OIDs should match "self" in addition to the current principal OID. Usually these could be
* some or all of delegators' OIDs, i.e. people that delegated privileges to the current principal.
* The reason is that if we want to match assignee or requestor (probably targetObject and owner as well)
* we want to give appropriate privileges also to assignee/requestor delegates.
*/
private <O extends ObjectType> boolean isApplicable(SubjectedObjectSelectorType objectSelector, PrismObject<O> object, MidPointPrincipal principal, Collection<String> otherSelfOids, OwnerResolver ownerResolver, String desc, String autzHumanReadableDesc, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException {
ObjectFilterExpressionEvaluator filterExpressionEvaluator = createFilterEvaluator(principal, desc, autzHumanReadableDesc, task, result);
if (!repositoryService.selectorMatches(objectSelector, object, filterExpressionEvaluator, LOGGER, " " + autzHumanReadableDesc + " not applicable for " + desc + " because of")) {
// No need to log inapplicability here. It should be logged inside repositoryService.selectorMatches()
return false;
}
OrgRelationObjectSpecificationType specOrgRelation = objectSelector.getOrgRelation();
RoleRelationObjectSpecificationType specRoleRelation = objectSelector.getRoleRelation();
// Special
List<SpecialObjectSpecificationType> specSpecial = objectSelector.getSpecial();
if (specSpecial != null && !specSpecial.isEmpty()) {
if (objectSelector.getFilter() != null || objectSelector.getOrgRef() != null || specOrgRelation != null || specRoleRelation != null) {
throw new SchemaException("Both filter/org/role/archetype and special " + desc + " specification specified in " + autzHumanReadableDesc);
}
for (SpecialObjectSpecificationType special : specSpecial) {
if (special == SpecialObjectSpecificationType.SELF) {
String principalOid = principal != null ? principal.getOid() : null;
if (principalOid == null) {
// This is a rare case. It should not normally happen. But it may happen in tests
// or during initial import. Therefore we are not going to die here. Just ignore it.
} else {
if (principalOid.equals(object.getOid())) {
LOGGER.trace(" {}: 'self' authorization applicable for {} - match on principal OID ({})", autzHumanReadableDesc, desc, principalOid);
return true;
} else if (otherSelfOids != null && otherSelfOids.contains(object.getOid())) {
LOGGER.trace(" {}: 'self' authorization applicable for {} - match on other 'self OID' ({})", autzHumanReadableDesc, desc, object.getOid());
return true;
} else {
LOGGER.trace(" {}: 'self' authorization not applicable for {}, principal OID: {} (other accepted self OIDs: {}), {} OID {}", autzHumanReadableDesc, desc, principalOid, otherSelfOids, desc, object.getOid());
}
}
} else {
throw new SchemaException("Unsupported special " + desc + " specification specified in " + autzHumanReadableDesc + ": " + special);
}
}
LOGGER.trace(" {}: special authorization not applicable for {}", autzHumanReadableDesc, desc);
return false;
} else {
LOGGER.trace(" {}: specials empty: {}", autzHumanReadableDesc, specSpecial);
}
// orgRelation
if (specOrgRelation != null) {
boolean match = false;
for (ObjectReferenceType subjectParentOrgRef : principal.getFocus().getParentOrgRef()) {
if (matchesOrgRelation(object, subjectParentOrgRef, specOrgRelation, autzHumanReadableDesc, desc)) {
LOGGER.trace(" org {} applicable for {}, object OID {} because subject org {} matches", autzHumanReadableDesc, desc, object.getOid(), subjectParentOrgRef.getOid());
match = true;
break;
}
}
if (!match) {
LOGGER.trace(" org {} not applicable for {}, object OID {} because none of the subject orgs matches", autzHumanReadableDesc, desc, object.getOid());
return false;
}
}
// roleRelation
if (specRoleRelation != null) {
boolean match = false;
for (ObjectReferenceType subjectRoleMembershipRef : principal.getFocus().getRoleMembershipRef()) {
if (matchesRoleRelation(object, subjectRoleMembershipRef, specRoleRelation)) {
LOGGER.trace(" {} applicable for {}, object OID {} because subject role relation {} matches", autzHumanReadableDesc, desc, object.getOid(), subjectRoleMembershipRef.getOid());
match = true;
break;
}
}
if (!match) {
LOGGER.trace(" {} not applicable for {}, object OID {} because none of the subject roles matches", autzHumanReadableDesc, desc, object.getOid());
return false;
}
}
if (objectSelector instanceof OwnedObjectSelectorType) {
OwnedObjectSelectorType ownedObjectSelector = (OwnedObjectSelectorType) objectSelector;
// Owner
SubjectedObjectSelectorType ownerSpec = ownedObjectSelector.getOwner();
if (ownerSpec != null) {
if (ownerResolver == null) {
ownerResolver = securityContextManager.getUserProfileService();
if (ownerResolver == null) {
LOGGER.trace(" {}: owner object spec not applicable for {}, object OID {} because there is no owner resolver", autzHumanReadableDesc, desc, object.getOid());
return false;
}
}
PrismObject<? extends FocusType> owner = ownerResolver.resolveOwner(object);
if (owner == null) {
LOGGER.trace(" {}: owner object spec not applicable for {}, object OID {} because it has no owner", autzHumanReadableDesc, desc, object.getOid());
return false;
}
boolean ownerApplicable = isApplicable(ownerSpec, owner, principal, emptySet(), ownerResolver, "owner of " + desc, autzHumanReadableDesc, task, result);
if (!ownerApplicable) {
LOGGER.trace(" {}: owner object spec not applicable for {}, object OID {} because owner does not match (owner={})", autzHumanReadableDesc, desc, object.getOid(), owner);
return false;
}
}
// Delegator
SubjectedObjectSelectorType delegatorSpec = ownedObjectSelector.getDelegator();
if (delegatorSpec != null) {
if (!isSelf(delegatorSpec)) {
throw new SchemaException("Unsupported non-self delegator clause");
}
if (!object.canRepresent(UserType.class)) {
LOGGER.trace(" {}: delegator object spec not applicable for {}, because the object is not user", autzHumanReadableDesc, desc);
return false;
}
boolean found = false;
for (ObjectReferenceType objectDelegatedRef : ((UserType) object.asObjectable()).getDelegatedRef()) {
if (principal.getOid().equals(objectDelegatedRef.getOid())) {
found = true;
break;
}
}
if (!found) {
if (BooleanUtils.isTrue(delegatorSpec.isAllowInactive())) {
for (AssignmentType objectAssignment : ((UserType) object.asObjectable()).getAssignment()) {
ObjectReferenceType objectAssignmentTargetRef = objectAssignment.getTargetRef();
if (objectAssignmentTargetRef == null) {
continue;
}
if (principal.getOid().equals(objectAssignmentTargetRef.getOid())) {
if (relationRegistry.isDelegation(objectAssignmentTargetRef.getRelation())) {
found = true;
break;
}
}
}
}
if (!found) {
LOGGER.trace(" {}: delegator object spec not applicable for {}, object OID {} because delegator does not match", autzHumanReadableDesc, desc, object.getOid());
return false;
}
}
}
// Requestor
SubjectedObjectSelectorType requestorSpec = ownedObjectSelector.getRequester();
if (requestorSpec != null) {
PrismObject<? extends ObjectType> requestor = getRequestor(object, result);
if (requestor == null) {
LOGGER.trace(" {}: requester object spec not applicable for {}, object OID {} because it has no requestor", autzHumanReadableDesc, desc, object.getOid());
return false;
}
boolean requestorApplicable = isApplicable(requestorSpec, requestor, principal, getDelegatorsForRequestor(principal), ownerResolver, "requestor of " + desc, autzHumanReadableDesc, task, result);
if (!requestorApplicable) {
LOGGER.trace(" {}: requester object spec not applicable for {}, object OID {} because requestor does not match (requestor={})", autzHumanReadableDesc, desc, object.getOid(), requestor);
return false;
}
}
// Requestor
SubjectedObjectSelectorType relatedObjectSpec = ownedObjectSelector.getRelatedObject();
if (relatedObjectSpec != null) {
PrismObject<? extends ObjectType> relatedObject = getRelatedObject(object, result);
if (relatedObject == null) {
LOGGER.trace(" {}: related object spec not applicable for {}, object OID {} because it has no related object", autzHumanReadableDesc, desc, object.getOid());
return false;
}
boolean relatedObjectApplicable = isApplicable(relatedObjectSpec, relatedObject, principal, getDelegatorsForRelatedObjects(principal), ownerResolver, "related object of " + desc, autzHumanReadableDesc, task, result);
if (!relatedObjectApplicable) {
LOGGER.trace(" {}: related object spec not applicable for {}, object OID {} because related object does not match (related object={})", autzHumanReadableDesc, desc, object.getOid(), relatedObject);
return false;
}
}
// Assignee
SubjectedObjectSelectorType assigneeSpec = ownedObjectSelector.getAssignee();
if (assigneeSpec != null) {
List<PrismObject<? extends ObjectType>> assignees = getAssignees(object, result);
if (assignees.isEmpty()) {
LOGGER.trace(" {}: assignee spec not applicable for {}, object OID {} because it has no assignees", autzHumanReadableDesc, desc, object.getOid());
return false;
}
Collection<String> relevantDelegators = getDelegatorsForAssignee(principal);
boolean assigneeApplicable = false;
for (PrismObject<? extends ObjectType> assignee : assignees) {
if (isApplicable(assigneeSpec, assignee, principal, relevantDelegators, ownerResolver, "assignee of " + desc, autzHumanReadableDesc, task, result)) {
assigneeApplicable = true;
break;
}
}
if (!assigneeApplicable) {
LOGGER.trace(" {}: assignee spec not applicable for {}, object OID {} because none of the assignees match (assignees={})", autzHumanReadableDesc, desc, object.getOid(), assignees);
return false;
}
}
// Tenant
TenantSelectorType tenantSpec = ownedObjectSelector.getTenant();
if (tenantSpec != null) {
if (BooleanUtils.isTrue(tenantSpec.isSameAsSubject())) {
ObjectReferenceType subjectTenantRef = principal.getFocus().getTenantRef();
if (subjectTenantRef == null || subjectTenantRef.getOid() == null) {
LOGGER.trace(" {}: tenant object spec not applicable for {}, object OID {} because subject does not have tenantRef", autzHumanReadableDesc, desc, object.getOid());
return false;
}
ObjectReferenceType objectTenantRef = object.asObjectable().getTenantRef();
if (objectTenantRef == null || objectTenantRef.getOid() == null) {
LOGGER.trace(" {}: tenant object spec not applicable for {}, object OID {} because object does not have tenantRef", autzHumanReadableDesc, desc, object.getOid());
return false;
}
if (!subjectTenantRef.getOid().equals(objectTenantRef.getOid())) {
LOGGER.trace(" {}: tenant object spec not applicable for {}, object OID {} because of tenant mismatch", autzHumanReadableDesc, desc, object.getOid());
return false;
}
if (!BooleanUtils.isTrue(tenantSpec.isIncludeTenantOrg())) {
O objectType = object.asObjectable();
if (objectType instanceof OrgType) {
if (BooleanUtils.isTrue(((OrgType) objectType).isTenant())) {
LOGGER.trace(" {}: tenant object spec not applicable for {}, object OID {} because it is a tenant org and it is not included", autzHumanReadableDesc, desc, object.getOid());
return false;
}
}
}
} else {
LOGGER.trace(" {}: tenant object spec not applicable for {}, object OID {} because there is a strange tenant specificaiton in authorization", autzHumanReadableDesc, desc, object.getOid());
return false;
}
}
}
LOGGER.trace(" {} applicable for {} (filter)", autzHumanReadableDesc, desc);
return true;
}
Aggregations