Search in sources :

Example 1 with ResourcePatternFilter

use of org.apache.kafka.common.resource.ResourcePatternFilter in project kafka by apache.

the class Authorizer method authorizeByResourceType.

/**
 * Check if the caller is authorized to perform theĀ given ACL operation on at least one
 * resource of the given type.
 *
 * Custom authorizer implementations should consider overriding this default implementation because:
 * 1. The default implementation iterates all AclBindings multiple times, without any caching
 *    by principal, host, operation, permission types, and resource types. More efficient
 *    implementations may be added in custom authorizers that directly access cached entries.
 * 2. The default implementation cannot integrate with any audit logging included in the
 *    authorizer implementation.
 * 3. The default implementation does not support any custom authorizer configs or other access
 *    rules apart from ACLs.
 *
 * @param requestContext Request context including request resourceType, security protocol and listener name
 * @param op             The ACL operation to check
 * @param resourceType   The resource type to check
 * @return               Return {@link AuthorizationResult#ALLOWED} if the caller is authorized
 *                       to perform the given ACL operation on at least one resource of the
 *                       given type. Return {@link AuthorizationResult#DENIED} otherwise.
 */
default AuthorizationResult authorizeByResourceType(AuthorizableRequestContext requestContext, AclOperation op, ResourceType resourceType) {
    SecurityUtils.authorizeByResourceTypeCheckArgs(op, resourceType);
    // access regardless of DENY ACLs.
    if (authorize(requestContext, Collections.singletonList(new Action(op, new ResourcePattern(resourceType, "hardcode", PatternType.LITERAL), 0, true, false))).get(0) == AuthorizationResult.ALLOWED) {
        return AuthorizationResult.ALLOWED;
    }
    // Filter out all the resource pattern corresponding to the RequestContext,
    // AclOperation, and ResourceType
    ResourcePatternFilter resourceTypeFilter = new ResourcePatternFilter(resourceType, null, PatternType.ANY);
    AclBindingFilter aclFilter = new AclBindingFilter(resourceTypeFilter, AccessControlEntryFilter.ANY);
    EnumMap<PatternType, Set<String>> denyPatterns = new EnumMap<PatternType, Set<String>>(PatternType.class) {

        {
            put(PatternType.LITERAL, new HashSet<>());
            put(PatternType.PREFIXED, new HashSet<>());
        }
    };
    EnumMap<PatternType, Set<String>> allowPatterns = new EnumMap<PatternType, Set<String>>(PatternType.class) {

        {
            put(PatternType.LITERAL, new HashSet<>());
            put(PatternType.PREFIXED, new HashSet<>());
        }
    };
    boolean hasWildCardAllow = false;
    KafkaPrincipal principal = new KafkaPrincipal(requestContext.principal().getPrincipalType(), requestContext.principal().getName());
    String hostAddr = requestContext.clientAddress().getHostAddress();
    for (AclBinding binding : acls(aclFilter)) {
        if (!binding.entry().host().equals(hostAddr) && !binding.entry().host().equals("*"))
            continue;
        if (!SecurityUtils.parseKafkaPrincipal(binding.entry().principal()).equals(principal) && !binding.entry().principal().equals("User:*"))
            continue;
        if (binding.entry().operation() != op && binding.entry().operation() != AclOperation.ALL)
            continue;
        if (binding.entry().permissionType() == AclPermissionType.DENY) {
            switch(binding.pattern().patternType()) {
                case LITERAL:
                    // If wildcard deny exists, return deny directly
                    if (binding.pattern().name().equals(ResourcePattern.WILDCARD_RESOURCE))
                        return AuthorizationResult.DENIED;
                    denyPatterns.get(PatternType.LITERAL).add(binding.pattern().name());
                    break;
                case PREFIXED:
                    denyPatterns.get(PatternType.PREFIXED).add(binding.pattern().name());
                    break;
                default:
            }
            continue;
        }
        if (binding.entry().permissionType() != AclPermissionType.ALLOW)
            continue;
        switch(binding.pattern().patternType()) {
            case LITERAL:
                if (binding.pattern().name().equals(ResourcePattern.WILDCARD_RESOURCE)) {
                    hasWildCardAllow = true;
                    continue;
                }
                allowPatterns.get(PatternType.LITERAL).add(binding.pattern().name());
                break;
            case PREFIXED:
                allowPatterns.get(PatternType.PREFIXED).add(binding.pattern().name());
                break;
            default:
        }
    }
    if (hasWildCardAllow) {
        return AuthorizationResult.ALLOWED;
    }
    // For any prefix allowed, if there's no dominant prefix denied, return allow.
    for (Map.Entry<PatternType, Set<String>> entry : allowPatterns.entrySet()) {
        for (String allowStr : entry.getValue()) {
            if (entry.getKey() == PatternType.LITERAL && denyPatterns.get(PatternType.LITERAL).contains(allowStr))
                continue;
            StringBuilder sb = new StringBuilder();
            boolean hasDominatedDeny = false;
            for (char ch : allowStr.toCharArray()) {
                sb.append(ch);
                if (denyPatterns.get(PatternType.PREFIXED).contains(sb.toString())) {
                    hasDominatedDeny = true;
                    break;
                }
            }
            if (!hasDominatedDeny)
                return AuthorizationResult.ALLOWED;
        }
    }
    return AuthorizationResult.DENIED;
}
Also used : PatternType(org.apache.kafka.common.resource.PatternType) AclBindingFilter(org.apache.kafka.common.acl.AclBindingFilter) Set(java.util.Set) HashSet(java.util.HashSet) ResourcePatternFilter(org.apache.kafka.common.resource.ResourcePatternFilter) ResourcePattern(org.apache.kafka.common.resource.ResourcePattern) KafkaPrincipal(org.apache.kafka.common.security.auth.KafkaPrincipal) AclBinding(org.apache.kafka.common.acl.AclBinding) EnumMap(java.util.EnumMap) EnumMap(java.util.EnumMap) Map(java.util.Map)

