Search in sources :

Example 1 with Expression

use of com.yahoo.elide.core.security.permissions.expressions.Expression in project elide by yahoo.

the class PermissionExpressionBuilder method buildAnyFieldFilterExpression.

/**
 * Build an expression representing any field on an entity.
 *
 * @param forType   Resource class
 * @param requestScope requestScope
 * @return Expressions
 */
public FilterExpression buildAnyFieldFilterExpression(Type<?> forType, RequestScope requestScope, Set<String> requestedFields) {
    Class<? extends Annotation> annotationClass = ReadPermission.class;
    ParseTree classPermissions = entityDictionary.getPermissionsForClass(forType, annotationClass);
    FilterExpression entityFilter = filterExpressionFromParseTree(classPermissions, forType, requestScope);
    // case where the permissions does not have ANY filterExpressionCheck
    if (entityFilter == FALSE_USER_CHECK_EXPRESSION || entityFilter == NO_EVALUATION_EXPRESSION || entityFilter == TRUE_USER_CHECK_EXPRESSION) {
        entityFilter = null;
    }
    FilterExpression allFieldsFilterExpression = entityFilter;
    List<String> fields = entityDictionary.getAllExposedFields(forType).stream().filter(field -> requestedFields == null || requestedFields.contains(field)).collect(Collectors.toList());
    for (String field : fields) {
        ParseTree fieldPermissions = entityDictionary.getPermissionsForField(forType, field, annotationClass);
        FilterExpression fieldExpression = filterExpressionFromParseTree(fieldPermissions, forType, requestScope);
        if (fieldExpression == null && entityFilter == null) {
            // this field will be visible across all instances
            return null;
        }
        if (fieldExpression == null || fieldExpression == FALSE_USER_CHECK_EXPRESSION) {
            // In either case this field is not useful for filtering when loading records
            continue;
        }
        if (fieldExpression == NO_EVALUATION_EXPRESSION || fieldExpression == TRUE_USER_CHECK_EXPRESSION) {
            // When the expression is TRUE_USER_CHECK_EXPRESSION all records can be loaded
            return null;
        }
        if (allFieldsFilterExpression != null) {
            allFieldsFilterExpression = new OrFilterExpression(allFieldsFilterExpression, fieldExpression);
        } else {
            allFieldsFilterExpression = fieldExpression;
        }
    }
    return allFieldsFilterExpression;
}
Also used : CheckExpression(com.yahoo.elide.core.security.permissions.expressions.CheckExpression) PermissionExpressionNormalizationVisitor(com.yahoo.elide.core.security.visitors.PermissionExpressionNormalizationVisitor) OrExpression(com.yahoo.elide.core.security.permissions.expressions.OrExpression) Function(java.util.function.Function) FAILURE(com.yahoo.elide.core.security.permissions.expressions.Expression.Results.FAILURE) OrFilterExpression(com.yahoo.elide.core.filter.expression.OrFilterExpression) SpecificFieldExpression(com.yahoo.elide.core.security.permissions.expressions.SpecificFieldExpression) PersistentResource(com.yahoo.elide.core.PersistentResource) PermissionExpressionVisitor(com.yahoo.elide.core.security.visitors.PermissionExpressionVisitor) ParseTree(org.antlr.v4.runtime.tree.ParseTree) NO_EVALUATION_EXPRESSION(com.yahoo.elide.core.security.visitors.PermissionToFilterExpressionVisitor.NO_EVALUATION_EXPRESSION) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) RequestScope(com.yahoo.elide.core.RequestScope) ChangeSpec(com.yahoo.elide.core.security.ChangeSpec) Check(com.yahoo.elide.core.security.checks.Check) PermissionToFilterExpressionVisitor(com.yahoo.elide.core.security.visitors.PermissionToFilterExpressionVisitor) AndExpression(com.yahoo.elide.core.security.permissions.expressions.AndExpression) AnyFieldExpression(com.yahoo.elide.core.security.permissions.expressions.AnyFieldExpression) Set(java.util.Set) Collectors(java.util.stream.Collectors) EntityDictionary(com.yahoo.elide.core.dictionary.EntityDictionary) Expression(com.yahoo.elide.core.security.permissions.expressions.Expression) List(java.util.List) ReadPermission(com.yahoo.elide.annotation.ReadPermission) Type(com.yahoo.elide.core.type.Type) Annotation(java.lang.annotation.Annotation) FALSE_USER_CHECK_EXPRESSION(com.yahoo.elide.core.security.visitors.PermissionToFilterExpressionVisitor.FALSE_USER_CHECK_EXPRESSION) TRUE_USER_CHECK_EXPRESSION(com.yahoo.elide.core.security.visitors.PermissionToFilterExpressionVisitor.TRUE_USER_CHECK_EXPRESSION) OrFilterExpression(com.yahoo.elide.core.filter.expression.OrFilterExpression) ReadPermission(com.yahoo.elide.annotation.ReadPermission) OrFilterExpression(com.yahoo.elide.core.filter.expression.OrFilterExpression) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) ParseTree(org.antlr.v4.runtime.tree.ParseTree)

