ISSUE-25 Delegation tokens api
This commit is contained in:
parent
4bd5f7d9da
commit
6c9b2ae2f8
4 changed files with 175 additions and 1 deletions
|
@ -3,7 +3,9 @@ package com.provectus.kafka.ui.cluster.mapper;
|
|||
import com.provectus.kafka.ui.cluster.config.ClustersProperties;
|
||||
import com.provectus.kafka.ui.cluster.model.*;
|
||||
import com.provectus.kafka.ui.model.*;
|
||||
import java.util.Base64;
|
||||
import java.util.Properties;
|
||||
import org.apache.kafka.common.security.token.delegation.TokenInformation;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
|
@ -83,4 +85,24 @@ public interface ClusterMapper {
|
|||
return copy;
|
||||
}
|
||||
|
||||
default DelegationToken mapToken(
|
||||
org.apache.kafka.common.security.token.delegation.DelegationToken t) {
|
||||
final byte[] encoded = Base64.getEncoder().encode(t.hmac());
|
||||
final TokenInformation ti = t.tokenInfo();
|
||||
return new DelegationToken()
|
||||
.expiryTimestamp(ti.expiryTimestamp())
|
||||
.issueTimestamp(ti.issueTimestamp())
|
||||
.maxTimestamp(ti.maxTimestamp())
|
||||
.tokenId(ti.tokenId())
|
||||
.token(new String(encoded))
|
||||
.principal(mapPricipal(ti.owner()))
|
||||
.renewers(ti.renewers().stream().map(this::mapPricipal).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
default KafkaPrincipal mapPricipal(org.apache.kafka.common.security.auth.KafkaPrincipal principal) {
|
||||
return new KafkaPrincipal()
|
||||
.name(principal.getName())
|
||||
.type(principal.getPrincipalType());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.apache.kafka.clients.consumer.KafkaConsumer;
|
|||
import org.apache.kafka.clients.consumer.OffsetAndMetadata;
|
||||
import org.apache.kafka.common.TopicPartition;
|
||||
import org.apache.kafka.common.serialization.StringDeserializer;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
@ -180,4 +181,31 @@ public class ClusterService {
|
|||
.orElse(Flux.empty());
|
||||
}
|
||||
|
||||
public Mono<Long> expireToken(String clusterName, String tokenId) {
|
||||
final byte[] decodedId = Base64.getDecoder().decode(tokenId);
|
||||
return kafkaService.getOrCreateAdminClient(
|
||||
clustersStorage.getClusterByName(clusterName).orElseThrow()
|
||||
).flatMap(cl -> ClusterUtil.toMono(
|
||||
cl.getAdminClient().expireDelegationToken(decodedId).expiryTimestamp()
|
||||
));
|
||||
}
|
||||
|
||||
public Mono<Long> renewToken(String clusterName, String id) {
|
||||
final byte[] decodedId = Base64.getDecoder().decode(id);
|
||||
return kafkaService.getOrCreateAdminClient(
|
||||
clustersStorage.getClusterByName(clusterName).orElseThrow()
|
||||
).flatMap(cl -> ClusterUtil.toMono(
|
||||
cl.getAdminClient().renewDelegationToken(decodedId).expiryTimestamp()
|
||||
));
|
||||
}
|
||||
|
||||
public Flux<DelegationToken> getTokens(String clusterName) {
|
||||
return kafkaService.getOrCreateAdminClient(
|
||||
clustersStorage.getClusterByName(clusterName).orElseThrow()
|
||||
).flatMap(cl -> ClusterUtil.toMono(
|
||||
cl.getAdminClient().describeDelegationToken().delegationTokens()
|
||||
)).map(list ->
|
||||
list.stream().map(clusterMapper::mapToken).collect(Collectors.toList())
|
||||
).flatMapMany(Flux::fromIterable);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,4 +126,21 @@ public class MetricsRestController implements ApiClustersApi {
|
|||
.collectMap(Pair::getKey, Pair::getValue)
|
||||
.map(positions -> new ConsumerPosition(seekType != null ? seekType : SeekType.BEGINNING, positions));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ResponseEntity<Long>> expireToken(String clusterName, String id, ServerWebExchange exchange) {
|
||||
return clusterService.expireToken(clusterName, id).map(ResponseEntity::ok);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ResponseEntity<Flux<DelegationToken>>> getTokens(String clusterName,
|
||||
ServerWebExchange exchange) {
|
||||
return Mono.just(ResponseEntity.ok(clusterService.getTokens(clusterName)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ResponseEntity<Long>> renewToken(String clusterName, String id,
|
||||
ServerWebExchange exchange) {
|
||||
return clusterService.renewToken(clusterName, id).map(ResponseEntity::ok);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,6 +92,65 @@ paths:
|
|||
schema:
|
||||
$ref: '#/components/schemas/ClusterStats'
|
||||
|
||||
/api/clusters/{clusterName}/tokens:
|
||||
get:
|
||||
tags:
|
||||
- api/clusters
|
||||
operationId: getTokens
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/DelegationTokens'
|
||||
parameters:
|
||||
- name: clusterName
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
|
||||
|
||||
/api/clusters/{clusterName}/tokens/{id}:
|
||||
patch:
|
||||
tags:
|
||||
- api/clusters
|
||||
operationId: renewToken
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
delete:
|
||||
tags:
|
||||
- api/clusters
|
||||
operationId: expireToken
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
parameters:
|
||||
- name: clusterName
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
|
||||
|
||||
|
||||
/api/clusters/{clusterName}/brokers/{id}/metrics:
|
||||
get:
|
||||
tags:
|
||||
|
@ -657,4 +716,52 @@ components:
|
|||
value:
|
||||
type: string
|
||||
additionalProperties:
|
||||
type: number
|
||||
type: number
|
||||
|
||||
KafkaPrincipal:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
|
||||
CreateDelegationToken:
|
||||
type: object
|
||||
properties:
|
||||
maxLifeTime:
|
||||
type: integer
|
||||
format: int64
|
||||
renewers:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/KafkaPrincipal"
|
||||
|
||||
DelegationToken:
|
||||
type: object
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
description: base64 encoded token
|
||||
principal:
|
||||
$ref: "#/components/schemas/KafkaPrincipal"
|
||||
renewers:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/KafkaPrincipal"
|
||||
issueTimestamp:
|
||||
type: integer
|
||||
format: int64
|
||||
maxTimestamp:
|
||||
type: integer
|
||||
format: int64
|
||||
expiryTimestamp:
|
||||
type: integer
|
||||
format: int64
|
||||
tokenId:
|
||||
type: string
|
||||
|
||||
DelegationTokens:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/DelegationToken'
|
||||
|
|
Loading…
Add table
Reference in a new issue