Search in sources :

Example 1 with ForbiddenAccessException

use of com.yahoo.elide.core.exceptions.ForbiddenAccessException in project elide by yahoo.

the class VerifyFieldAccessFilterExpressionVisitor method visitPredicate.

/**
 * Enforce ReadPermission on provided query filter.
 *
 * @return true if allowed, false if rejected
 */
@Override
public Boolean visitPredicate(FilterPredicate filterPredicate) {
    RequestScope requestScope = resource.getRequestScope();
    Set<PersistentResource> val = Collections.singleton(resource);
    PermissionExecutor permissionExecutor = requestScope.getPermissionExecutor();
    ExpressionResult result = permissionExecutor.evaluateFilterJoinUserChecks(resource, filterPredicate);
    if (result == ExpressionResult.UNEVALUATED) {
        result = evaluateUserChecks(filterPredicate, permissionExecutor);
    }
    if (result == ExpressionResult.PASS) {
        return true;
    }
    if (result == ExpressionResult.FAIL) {
        return false;
    }
    for (PathElement element : filterPredicate.getPath().getPathElements()) {
        String fieldName = element.getFieldName();
        if ("this".equals(fieldName)) {
            continue;
        }
        try {
            val = val.stream().filter(Objects::nonNull).flatMap(x -> getValueChecked(x, fieldName, requestScope).toList(LinkedHashSet::new).blockingGet().stream()).filter(Objects::nonNull).collect(Collectors.toSet());
        } catch (ForbiddenAccessException e) {
            result = permissionExecutor.handleFilterJoinReject(filterPredicate, element, e);
            if (result == ExpressionResult.DEFERRED) {
                continue;
            }
            // pass or fail
            return result == ExpressionResult.PASS;
        }
    }
    return true;
}
Also used : FilterExpressionVisitor(com.yahoo.elide.core.filter.expression.FilterExpressionVisitor) FilterPredicate(com.yahoo.elide.core.filter.predicates.FilterPredicate) NotFilterExpression(com.yahoo.elide.core.filter.expression.NotFilterExpression) Set(java.util.Set) EntityProjection(com.yahoo.elide.core.request.EntityProjection) PermissionExecutor(com.yahoo.elide.core.security.PermissionExecutor) Collectors(java.util.stream.Collectors) EntityDictionary(com.yahoo.elide.core.dictionary.EntityDictionary) Objects(java.util.Objects) ForbiddenAccessException(com.yahoo.elide.core.exceptions.ForbiddenAccessException) ExpressionResult(com.yahoo.elide.core.security.permissions.ExpressionResult) ReadPermission(com.yahoo.elide.annotation.ReadPermission) OrFilterExpression(com.yahoo.elide.core.filter.expression.OrFilterExpression) PersistentResource(com.yahoo.elide.core.PersistentResource) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) Relationship(com.yahoo.elide.core.request.Relationship) Observable(io.reactivex.Observable) PathElement(com.yahoo.elide.core.Path.PathElement) RelationshipType(com.yahoo.elide.core.dictionary.RelationshipType) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) Collections(java.util.Collections) LinkedHashSet(java.util.LinkedHashSet) RequestScope(com.yahoo.elide.core.RequestScope) LinkedHashSet(java.util.LinkedHashSet) PersistentResource(com.yahoo.elide.core.PersistentResource) PathElement(com.yahoo.elide.core.Path.PathElement) ExpressionResult(com.yahoo.elide.core.security.permissions.ExpressionResult) PermissionExecutor(com.yahoo.elide.core.security.PermissionExecutor) Objects(java.util.Objects) RequestScope(com.yahoo.elide.core.RequestScope) ForbiddenAccessException(com.yahoo.elide.core.exceptions.ForbiddenAccessException)

Example 2 with ForbiddenAccessException

use of com.yahoo.elide.core.exceptions.ForbiddenAccessException in project elide by yahoo.

the class AbstractPermissionExecutor method executeExpressions.

/**
 * Execute expressions.
 *
 * @param expression The expression to evaluate.
 * @param annotationClass The permission associated with the expression.
 * @param mode The evaluation mode of the expression.
 */