Example 2 with Expression

use of com.yahoo.elide.core.security.permissions.expressions.Expression in project elide by yahoo.

the class PermissionExpressionBuilder method buildAnyFieldExpression.

/**
 * Build an expression representing any field on an entity.
 *
 * @param condition       The condition which triggered this permission expression check
 * @param checkFn         check function
 * @param scope           RequestScope
 * @param requestedFields The list of requested fields
 * @return Expressions
 */
private Expression buildAnyFieldExpression(final PermissionCondition condition, final Function<Check, Expression> checkFn, final Set<String> requestedFields, final RequestScope scope) {
    Type<?> resourceClass = condition.getEntityClass();
    Class<? extends Annotation> annotationClass = condition.getPermission();
    ParseTree classPermissions = entityDictionary.getPermissionsForClass(resourceClass, annotationClass);
    Expression entityExpression = normalizedExpressionFromParseTree(classPermissions, checkFn);
    OrExpression allFieldsExpression = new OrExpression(FAILURE, null);
    List<String> fields = entityDictionary.getAllExposedFields(resourceClass);
    boolean entityExpressionUsed = false;
    boolean fieldExpressionUsed = false;
    for (String field : fields) {
        if (requestedFields != null && !requestedFields.contains(field)) {
            continue;
        }
        ParseTree fieldPermissions = entityDictionary.getPermissionsForField(resourceClass, field, annotationClass);
        Expression fieldExpression = normalizedExpressionFromParseTree(fieldPermissions, checkFn);
        if (fieldExpression == null) {
            if (entityExpressionUsed) {
                continue;
            }
            if (entityExpression == null) {
                // One field had no permissions set - so we allow the action.
                return SUCCESSFUL_EXPRESSION;
            }
            fieldExpression = entityExpression;
            entityExpressionUsed = true;
        } else {
            fieldExpressionUsed = true;
        }
        allFieldsExpression = new OrExpression(allFieldsExpression, fieldExpression);
    }
    if (!fieldExpressionUsed) {
        // If there are no permissions, allow access...
        if (entityExpression == null) {
            return SUCCESSFUL_EXPRESSION;
        }
        return new AnyFieldExpression(condition, entityExpression);
    }
    return new AnyFieldExpression(condition, allFieldsExpression);
}
Also used : AnyFieldExpression(com.yahoo.elide.core.security.permissions.expressions.AnyFieldExpression) CheckExpression(com.yahoo.elide.core.security.permissions.expressions.CheckExpression) OrExpression(com.yahoo.elide.core.security.permissions.expressions.OrExpression) OrFilterExpression(com.yahoo.elide.core.filter.expression.OrFilterExpression) SpecificFieldExpression(com.yahoo.elide.core.security.permissions.expressions.SpecificFieldExpression) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) AndExpression(com.yahoo.elide.core.security.permissions.expressions.AndExpression) AnyFieldExpression(com.yahoo.elide.core.security.permissions.expressions.AnyFieldExpression) Expression(com.yahoo.elide.core.security.permissions.expressions.Expression) OrExpression(com.yahoo.elide.core.security.permissions.expressions.OrExpression) ParseTree(org.antlr.v4.runtime.tree.ParseTree)

Example 3 with Expression

use of com.yahoo.elide.core.security.permissions.expressions.Expression in project elide by yahoo.

the class ActivePermissionExecutor method checkPermissions.

/**
 * First attempts to check user permissions (by looking in the cache and if not present by executing user
 * permissions).  If user permissions don't short circuit the check, run the provided expression executor.
 *
 * @param <A> type parameter
 * @param resourceClass Resource class
 * @param annotationClass Annotation class
 * @param fields Set of all field names that is being accessed
 * @param expressionSupplier Builds a permission expression.
 * @param expressionExecutor Evaluates the expression (post user check evaluation)
 */
