use of io.streamnative.pulsar.handlers.kop.security.auth.Resource in project starlight-for-kafka by datastax.
the class KafkaRequestHandler method handleDescribeConfigs.
@Override
protected void handleDescribeConfigs(KafkaHeaderAndRequest describeConfigs, CompletableFuture<AbstractResponse> resultFuture) {
checkArgument(describeConfigs.getRequest() instanceof DescribeConfigsRequest);
DescribeConfigsRequest request = (DescribeConfigsRequest) describeConfigs.getRequest();
if (request.resources().isEmpty()) {
resultFuture.complete(new DescribeConfigsResponse(0, Maps.newHashMap()));
return;
}
Collection<ConfigResource> authorizedResources = Collections.synchronizedList(new ArrayList<>());
Map<ConfigResource, DescribeConfigsResponse.Config> failedConfigResourceMap = Maps.newConcurrentMap();
AtomicInteger unfinishedAuthorizationCount = new AtomicInteger(request.resources().size());
String namespacePrefix = currentNamespacePrefix();
Consumer<Runnable> completeOne = (action) -> {
// When complete one authorization or failed, will do the action first.
action.run();
if (unfinishedAuthorizationCount.decrementAndGet() == 0) {
adminManager.describeConfigsAsync(authorizedResources.stream().collect(Collectors.toMap(resource -> resource, resource -> Optional.ofNullable(request.configNames(resource)).map(HashSet::new))), namespacePrefix).thenApply(configResourceConfigMap -> {
configResourceConfigMap.putAll(failedConfigResourceMap);
resultFuture.complete(new DescribeConfigsResponse(0, configResourceConfigMap));
return null;
});
}
};
// Do authorization for each of resource
request.resources().forEach(configResource -> {
switch(configResource.type()) {
case TOPIC:
KopTopic kopTopic;
try {
kopTopic = new KopTopic(configResource.name(), namespacePrefix);
} catch (KoPTopicException e) {
completeOne.accept(() -> {
final ApiError error = new ApiError(Errors.UNKNOWN_TOPIC_OR_PARTITION, "Topic " + configResource.name() + " doesn't exist");
failedConfigResourceMap.put(configResource, new DescribeConfigsResponse.Config(error, Collections.emptyList()));
});
return;
}
String fullTopicName = kopTopic.getFullName();
authorize(AclOperation.DESCRIBE_CONFIGS, Resource.of(ResourceType.TOPIC, fullTopicName)).whenComplete((isAuthorized, ex) -> {
if (ex != null) {
log.error("DescribeConfigs in topic authorize failed, topic - {}. {}", fullTopicName, ex.getMessage());
completeOne.accept(() -> failedConfigResourceMap.put(configResource, new DescribeConfigsResponse.Config(new ApiError(Errors.TOPIC_AUTHORIZATION_FAILED, null), Collections.emptyList())));
return;
}
if (isAuthorized) {
completeOne.accept(() -> authorizedResources.add(configResource));
return;
}
completeOne.accept(() -> failedConfigResourceMap.put(configResource, new DescribeConfigsResponse.Config(new ApiError(Errors.TOPIC_AUTHORIZATION_FAILED, null), Collections.emptyList())));
});
break;
case BROKER:
// Current KoP don't support Broker Resource.
// but we are not exposing anything to the client, so it is fine to serve requests.
completeOne.accept(() -> authorizedResources.add(configResource));
break;
case UNKNOWN:
default:
completeOne.accept(() -> log.error("KoP doesn't support resource type: " + configResource.type()));
break;
}
});
}
use of io.streamnative.pulsar.handlers.kop.security.auth.Resource in project kop by streamnative.
the class KafkaRequestHandler method handleDescribeConfigs.
@Override
protected void handleDescribeConfigs(KafkaHeaderAndRequest describeConfigs, CompletableFuture<AbstractResponse> resultFuture) {
checkArgument(describeConfigs.getRequest() instanceof DescribeConfigsRequest);
DescribeConfigsRequest request = (DescribeConfigsRequest) describeConfigs.getRequest();
if (request.resources().isEmpty()) {
resultFuture.complete(new DescribeConfigsResponse(0, Maps.newHashMap()));
return;
}
Collection<ConfigResource> authorizedResources = Collections.synchronizedList(new ArrayList<>());
Map<ConfigResource, DescribeConfigsResponse.Config> failedConfigResourceMap = Maps.newConcurrentMap();
AtomicInteger unfinishedAuthorizationCount = new AtomicInteger(request.resources().size());
String namespacePrefix = currentNamespacePrefix();
Consumer<Runnable> completeOne = (action) -> {
// When complete one authorization or failed, will do the action first.
action.run();
if (unfinishedAuthorizationCount.decrementAndGet() == 0) {
adminManager.describeConfigsAsync(authorizedResources.stream().collect(Collectors.toMap(resource -> resource, resource -> Optional.ofNullable(request.configNames(resource)).map(HashSet::new))), namespacePrefix).thenApply(configResourceConfigMap -> {
configResourceConfigMap.putAll(failedConfigResourceMap);
resultFuture.complete(new DescribeConfigsResponse(0, configResourceConfigMap));
return null;
});
}
};
// Do authorization for each of resource
request.resources().forEach(configResource -> {
switch(configResource.type()) {
case TOPIC:
KopTopic kopTopic;
try {
kopTopic = new KopTopic(configResource.name(), namespacePrefix);
} catch (KoPTopicException e) {
completeOne.accept(() -> {
final ApiError error = new ApiError(Errors.UNKNOWN_TOPIC_OR_PARTITION, "Topic " + configResource.name() + " doesn't exist");
failedConfigResourceMap.put(configResource, new DescribeConfigsResponse.Config(error, Collections.emptyList()));
});
return;
}
String fullTopicName = kopTopic.getFullName();
authorize(AclOperation.DESCRIBE_CONFIGS, Resource.of(ResourceType.TOPIC, fullTopicName)).whenComplete((isAuthorized, ex) -> {
if (ex != null) {
log.error("DescribeConfigs in topic authorize failed, topic - {}. {}", fullTopicName, ex.getMessage());
completeOne.accept(() -> failedConfigResourceMap.put(configResource, new DescribeConfigsResponse.Config(new ApiError(Errors.TOPIC_AUTHORIZATION_FAILED, null), Collections.emptyList())));
return;
}
if (isAuthorized) {
completeOne.accept(() -> authorizedResources.add(configResource));
return;
}
completeOne.accept(() -> failedConfigResourceMap.put(configResource, new DescribeConfigsResponse.Config(new ApiError(Errors.TOPIC_AUTHORIZATION_FAILED, null), Collections.emptyList())));
});
break;
case BROKER:
// Current KoP don't support Broker Resource.
// but we are not exposing anything to the client, so it is fine to serve requests.
completeOne.accept(() -> authorizedResources.add(configResource));
break;
case UNKNOWN:
default:
completeOne.accept(() -> log.error("KoP doesn't support resource type: " + configResource.type()));
break;
}
});
}
Aggregations