Search in sources :

Example 1 with ResourcePattern

use of org.apache.kafka.common.resource.ResourcePattern 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 ResourcePattern

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

the class RequestResponseTest method createCreateAclsRequest.

private CreateAclsRequest createCreateAclsRequest(short version) {
    List<CreateAclsRequestData.AclCreation> creations = new ArrayList<>();
    creations.add(CreateAclsRequest.aclCreation(new AclBinding(new ResourcePattern(ResourceType.TOPIC, "mytopic", PatternType.LITERAL), new AccessControlEntry("User:ANONYMOUS", "127.0.0.1", AclOperation.READ, AclPermissionType.ALLOW))));
    creations.add(CreateAclsRequest.aclCreation(new AclBinding(new ResourcePattern(ResourceType.GROUP, "mygroup", PatternType.LITERAL), new AccessControlEntry("User:ANONYMOUS", "*", AclOperation.WRITE, AclPermissionType.DENY))));
    CreateAclsRequestData data = new CreateAclsRequestData().setCreations(creations);
    return new CreateAclsRequest.Builder(data).build(version);
}
Also used : ResourcePattern(org.apache.kafka.common.resource.ResourcePattern) ArrayList(java.util.ArrayList) CreateAclsRequestData(org.apache.kafka.common.message.CreateAclsRequestData) AccessControlEntry(org.apache.kafka.common.acl.AccessControlEntry) AclBinding(org.apache.kafka.common.acl.AclBinding)

Example 3 with ResourcePattern

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

the class AclBindingTest method testMatching.

@Test
public void testMatching() {
    assertEquals(ACL1, ACL1);
    final AclBinding acl1Copy = new AclBinding(new ResourcePattern(ResourceType.TOPIC, "mytopic", PatternType.LITERAL), new AccessControlEntry("User:ANONYMOUS", "", AclOperation.ALL, AclPermissionType.ALLOW));
    assertEquals(ACL1, acl1Copy);
    assertEquals(acl1Copy, ACL1);
    assertEquals(ACL2, ACL2);
    assertNotEquals(ACL1, ACL2);
    assertNotEquals(ACL2, ACL1);
    assertTrue(AclBindingFilter.ANY.matches(ACL1));
    assertNotEquals(AclBindingFilter.ANY, ACL1);
    assertTrue(AclBindingFilter.ANY.matches(ACL2));
    assertNotEquals(AclBindingFilter.ANY, ACL2);
    assertTrue(AclBindingFilter.ANY.matches(ACL3));
    assertNotEquals(AclBindingFilter.ANY, ACL3);
    assertEquals(AclBindingFilter.ANY, AclBindingFilter.ANY);
    assertTrue(ANY_ANONYMOUS.matches(ACL1));
    assertNotEquals(ANY_ANONYMOUS, ACL1);
    assertFalse(ANY_ANONYMOUS.matches(ACL2));
    assertNotEquals(ANY_ANONYMOUS, ACL2);
    assertTrue(ANY_ANONYMOUS.matches(ACL3));
    assertNotEquals(ANY_ANONYMOUS, ACL3);
    assertFalse(ANY_DENY.matches(ACL1));
    assertFalse(ANY_DENY.matches(ACL2));
    assertTrue(ANY_DENY.matches(ACL3));
    assertTrue(ANY_MYTOPIC.matches(ACL1));
    assertTrue(ANY_MYTOPIC.matches(ACL2));
    assertFalse(ANY_MYTOPIC.matches(ACL3));
    assertTrue(ANY_ANONYMOUS.matches(UNKNOWN_ACL));
    assertTrue(ANY_DENY.matches(UNKNOWN_ACL));
    assertEquals(UNKNOWN_ACL, UNKNOWN_ACL);
    assertFalse(ANY_MYTOPIC.matches(UNKNOWN_ACL));
}
Also used : ResourcePattern(org.apache.kafka.common.resource.ResourcePattern) Test(org.junit.jupiter.api.Test)

Example 4 with ResourcePattern

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

the class DescribeAclsResponse method aclsResources.