Example 2 with ResourcePatternFilter

use of org.apache.kafka.common.resource.ResourcePatternFilter in project kafka by apache.

the class DeleteAclsRequest method aclBindingFilter.

private static AclBindingFilter aclBindingFilter(DeleteAclsFilter filter) {
    ResourcePatternFilter patternFilter = new ResourcePatternFilter(ResourceType.fromCode(filter.resourceTypeFilter()), filter.resourceNameFilter(), PatternType.fromCode(filter.patternTypeFilter()));
    AccessControlEntryFilter entryFilter = new AccessControlEntryFilter(filter.principalFilter(), filter.hostFilter(), AclOperation.fromCode(filter.operation()), AclPermissionType.fromCode(filter.permissionType()));
    return new AclBindingFilter(patternFilter, entryFilter);
}
Also used : AclBindingFilter(org.apache.kafka.common.acl.AclBindingFilter) ResourcePatternFilter(org.apache.kafka.common.resource.ResourcePatternFilter) AccessControlEntryFilter(org.apache.kafka.common.acl.AccessControlEntryFilter)

Example 3 with ResourcePatternFilter

use of org.apache.kafka.common.resource.ResourcePatternFilter in project kafka by apache.

the class StandardAuthorizerTest method testListAcls.

@Test
public void testListAcls() throws Exception {
    StandardAuthorizer authorizer = new StandardAuthorizer();
    authorizer.configure(Collections.emptyMap());
    List<StandardAclWithId> fooAcls = asList(withId(newFooAcl(READ, ALLOW)), withId(newFooAcl(WRITE, ALLOW)));
    List<StandardAclWithId> barAcls = asList(withId(newBarAcl(DESCRIBE_CONFIGS, DENY)), withId(newBarAcl(ALTER_CONFIGS, DENY)));
    fooAcls.forEach(a -> authorizer.addAcl(a.id(), a.acl()));
    barAcls.forEach(a -> authorizer.addAcl(a.id(), a.acl()));
    assertContains(authorizer.acls(AclBindingFilter.ANY), fooAcls.get(0).acl(), fooAcls.get(1).acl(), barAcls.get(0).acl(), barAcls.get(1).acl());
    authorizer.removeAcl(fooAcls.get(1).id());
    assertContains(authorizer.acls(AclBindingFilter.ANY), fooAcls.get(0).acl(), barAcls.get(0).acl(), barAcls.get(1).acl());
    assertContains(authorizer.acls(new AclBindingFilter(new ResourcePatternFilter(TOPIC, null, PatternType.ANY), AccessControlEntryFilter.ANY)), fooAcls.get(0).acl());
}
Also used : AclBindingFilter(org.apache.kafka.common.acl.AclBindingFilter) ResourcePatternFilter(org.apache.kafka.common.resource.ResourcePatternFilter) Test(org.junit.jupiter.api.Test)

