Como posso obter um token de autenticação Kubernetes do AWS EKS usando o AWS Java SDK v2? Um token de autenticação que pode ser usado para autenticar com o Kubernetes usando um Kubernetes SDK. Em outras palavras, desejo obter um token de autenticação do EKS para usar na autenticação com o Kubernetes, para que não seja necessário criar uma "configuração do kube".
Na verdade, eu tenho uma solução trabalhando com o AWS Java SDK v1 (não v2), observando os exemplos de código na seguinte edição aberta . Também há um exemplo de código Python aqui, mas não estou tendo sucesso com o AWS Java SDK v2. Minha tentativa de fazer isso com o AWS Java SDK v2:
public static String getAuthenticationToken(AwsCredentialsProvider awsAuth, Region awsRegion, String clusterName) {
try {
SdkHttpFullRequest requestToSign = SdkHttpFullRequest
.builder()
.method(SdkHttpMethod.GET)
.uri(new URI("https", String.format("sts.%s.amazonaws.com", awsRegion.id()), null, null))
.appendHeader("x-k8s-aws-id", clusterName)
.appendRawQueryParameter("Action", "GetCallerIdentity")
.appendRawQueryParameter("Version", "2011-06-15")
.build();
ZonedDateTime expirationDate = DateUtil.addSeconds(DateUtil.now(), 60);
Aws4PresignerParams presignerParams = Aws4PresignerParams.builder()
.awsCredentials(awsAuth.resolveCredentials())
.expirationTime(expirationDate.toInstant())
.signingName("sts")
.signingRegion(awsRegion)
.build();
SdkHttpFullRequest signedRequest = Aws4Signer.create().presign(requestToSign, presignerParams);
String encodedUrl = Base64.getUrlEncoder().withoutPadding().encodeToString(signedRequest.getUri().toString().getBytes(CharSet.UTF_8.getCharset()));
return ("k8s-aws-v1." + encodedUrl);
} catch (Exception e) {
String errorMessage = "A problem occurred generating an Eks token";
logger.error(errorMessage, e);
throw new RuntimeException(errorMessage, e);
}
}
Ele gera um token, mas quando uso o token no meu cliente Kubernetes (o SDK oficial do Java Kubernetes) recebo uma resposta "Não autorizada" - por isso estou perdendo algo que não consigo identificar ...
A versão do AWS Java SDK v1 tem a seguinte aparência: (Na edição aberta mencionada anteriormente)
Eu trabalhei, mas estou tentando obter algo semelhante para trabalhar no AWS Java SDK v2.
private String generateToken(String clusterName,
Date expirationDate,
String serviceName,
String region,
AWSSecurityTokenServiceClient awsSecurityTokenServiceClient,
AWSCredentialsProvider credentialsProvider,
String scheme,
String host) throws URISyntaxException {
try {
DefaultRequest<GetCallerIdentityRequest> callerIdentityRequestDefaultRequest = new DefaultRequest<>(new GetCallerIdentityRequest(), serviceName);
URI uri = new URI(scheme, host, null, null);
callerIdentityRequestDefaultRequest.setResourcePath("/");
callerIdentityRequestDefaultRequest.setEndpoint(uri);
callerIdentityRequestDefaultRequest.setHttpMethod(HttpMethodName.GET);
callerIdentityRequestDefaultRequest.addParameter("Action", "GetCallerIdentity");
callerIdentityRequestDefaultRequest.addParameter("Version", "2011-06-15");
callerIdentityRequestDefaultRequest.addHeader("x-k8s-aws-id", clusterName);
Signer signer = SignerFactory.createSigner(SignerFactory.VERSION_FOUR_SIGNER, new SignerParams(serviceName, region));
SignerProvider signerProvider = new DefaultSignerProvider(awsSecurityTokenServiceClient, signer);
PresignerParams presignerParams = new PresignerParams(uri,
credentialsProvider,
signerProvider,
SdkClock.STANDARD);
PresignerFacade presignerFacade = new PresignerFacade(presignerParams);
URL url = presignerFacade.presign(callerIdentityRequestDefaultRequest, expirationDate);
String encodedUrl = Base64.getUrlEncoder().withoutPadding().encodeToString(url.toString().getBytes());
log.info("Token [{}]", encodedUrl);
return "k8s-aws-v1." + encodedUrl;
} catch (URISyntaxException e) {
log.error("could not generate token", e);
throw e;
}
}
Respostas:
Ok, finalmente consegui funcionar.
A versão do AWS Java SDK v2:
O problema estava no meu endpoint STS Uri:
Observe o
/
nopath
(terceiro) argumento para oURI
objeto. A versão do AWS Java SDK v1 não criou o URI assim, mas especificou o/
outro lugar. Se eu agora imprimir aURI
String como recebohttps://sts.eu-west-1.amazonaws.com/
, enquanto a versão original na pergunta acabou de retornarhttps://sts.eu-west-1.amazonaws.com
Interessante o suficiente - a versão original também gerou um token, mas o token foi rejeitado pelo Kubernetes. Deve-se esperar um comportamento semelhante se a data de validade estiver muito distante no futuro - você receberá um token, mas isso levará a uma
Unauthorized
resposta do serviço Kubernetes.Depois de alterar o ponto final do STS, tudo funcionou, mas fiz mais uma alteração:
Eu adicionei a seguinte linha ao meu
Aws4PresignerParams
:Não era necessário, mas o AWS Java SDK v1 original fazia algo com um relógio quando especificado
SdkClock.STANDARD
, e oZonedDateTime
que eu uso na versão do AWS Java SDK v2 usa o fuso horário UTC.fonte
/
eu ainda recebi um token, mas, como indicado, ele simplesmente não funcionou quando comecei a integrar o Kubernetes.Unauthorized
resposta.