public static List<DescribeAclsResource> aclsResources(Collection<AclBinding> acls) {
    Map<ResourcePattern, List<AccessControlEntry>> patternToEntries = new HashMap<>();
    for (AclBinding acl : acls) {
        patternToEntries.computeIfAbsent(acl.pattern(), v -> new ArrayList<>()).add(acl.entry());
    }
    List<DescribeAclsResource> resources = new ArrayList<>(patternToEntries.size());
    for (Entry<ResourcePattern, List<AccessControlEntry>> entry : patternToEntries.entrySet()) {
        ResourcePattern key = entry.getKey();
        List<AclDescription> aclDescriptions = new ArrayList<>();
        for (AccessControlEntry ace : entry.getValue()) {
            AclDescription ad = new AclDescription().setHost(ace.host()).setOperation(ace.operation().code()).setPermissionType(ace.permissionType().code()).setPrincipal(ace.principal());
            aclDescriptions.add(ad);
        }
        DescribeAclsResource dar = new DescribeAclsResource().setResourceName(key.name()).setPatternType(key.patternType().code()).setResourceType(key.resourceType().code()).setAcls(aclDescriptions);
        resources.add(dar);
    }
    return resources;
}
Also used : DescribeAclsResponseData(org.apache.kafka.common.message.DescribeAclsResponseData) Collection(java.util.Collection) ByteBufferAccessor(org.apache.kafka.common.protocol.ByteBufferAccessor) AclPermissionType(org.apache.kafka.common.acl.AclPermissionType) HashMap(java.util.HashMap) ResourcePattern(org.apache.kafka.common.resource.ResourcePattern) AclOperation(org.apache.kafka.common.acl.AclOperation) DescribeAclsResource(org.apache.kafka.common.message.DescribeAclsResponseData.DescribeAclsResource) ApiKeys(org.apache.kafka.common.protocol.ApiKeys) PatternType(org.apache.kafka.common.resource.PatternType) Collectors(java.util.stream.Collectors) ByteBuffer(java.nio.ByteBuffer) ArrayList(java.util.ArrayList) AccessControlEntry(org.apache.kafka.common.acl.AccessControlEntry) List(java.util.List) Stream(java.util.stream.Stream) ResourceType(org.apache.kafka.common.resource.ResourceType) AclDescription(org.apache.kafka.common.message.DescribeAclsResponseData.AclDescription) AclBinding(org.apache.kafka.common.acl.AclBinding) Map(java.util.Map) Entry(java.util.Map.Entry) UnsupportedVersionException(org.apache.kafka.common.errors.UnsupportedVersionException) Errors(org.apache.kafka.common.protocol.Errors) Optional(java.util.Optional) DescribeAclsResource(org.apache.kafka.common.message.DescribeAclsResponseData.DescribeAclsResource) HashMap(java.util.HashMap) ResourcePattern(org.apache.kafka.common.resource.ResourcePattern) ArrayList(java.util.ArrayList) AccessControlEntry(org.apache.kafka.common.acl.AccessControlEntry) ArrayList(java.util.ArrayList) List(java.util.List) AclBinding(org.apache.kafka.common.acl.AclBinding) AclDescription(org.apache.kafka.common.message.DescribeAclsResponseData.AclDescription)

Example 5 with ResourcePattern

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

the class MirrorSourceConnector method targetAclBinding.

AclBinding targetAclBinding(AclBinding sourceAclBinding) {
    String targetTopic = formatRemoteTopic(sourceAclBinding.pattern().name());
    final AccessControlEntry entry;
    if (sourceAclBinding.entry().permissionType() == AclPermissionType.ALLOW && sourceAclBinding.entry().operation() == AclOperation.ALL) {
        entry = downgradeAllowAllACL(sourceAclBinding.entry());
    } else {
        entry = sourceAclBinding.entry();
    }
    return new AclBinding(new ResourcePattern(ResourceType.TOPIC, targetTopic, PatternType.LITERAL), entry);
}
Also used : ResourcePattern(org.apache.kafka.common.resource.ResourcePattern) AccessControlEntry(org.apache.kafka.common.acl.AccessControlEntry) AclBinding(org.apache.kafka.common.acl.AclBinding)

Aggregations

ResourcePattern (org.apache.kafka.common.resource.ResourcePattern)17 AccessControlEntry (org.apache.kafka.common.acl.AccessControlEntry)14 AclBinding (org.apache.kafka.common.acl.AclBinding)13 Test (org.junit.jupiter.api.Test)6 HashSet (java.util.HashSet)4 ArrayList (java.util.ArrayList)3 Map (java.util.Map)3 HashMap (java.util.HashMap)2 List (java.util.List)2 Set (java.util.Set)2 VersionedAcls (kafka.security.authorizer.AclAuthorizer.VersionedAcls)2 AclEntry (kafka.security.authorizer.AclEntry)2 AclBindingFilter (org.apache.kafka.common.acl.AclBindingFilter)2 PatternType (org.apache.kafka.common.resource.PatternType)2 ResourcePatternFilter (org.apache.kafka.common.resource.ResourcePatternFilter)2 StandardAclTest (org.apache.kafka.metadata.authorizer.StandardAclTest)2 StandardAclWithIdTest (org.apache.kafka.metadata.authorizer.StandardAclWithIdTest)2 ByteBuffer (java.nio.ByteBuffer)1 Collection (java.util.Collection)1 EnumMap (java.util.EnumMap)1