Search in sources :

Example 1 with AclBinding

use of org.apache.kafka.common.acl.AclBinding in project apache-kafka-on-k8s by banzaicloud.

the class KafkaAdminClientTest method testDescribeAcls.

@Test
public void testDescribeAcls() throws Exception {
    try (AdminClientUnitTestEnv env = mockClientEnv()) {
        env.kafkaClient().setNodeApiVersions(NodeApiVersions.create());
        env.kafkaClient().prepareMetadataUpdate(env.cluster(), Collections.<String>emptySet());
        env.kafkaClient().setNode(env.cluster().controller());
        // Test a call where we get back ACL1 and ACL2.
        env.kafkaClient().prepareResponse(new DescribeAclsResponse(0, ApiError.NONE, asList(ACL1, ACL2)));
        assertCollectionIs(env.adminClient().describeAcls(FILTER1).values().get(), ACL1, ACL2);
        // Test a call where we get back no results.
        env.kafkaClient().prepareResponse(new DescribeAclsResponse(0, ApiError.NONE, Collections.<AclBinding>emptySet()));
        assertTrue(env.adminClient().describeAcls(FILTER2).values().get().isEmpty());
        // Test a call where we get back an error.
        env.kafkaClient().prepareResponse(new DescribeAclsResponse(0, new ApiError(Errors.SECURITY_DISABLED, "Security is disabled"), Collections.<AclBinding>emptySet()));
        assertFutureError(env.adminClient().describeAcls(FILTER2).values(), SecurityDisabledException.class);
    }
}
Also used : DescribeAclsResponse(org.apache.kafka.common.requests.DescribeAclsResponse) AclBinding(org.apache.kafka.common.acl.AclBinding) ApiError(org.apache.kafka.common.requests.ApiError) Test(org.junit.Test)

Example 2 with AclBinding

use of org.apache.kafka.common.acl.AclBinding in project apache-kafka-on-k8s by banzaicloud.

the class KafkaAdminClient method createAcls.

@Override
public CreateAclsResult createAcls(Collection<AclBinding> acls, CreateAclsOptions options) {
    final long now = time.milliseconds();
    final Map<AclBinding, KafkaFutureImpl<Void>> futures = new HashMap<>();
    final List<AclCreation> aclCreations = new ArrayList<>();
    for (AclBinding acl : acls) {
        if (futures.get(acl) == null) {
            KafkaFutureImpl<Void> future = new KafkaFutureImpl<>();
            futures.put(acl, future);
            String indefinite = acl.toFilter().findIndefiniteField();
            if (indefinite == null) {
                aclCreations.add(new AclCreation(acl));
            } else {
                future.completeExceptionally(new InvalidRequestException("Invalid ACL creation: " + indefinite));
            }
        }
    }
    runnable.call(new Call("createAcls", calcDeadlineMs(now, options.timeoutMs()), new LeastLoadedNodeProvider()) {

        @Override
        AbstractRequest.Builder createRequest(int timeoutMs) {
            return new CreateAclsRequest.Builder(aclCreations);
        }

        @Override
        void handleResponse(AbstractResponse abstractResponse) {
            CreateAclsResponse response = (CreateAclsResponse) abstractResponse;
            List<AclCreationResponse> responses = response.aclCreationResponses();
            Iterator<AclCreationResponse> iter = responses.iterator();
            for (AclCreation aclCreation : aclCreations) {
                KafkaFutureImpl<Void> future = futures.get(aclCreation.acl());
                if (!iter.hasNext()) {
                    future.completeExceptionally(new UnknownServerException("The broker reported no creation result for the given ACL."));
                } else {
                    AclCreationResponse creation = iter.next();
                    if (creation.error().isFailure()) {
                        future.completeExceptionally(creation.error().exception());
                    } else {
                        future.complete(null);
                    }
                }
            }
        }

        @Override
        void handleFailure(Throwable throwable) {
            completeAllExceptionally(futures.values(), throwable);
        }
    }, now);
    return new CreateAclsResult(new HashMap<AclBinding, KafkaFuture<Void>>(futures));
}
Also used : HashMap(java.util.HashMap) ChannelBuilder(org.apache.kafka.common.network.ChannelBuilder) ArrayList(java.util.ArrayList) CreateAclsResponse(org.apache.kafka.common.requests.CreateAclsResponse) CreateAclsRequest(org.apache.kafka.common.requests.CreateAclsRequest) Iterator(java.util.Iterator) InvalidRequestException(org.apache.kafka.common.errors.InvalidRequestException) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) AclBinding(org.apache.kafka.common.acl.AclBinding) AclCreation(org.apache.kafka.common.requests.CreateAclsRequest.AclCreation) KafkaFuture(org.apache.kafka.common.KafkaFuture) AbstractResponse(org.apache.kafka.common.requests.AbstractResponse) KafkaFutureImpl(org.apache.kafka.common.internals.KafkaFutureImpl) UnknownServerException(org.apache.kafka.common.errors.UnknownServerException) AclCreationResponse(org.apache.kafka.common.requests.CreateAclsResponse.AclCreationResponse)