protected <A extends Annotation> ExpressionResult checkPermissions(Type<?> resourceClass, Class<A> annotationClass, Set<String> fields, Supplier<Expression> expressionSupplier, Optional<Function<Expression, ExpressionResult>> expressionExecutor) {
    // If the user check has already been evaluated before, return the result directly and save the building cost
    ImmutableSet<String> immutableFields = fields == null ? null : ImmutableSet.copyOf(fields);
    ExpressionResult expressionResult = userPermissionCheckCache.get(Triple.of(annotationClass, resourceClass, immutableFields));
    if (expressionResult == PASS) {
        return expressionResult;
    }
    Expression expression = expressionSupplier.get();
    if (expressionResult == null) {
        expressionResult = executeExpressions(expression, annotationClass, Expression.EvaluationMode.USER_CHECKS_ONLY);
        userPermissionCheckCache.put(Triple.of(annotationClass, resourceClass, immutableFields), expressionResult);
        if (expressionResult == PASS) {
            return expressionResult;
        }
    }
    return expressionExecutor.map(executor -> executor.apply(expression)).orElse(expressionResult);
}
Also used : PASS(com.yahoo.elide.core.security.permissions.ExpressionResult.PASS) Getter(lombok.Getter) HashMap(java.util.HashMap) DEFERRED(com.yahoo.elide.core.security.permissions.ExpressionResult.DEFERRED) PermissionExecutor(com.yahoo.elide.core.security.PermissionExecutor) Function(java.util.function.Function) Supplier(java.util.function.Supplier) UpdatePermission(com.yahoo.elide.annotation.UpdatePermission) DeletePermission(com.yahoo.elide.annotation.DeletePermission) PermissionExpressionBuilder(com.yahoo.elide.core.security.permissions.PermissionExpressionBuilder) Map(java.util.Map) PersistentResource(com.yahoo.elide.core.PersistentResource) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) Triple(org.apache.commons.lang3.tuple.Triple) RequestScope(com.yahoo.elide.core.RequestScope) ChangeSpec(com.yahoo.elide.core.security.ChangeSpec) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) Expression(com.yahoo.elide.core.security.permissions.expressions.Expression) ForbiddenAccessException(com.yahoo.elide.core.exceptions.ForbiddenAccessException) ExpressionResult(com.yahoo.elide.core.security.permissions.ExpressionResult) Slf4j(lombok.extern.slf4j.Slf4j) ReadPermission(com.yahoo.elide.annotation.ReadPermission) ExpressionResultCache(com.yahoo.elide.core.security.permissions.ExpressionResultCache) CreatePermission(com.yahoo.elide.annotation.CreatePermission) Type(com.yahoo.elide.core.type.Type) Annotation(java.lang.annotation.Annotation) Optional(java.util.Optional) Queue(java.util.Queue) AllArgsConstructor(lombok.AllArgsConstructor) Collections(java.util.Collections) FAIL(com.yahoo.elide.core.security.permissions.ExpressionResult.FAIL) NonTransferable(com.yahoo.elide.annotation.NonTransferable) ExpressionResult(com.yahoo.elide.core.security.permissions.ExpressionResult) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) Expression(com.yahoo.elide.core.security.permissions.expressions.Expression)

Example 4 with Expression

use of com.yahoo.elide.core.security.permissions.expressions.Expression in project elide by yahoo.

the class ActivePermissionExecutor method executeCommitChecks.

/**
 * Execute commmit checks.
 */
@Override
public void executeCommitChecks() {
    commitCheckQueue.forEach((expr) -> {
        Expression expression = expr.getExpression();
        ExpressionResult result = expression.evaluate(Expression.EvaluationMode.ALL_CHECKS);
        if (result == FAIL) {
            ForbiddenAccessException e = new ForbiddenAccessException(expr.getAnnotationClass(), expression, Expression.EvaluationMode.ALL_CHECKS);
            if (log.isTraceEnabled()) {
                log.trace("{}", e.getLoggedMessage());
            }
            throw e;
        }
    });
    commitCheckQueue.clear();
}
Also used : FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) Expression(com.yahoo.elide.core.security.permissions.expressions.Expression) ExpressionResult(com.yahoo.elide.core.security.permissions.ExpressionResult) ForbiddenAccessException(com.yahoo.elide.core.exceptions.ForbiddenAccessException)

Example 5 with Expression

use of com.yahoo.elide.core.security.permissions.expressions.Expression in project elide by yahoo.

the class PermissionExpressionNormalizationVisitorTest method orExpressionTest.