protected ExpressionResult executeExpressions(final Expression expression, final Class<? extends Annotation> annotationClass, Expression.EvaluationMode mode) {
    ExpressionResult result = expression.evaluate(mode);
    // Record the check
    if (log.isTraceEnabled()) {
        String checkKey = expression.toString();
        Long checkOccurrences = checkStats.getOrDefault(checkKey, 0L) + 1;
        checkStats.put(checkKey, checkOccurrences);
    }
    if (result == DEFERRED) {
        /*
             * Checking user checks only are an optimization step.  We don't need to defer these checks because
             * INLINE_ONLY checks will be evaluated later.  Also, the user checks don't have
             * the correct context to evaluate as COMMIT checks later.
             */
        if (mode == Expression.EvaluationMode.USER_CHECKS_ONLY) {
            return DEFERRED;
        }
        if (isInlineOnlyCheck(annotationClass)) {
            // Force evaluation of checks that can only be executed inline.
            result = expression.evaluate(Expression.EvaluationMode.ALL_CHECKS);
            if (result == FAIL) {
                ForbiddenAccessException e = new ForbiddenAccessException(annotationClass, expression, Expression.EvaluationMode.ALL_CHECKS);
                if (log.isTraceEnabled()) {
                    log.trace("{}", e.getLoggedMessage());
                }
                throw e;
            }
            return result;
        }
        commitCheckQueue.add(new AbstractPermissionExecutor.QueuedCheck(expression, annotationClass));
        return DEFERRED;
    }
    if (result == FAIL) {
        ForbiddenAccessException e = new ForbiddenAccessException(annotationClass, expression, mode);
        if (log.isTraceEnabled()) {
            log.trace("{}", e.getLoggedMessage());
        }
        throw e;
    }
    return result;
}
Also used : ExpressionResult(com.yahoo.elide.core.security.permissions.ExpressionResult) ForbiddenAccessException(com.yahoo.elide.core.exceptions.ForbiddenAccessException)

Example 3 with ForbiddenAccessException

use of com.yahoo.elide.core.exceptions.ForbiddenAccessException 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 4 with ForbiddenAccessException

use of com.yahoo.elide.core.exceptions.ForbiddenAccessException in project elide by yahoo.

the class VerifyFieldAccessFilterExpressionVisitorTest method testCustomFilterJoin.

@Test
public void testCustomFilterJoin() throws Exception {
    RSQLFilterDialect dialect = RSQLFilterDialect.builder().dictionary(scope.getDictionary()).build();
    FilterExpression expression = dialect.parseFilterExpression("genre==foo", ClassType.of(Book.class), true);
    Book book = new Book();
    PersistentResource<Book> resource = new PersistentResource<>(book, "", scope);
    PermissionExecutor permissionExecutor = scope.getPermissionExecutor();
    DataStoreTransaction tx = scope.getTransaction();
    when(permissionExecutor.checkUserPermissions(ClassType.of(Book.class), ReadPermission.class, GENRE)).thenReturn(ExpressionResult.DEFERRED);
    when(permissionExecutor.checkSpecificFieldPermissions(resource, null, ReadPermission.class, GENRE)).thenThrow(new ForbiddenAccessException(ReadPermission.class));
    when(permissionExecutor.evaluateFilterJoinUserChecks(any(), any())).thenReturn(ExpressionResult.DEFERRED);
    when(permissionExecutor.handleFilterJoinReject(any(), any(), any())).thenAnswer(invocation -> {
        FilterPredicate filterPredicate = invocation.getArgument(0);
        PathElement pathElement = invocation.getArgument(1);
        ForbiddenAccessException reason = invocation.getArgument(2);
        assertEquals("Book", pathElement.getType().getSimpleName());
        assertEquals(GENRE, filterPredicate.getField());
        assertEquals("book.genre IN [foo]", filterPredicate.toString());
        // custom processing
        return "Book".equals(pathElement.getType().getSimpleName()) && filterPredicate.toString().matches("book.genre IN \\[\\w+\\]") && reason.getLoggedMessage().matches(".*Message=ReadPermission Denied.*\\n.*") ? ExpressionResult.DEFERRED : ExpressionResult.FAIL;
    });
    VerifyFieldAccessFilterExpressionVisitor visitor = new VerifyFieldAccessFilterExpressionVisitor(resource);
    // restricted HOME field
    assertTrue(expression.accept(visitor));
    verify(permissionExecutor, times(1)).evaluateFilterJoinUserChecks(any(), any());
    verify(permissionExecutor, times(1)).checkSpecificFieldPermissions(resource, null, ReadPermission.class, GENRE);
    verify(permissionExecutor, never()).checkUserPermissions(any(), any(), isA(String.class));
    verify(permissionExecutor, times(1)).handleFilterJoinReject(any(), any(), any());
    verify(tx, never()).getToManyRelation(any(), any(), any(), any());
}
Also used : PersistentResource(com.yahoo.elide.core.PersistentResource) PermissionExecutor(com.yahoo.elide.core.security.PermissionExecutor) ForbiddenAccessException(com.yahoo.elide.core.exceptions.ForbiddenAccessException) PathElement(com.yahoo.elide.core.Path.PathElement) Book(example.Book) DataStoreTransaction(com.yahoo.elide.core.datastore.DataStoreTransaction) FilterPredicate(com.yahoo.elide.core.filter.predicates.FilterPredicate) OrFilterExpression(com.yahoo.elide.core.filter.expression.OrFilterExpression) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) NotFilterExpression(com.yahoo.elide.core.filter.expression.NotFilterExpression) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) ReadPermission(com.yahoo.elide.annotation.ReadPermission) RSQLFilterDialect(com.yahoo.elide.core.filter.dialect.RSQLFilterDialect) Test(org.junit.jupiter.api.Test)