Example 3 with AclBinding

use of org.apache.kafka.common.acl.AclBinding 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 4 with AclBinding

use of org.apache.kafka.common.acl.AclBinding in project kafka by apache.

the class KafkaAdminClient method deleteAcls.

@Override
public DeleteAclsResult deleteAcls(Collection<AclBindingFilter> filters, DeleteAclsOptions options) {
    final long now = time.milliseconds();
    final Map<AclBindingFilter, KafkaFutureImpl<FilterResults>> futures = new HashMap<>();
    final List<AclBindingFilter> aclBindingFiltersSent = new ArrayList<>();
    final List<DeleteAclsFilter> deleteAclsFilters = new ArrayList<>();
    for (AclBindingFilter filter : filters) {
        if (futures.get(filter) == null) {
            aclBindingFiltersSent.add(filter);
            deleteAclsFilters.add(DeleteAclsRequest.deleteAclsFilter(filter));
            futures.put(filter, new KafkaFutureImpl<>());
        }
    }
    final DeleteAclsRequestData data = new DeleteAclsRequestData().setFilters(deleteAclsFilters);
    runnable.call(new Call("deleteAcls", calcDeadlineMs(now, options.timeoutMs()), new LeastLoadedNodeProvider()) {

        @Override
        DeleteAclsRequest.Builder createRequest(int timeoutMs) {
            return new DeleteAclsRequest.Builder(data);
        }

        @Override
        void handleResponse(AbstractResponse abstractResponse) {
            DeleteAclsResponse response = (DeleteAclsResponse) abstractResponse;
            List<DeleteAclsResponseData.DeleteAclsFilterResult> results = response.filterResults();
            Iterator<DeleteAclsResponseData.DeleteAclsFilterResult> iter = results.iterator();
            for (AclBindingFilter bindingFilter : aclBindingFiltersSent) {
                KafkaFutureImpl<FilterResults> future = futures.get(bindingFilter);
                if (!iter.hasNext()) {
                    future.completeExceptionally(new UnknownServerException("The broker reported no deletion result for the given filter."));
                } else {
                    DeleteAclsFilterResult filterResult = iter.next();
                    ApiError error = new ApiError(Errors.forCode(filterResult.errorCode()), filterResult.errorMessage());
                    if (error.isFailure()) {
                        future.completeExceptionally(error.exception());
                    } else {
                        List<FilterResult> filterResults = new ArrayList<>();
                        for (DeleteAclsMatchingAcl matchingAcl : filterResult.matchingAcls()) {
                            ApiError aclError = new ApiError(Errors.forCode(matchingAcl.errorCode()), matchingAcl.errorMessage());
                            AclBinding aclBinding = DeleteAclsResponse.aclBinding(matchingAcl);
                            filterResults.add(new FilterResult(aclBinding, aclError.exception()));
                        }
                        future.complete(new FilterResults(filterResults));
                    }
                }
            }
        }

        @Override
        void handleFailure(Throwable throwable) {
            completeAllExceptionally(futures.values(), throwable);
        }
    }, now);
    return new DeleteAclsResult(new HashMap<>(futures));
}
Also used : HashMap(java.util.HashMap) ChannelBuilder(org.apache.kafka.common.network.ChannelBuilder) ArrayList(java.util.ArrayList) DeleteAclsRequestData(org.apache.kafka.common.message.DeleteAclsRequestData) DeleteAclsResponse(org.apache.kafka.common.requests.DeleteAclsResponse) DeleteAclsFilterResult(org.apache.kafka.common.message.DeleteAclsResponseData.DeleteAclsFilterResult) Iterator(java.util.Iterator) LinkedList(java.util.LinkedList) ArrayList(java.util.ArrayList) List(java.util.List) AclBinding(org.apache.kafka.common.acl.AclBinding) FilterResults(org.apache.kafka.clients.admin.DeleteAclsResult.FilterResults) AclBindingFilter(org.apache.kafka.common.acl.AclBindingFilter) AbstractResponse(org.apache.kafka.common.requests.AbstractResponse) DeleteAclsResponseData(org.apache.kafka.common.message.DeleteAclsResponseData) KafkaFutureImpl(org.apache.kafka.common.internals.KafkaFutureImpl) DeleteAclsRequest(org.apache.kafka.common.requests.DeleteAclsRequest) DeleteAclsFilter(org.apache.kafka.common.message.DeleteAclsRequestData.DeleteAclsFilter) UnknownServerException(org.apache.kafka.common.errors.UnknownServerException) ApiError(org.apache.kafka.common.requests.ApiError) DeleteAclsFilterResult(org.apache.kafka.common.message.DeleteAclsResponseData.DeleteAclsFilterResult) FilterResult(org.apache.kafka.clients.admin.DeleteAclsResult.FilterResult) DeleteAclsMatchingAcl(org.apache.kafka.common.message.DeleteAclsResponseData.DeleteAclsMatchingAcl)

Example 5 with AclBinding

use of org.apache.kafka.common.acl.AclBinding in project kafka by apache.