@Test
public void orExpressionTest() {
    ParseTree tree;
    Expression normalizedExpression;
    tree = EntityPermissions.parseExpression("not (sampleCommit or sampleOperation)");
    normalizedExpression = tree.accept(permissionExpressionVisitor).accept(normalizationVisitor);
    Assertions.assertEquals("(NOT ((sampleCommit \u001B[34mWAS UNEVALUATED\u001B[m))) AND " + "(NOT ((sampleOperation \u001B[34mWAS UNEVALUATED\u001B[m)))", normalizedExpression.toString());
    tree = EntityPermissions.parseExpression("not (Prefab.Role.All or sampleCommit or initCheck)");
    normalizedExpression = tree.accept(permissionExpressionVisitor).accept(normalizationVisitor);
    Assertions.assertEquals("((NOT ((Prefab.Role.All \u001B[34mWAS UNEVALUATED\u001B[m))) AND " + "(NOT ((sampleCommit \u001B[34mWAS UNEVALUATED\u001B[m)))) AND " + "(NOT ((initCheck \u001B[34mWAS UNEVALUATED\u001B[m)))", normalizedExpression.toString());
    tree = EntityPermissions.parseExpression("not (parentInitCheck or passingOp) or (FailOp or shouldCache)");
    normalizedExpression = tree.accept(permissionExpressionVisitor).accept(normalizationVisitor);
    Assertions.assertEquals("((NOT ((parentInitCheck \u001B[34mWAS UNEVALUATED\u001B[m))) AND (NOT ((passingOp \u001B[34mWAS UNEVALUATED\u001B[m)))) OR " + "(((FailOp \u001B[34mWAS UNEVALUATED\u001B[m)) OR ((shouldCache \u001B[34mWAS UNEVALUATED\u001B[m)))", normalizedExpression.toString());
    tree = EntityPermissions.parseExpression("not (parentInitCheck or passingOp) or not (FailOp or shouldCache)");
    normalizedExpression = tree.accept(permissionExpressionVisitor).accept(normalizationVisitor);
    Assertions.assertEquals("((NOT ((parentInitCheck \u001B[34mWAS UNEVALUATED\u001B[m))) AND (NOT ((passingOp \u001B[34mWAS UNEVALUATED\u001B[m)))) OR " + "((NOT ((FailOp \u001B[34mWAS UNEVALUATED\u001B[m))) AND (NOT ((shouldCache \u001B[34mWAS UNEVALUATED\u001B[m))))", normalizedExpression.toString());
    tree = EntityPermissions.parseExpression("not (not (parentInitCheck or passingOp) or not (FailOp or shouldCache))");
    normalizedExpression = tree.accept(permissionExpressionVisitor).accept(normalizationVisitor);
    Assertions.assertEquals("(((parentInitCheck \u001B[34mWAS UNEVALUATED\u001B[m)) OR ((passingOp \u001B[34mWAS UNEVALUATED\u001B[m))) AND " + "(((FailOp \u001B[34mWAS UNEVALUATED\u001B[m)) OR ((shouldCache \u001B[34mWAS UNEVALUATED\u001B[m)))", normalizedExpression.toString());
}
Also used : CheckExpression(com.yahoo.elide.core.security.permissions.expressions.CheckExpression) Expression(com.yahoo.elide.core.security.permissions.expressions.Expression) ParseTree(org.antlr.v4.runtime.tree.ParseTree) Test(org.junit.jupiter.api.Test)

Aggregations

Expression (com.yahoo.elide.core.security.permissions.expressions.Expression)24 Test (org.junit.jupiter.api.Test)12 CheckExpression (com.yahoo.elide.core.security.permissions.expressions.CheckExpression)11 AndExpression (com.yahoo.elide.core.security.permissions.expressions.AndExpression)8 OrExpression (com.yahoo.elide.core.security.permissions.expressions.OrExpression)8 ParseTree (org.antlr.v4.runtime.tree.ParseTree)8 FilterExpression (com.yahoo.elide.core.filter.expression.FilterExpression)7 ReadPermission (com.yahoo.elide.annotation.ReadPermission)5 PersistentResource (com.yahoo.elide.core.PersistentResource)5 RequestScope (com.yahoo.elide.core.RequestScope)5 OrFilterExpression (com.yahoo.elide.core.filter.expression.OrFilterExpression)5 ChangeSpec (com.yahoo.elide.core.security.ChangeSpec)5 Type (com.yahoo.elide.core.type.Type)5 Function (java.util.function.Function)5 ForbiddenAccessException (com.yahoo.elide.core.exceptions.ForbiddenAccessException)4 ExpressionResult (com.yahoo.elide.core.security.permissions.ExpressionResult)4 AnyFieldExpression (com.yahoo.elide.core.security.permissions.expressions.AnyFieldExpression)4 SpecificFieldExpression (com.yahoo.elide.core.security.permissions.expressions.SpecificFieldExpression)4 Annotation (java.lang.annotation.Annotation)4 Set (java.util.Set)4