Search in sources :

Example 1 with PatternType

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

Aggregations

EnumMap (java.util.EnumMap)1 HashSet (java.util.HashSet)1 Map (java.util.Map)1 Set (java.util.Set)1 AclBinding (org.apache.kafka.common.acl.AclBinding)1 AclBindingFilter (org.apache.kafka.common.acl.AclBindingFilter)1 PatternType (org.apache.kafka.common.resource.PatternType)1 ResourcePattern (org.apache.kafka.common.resource.ResourcePattern)1 ResourcePatternFilter (org.apache.kafka.common.resource.ResourcePatternFilter)1 KafkaPrincipal (org.apache.kafka.common.security.auth.KafkaPrincipal)1