the class KafkaAdminClient method createAcls.

@Override
public CreateAclsResult createAcls(Collection<AclBinding> acls, CreateAclsOptions options) {
    final long now = time.milliseconds();
    final Map<AclBinding, KafkaFutureImpl<Void>> futures = new HashMap<>();
    final List<AclCreation> aclCreations = new ArrayList<>();
    final List<AclBinding> aclBindingsSent = new ArrayList<>();
    for (AclBinding acl : acls) {
        if (futures.get(acl) == null) {
            KafkaFutureImpl<Void> future = new KafkaFutureImpl<>();
            futures.put(acl, future);
            String indefinite = acl.toFilter().findIndefiniteField();
            if (indefinite == null) {
                aclCreations.add(CreateAclsRequest.aclCreation(acl));
                aclBindingsSent.add(acl);
            } else {
                future.completeExceptionally(new InvalidRequestException("Invalid ACL creation: " + indefinite));
            }
        }
    }
    final CreateAclsRequestData data = new CreateAclsRequestData().setCreations(aclCreations);
    runnable.call(new Call("createAcls", calcDeadlineMs(now, options.timeoutMs()), new LeastLoadedNodeProvider()) {

        @Override
        CreateAclsRequest.Builder createRequest(int timeoutMs) {
            return new CreateAclsRequest.Builder(data);
        }

        @Override
        void handleResponse(AbstractResponse abstractResponse) {
            CreateAclsResponse response = (CreateAclsResponse) abstractResponse;
            List<AclCreationResult> responses = response.results();
            Iterator<AclCreationResult> iter = responses.iterator();
            for (AclBinding aclBinding : aclBindingsSent) {
                KafkaFutureImpl<Void> future = futures.get(aclBinding);
                if (!iter.hasNext()) {
                    future.completeExceptionally(new UnknownServerException("The broker reported no creation result for the given ACL: " + aclBinding));
                } else {
                    AclCreationResult creation = iter.next();
                    Errors error = Errors.forCode(creation.errorCode());
                    ApiError apiError = new ApiError(error, creation.errorMessage());
                    if (apiError.isFailure())
                        future.completeExceptionally(apiError.exception());
                    else
                        future.complete(null);
                }
            }
        }

        @Override
        void handleFailure(Throwable throwable) {
            completeAllExceptionally(futures.values(), throwable);
        }
    }, now);
    return new CreateAclsResult(new HashMap<>(futures));
}
Also used : HashMap(java.util.HashMap) ChannelBuilder(org.apache.kafka.common.network.ChannelBuilder) ArrayList(java.util.ArrayList) CreateAclsResponse(org.apache.kafka.common.requests.CreateAclsResponse) CreateAclsRequest(org.apache.kafka.common.requests.CreateAclsRequest) Iterator(java.util.Iterator) InvalidRequestException(org.apache.kafka.common.errors.InvalidRequestException) LinkedList(java.util.LinkedList) ArrayList(java.util.ArrayList) List(java.util.List) AclBinding(org.apache.kafka.common.acl.AclBinding) AclCreation(org.apache.kafka.common.message.CreateAclsRequestData.AclCreation) AbstractResponse(org.apache.kafka.common.requests.AbstractResponse) CreateAclsRequestData(org.apache.kafka.common.message.CreateAclsRequestData) KafkaFutureImpl(org.apache.kafka.common.internals.KafkaFutureImpl) UnknownServerException(org.apache.kafka.common.errors.UnknownServerException) Errors(org.apache.kafka.common.protocol.Errors) ApiError(org.apache.kafka.common.requests.ApiError) AclCreationResult(org.apache.kafka.common.message.CreateAclsResponseData.AclCreationResult)

Aggregations

AclBinding (org.apache.kafka.common.acl.AclBinding)28 AccessControlEntry (org.apache.kafka.common.acl.AccessControlEntry)16 ResourcePattern (org.apache.kafka.common.resource.ResourcePattern)14 ArrayList (java.util.ArrayList)11 List (java.util.List)7 Test (org.junit.jupiter.api.Test)6 HashMap (java.util.HashMap)5 AclBindingFilter (org.apache.kafka.common.acl.AclBindingFilter)5 Map (java.util.Map)4 UnknownServerException (org.apache.kafka.common.errors.UnknownServerException)4 ApiError (org.apache.kafka.common.requests.ApiError)4 Iterator (java.util.Iterator)3 LinkedList (java.util.LinkedList)3 InvalidRequestException (org.apache.kafka.common.errors.InvalidRequestException)3 KafkaFutureImpl (org.apache.kafka.common.internals.KafkaFutureImpl)3 DeleteAclsResponseData (org.apache.kafka.common.message.DeleteAclsResponseData)3 ChannelBuilder (org.apache.kafka.common.network.ChannelBuilder)3 Errors (org.apache.kafka.common.protocol.Errors)3 AbstractResponse (org.apache.kafka.common.requests.AbstractResponse)3 PatternType (org.apache.kafka.common.resource.PatternType)3