Example 5 with ForbiddenAccessException

use of com.yahoo.elide.core.exceptions.ForbiddenAccessException in project elide by yahoo.

the class Elide method handleRuntimeException.

private ElideResponse handleRuntimeException(RuntimeException error, boolean isVerbose) {
    CustomErrorException mappedException = mapError(error);
    if (mappedException != null) {
        return buildErrorResponse(mappedException, isVerbose);
    }
    if (error instanceof WebApplicationException) {
        throw error;
    }
    if (error instanceof ForbiddenAccessException) {
        ForbiddenAccessException e = (ForbiddenAccessException) error;
        if (log.isDebugEnabled()) {
            log.debug("{}", e.getLoggedMessage());
        }
        return buildErrorResponse(e, isVerbose);
    }
    if (error instanceof JsonPatchExtensionException) {
        JsonPatchExtensionException e = (JsonPatchExtensionException) error;
        log.debug("JSON patch extension exception caught", e);
        return buildErrorResponse(e, isVerbose);
    }
    if (error instanceof HttpStatusException) {
        HttpStatusException e = (HttpStatusException) error;
        log.debug("Caught HTTP status exception", e);
        return buildErrorResponse(e, isVerbose);
    }
    if (error instanceof ParseCancellationException) {
        ParseCancellationException e = (ParseCancellationException) error;
        log.debug("Parse cancellation exception uncaught by Elide (i.e. invalid URL)", e);
        return buildErrorResponse(new InvalidURLException(e), isVerbose);
    }
    if (error instanceof ConstraintViolationException) {
        ConstraintViolationException e = (ConstraintViolationException) error;
        log.debug("Constraint violation exception caught", e);
        String message = "Constraint violation";
        final ErrorObjects.ErrorObjectsBuilder errorObjectsBuilder = ErrorObjects.builder();
        for (ConstraintViolation<?> constraintViolation : e.getConstraintViolations()) {
            errorObjectsBuilder.addError().withDetail(constraintViolation.getMessage());
            final String propertyPathString = constraintViolation.getPropertyPath().toString();
            if (!propertyPathString.isEmpty()) {
                Map<String, Object> source = new HashMap<>(1);
                source.put("property", propertyPathString);
                errorObjectsBuilder.with("source", source);
            }
        }
        return buildErrorResponse(new CustomErrorException(HttpStatus.SC_BAD_REQUEST, message, errorObjectsBuilder.build()), isVerbose);
    }
    log.error("Error or exception uncaught by Elide", error);
    throw new RuntimeException(error);
}
Also used : ErrorObjects(com.yahoo.elide.core.exceptions.ErrorObjects) WebApplicationException(javax.ws.rs.WebApplicationException) HashMap(java.util.HashMap) HttpStatusException(com.yahoo.elide.core.exceptions.HttpStatusException) ForbiddenAccessException(com.yahoo.elide.core.exceptions.ForbiddenAccessException) InvalidURLException(com.yahoo.elide.core.exceptions.InvalidURLException) ParseCancellationException(org.antlr.v4.runtime.misc.ParseCancellationException) ConstraintViolationException(javax.validation.ConstraintViolationException) CustomErrorException(com.yahoo.elide.core.exceptions.CustomErrorException) JsonPatchExtensionException(com.yahoo.elide.core.exceptions.JsonPatchExtensionException)

Aggregations

ForbiddenAccessException (com.yahoo.elide.core.exceptions.ForbiddenAccessException)11 ExpressionResult (com.yahoo.elide.core.security.permissions.ExpressionResult)6 PersistentResource (com.yahoo.elide.core.PersistentResource)4 ReadPermission (com.yahoo.elide.annotation.ReadPermission)3 PathElement (com.yahoo.elide.core.Path.PathElement)3 FilterExpression (com.yahoo.elide.core.filter.expression.FilterExpression)3 PermissionExecutor (com.yahoo.elide.core.security.PermissionExecutor)3 LinkedHashSet (java.util.LinkedHashSet)3 CustomErrorException (com.yahoo.elide.core.exceptions.CustomErrorException)2 ErrorObjects (com.yahoo.elide.core.exceptions.ErrorObjects)2 HttpStatusException (com.yahoo.elide.core.exceptions.HttpStatusException)2 AndFilterExpression (com.yahoo.elide.core.filter.expression.AndFilterExpression)2 NotFilterExpression (com.yahoo.elide.core.filter.expression.NotFilterExpression)2 OrFilterExpression (com.yahoo.elide.core.filter.expression.OrFilterExpression)2 FilterPredicate (com.yahoo.elide.core.filter.predicates.FilterPredicate)2 Relationship (com.yahoo.elide.core.request.Relationship)2 Expression (com.yahoo.elide.core.security.permissions.expressions.Expression)2 HashMap (java.util.HashMap)2 ConstraintViolationException (javax.validation.ConstraintViolationException)2 WebApplicationException (javax.ws.rs.WebApplicationException)2