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;
}
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);
}
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());
}
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);
}
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);
}
Aggregations