Example 4 with ResourcePatternFilter

use of org.apache.kafka.common.resource.ResourcePatternFilter in project kafka by apache.

the class DescribeAclsRequestTest method shouldRoundTripAnyV0AsLiteral.

@Test
public void shouldRoundTripAnyV0AsLiteral() {
    final DescribeAclsRequest original = new DescribeAclsRequest.Builder(ANY_FILTER).build(V0);
    final DescribeAclsRequest expected = new DescribeAclsRequest.Builder(new AclBindingFilter(new ResourcePatternFilter(ANY_FILTER.patternFilter().resourceType(), ANY_FILTER.patternFilter().name(), PatternType.LITERAL), ANY_FILTER.entryFilter())).build(V0);
    final DescribeAclsRequest result = DescribeAclsRequest.parse(original.serialize(), V0);
    assertRequestEquals(expected, result);
}
Also used : AclBindingFilter(org.apache.kafka.common.acl.AclBindingFilter) ResourcePatternFilter(org.apache.kafka.common.resource.ResourcePatternFilter) Test(org.junit.jupiter.api.Test)

Example 5 with ResourcePatternFilter

use of org.apache.kafka.common.resource.ResourcePatternFilter in project kafka by apache.

the class DeleteAclsRequestTest method shouldRoundTripAnyV0AsLiteral.

@Test
public void shouldRoundTripAnyV0AsLiteral() {
    final DeleteAclsRequest original = new DeleteAclsRequest.Builder(requestData(ANY_FILTER)).build(V0);
    final DeleteAclsRequest expected = new DeleteAclsRequest.Builder(requestData(new AclBindingFilter(new ResourcePatternFilter(ANY_FILTER.patternFilter().resourceType(), ANY_FILTER.patternFilter().name(), PatternType.LITERAL), ANY_FILTER.entryFilter()))).build(V0);
    final DeleteAclsRequest result = DeleteAclsRequest.parse(original.serialize(), V0);
    assertRequestEquals(expected, result);
}
Also used : AclBindingFilter(org.apache.kafka.common.acl.AclBindingFilter) ResourcePatternFilter(org.apache.kafka.common.resource.ResourcePatternFilter) Test(org.junit.jupiter.api.Test)

Aggregations

AclBindingFilter (org.apache.kafka.common.acl.AclBindingFilter)8 ResourcePatternFilter (org.apache.kafka.common.resource.ResourcePatternFilter)8 Test (org.junit.jupiter.api.Test)5 AccessControlEntryFilter (org.apache.kafka.common.acl.AccessControlEntryFilter)3 HashSet (java.util.HashSet)2 AclBinding (org.apache.kafka.common.acl.AclBinding)2 ResourcePattern (org.apache.kafka.common.resource.ResourcePattern)2 StandardAclTest (org.apache.kafka.metadata.authorizer.StandardAclTest)2 StandardAclWithIdTest (org.apache.kafka.metadata.authorizer.StandardAclWithIdTest)2 ArrayList (java.util.ArrayList)1 EnumMap (java.util.EnumMap)1 List (java.util.List)1 Map (java.util.Map)1 Set (java.util.Set)1 Endpoint (org.apache.kafka.common.Endpoint)1 AccessControlEntry (org.apache.kafka.common.acl.AccessControlEntry)1 InvalidRequestException (org.apache.kafka.common.errors.InvalidRequestException)1 PatternType (org.apache.kafka.common.resource.PatternType)1 KafkaPrincipal (org.apache.kafka.common.security.auth.KafkaPrincipal)1 LogContext (org.apache.kafka.common.utils.LogContext)1