Comment puis-je obtenir un jeton d'authentification Kubernetes auprès d'AWS EKS à l'aide d'AWS Java SDK v2? Un jeton d'authentification qui peut ensuite être utilisé pour s'authentifier auprès de Kubernetes à l'aide d'un SDK Kubernetes. En d'autres termes, je veux obtenir un jeton d'authentification d'EKS à utiliser pour l'authentification avec Kubernetes afin de ne pas avoir à créer une "configuration de kube".
J'ai en fait obtenu une solution fonctionnant avec AWS Java SDK v1 (pas v2) en regardant les exemples de code dans le problème ouvert suivant . Il y a aussi un exemple de code Python ici MAIS je n'ai aucun succès avec AWS Java SDK v2. Ma tentative de le faire avec 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);
}
}
Il génère un jeton, mais lorsque j'utilise le jeton dans mon client Kubernetes (le SDK Java Kubernetes officiel), je reçois une réponse "Non autorisé" - donc il me manque quelque chose sur lequel je ne peux pas mettre le doigt ...
La version AWS Java SDK v1 ressemble à ceci: (D'après le problème ouvert mentionné précédemment)
Je l'ai fait fonctionner, mais j'ai du mal à obtenir quelque chose de similaire à travailler dans 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;
}
}
Réponses:
D'accord, je l'ai finalement fait fonctionner.
La version AWS Java SDK v2:
Le problème était dans mon point de terminaison STS Uri:
Notez le
/
dans lepath
(troisième) argument de l'URI
objet. La version AWS Java SDK v1 n'a pas créé l'URI comme ça, mais a spécifié/
ailleurs. Si j'imprime maintenant le enURI
tant que chaîne que j'obtienshttps://sts.eu-west-1.amazonaws.com/
, alors que la version originale dans la question vient de revenirhttps://sts.eu-west-1.amazonaws.com
Assez intéressant - la version originale a également généré un jeton, mais le jeton a été rejeté par Kubernetes. On devrait s'attendre à un comportement similaire si la date d'expiration est trop éloignée dans le futur - vous obtiendrez un jeton, mais cela conduira à une
Unauthorized
réponse du service Kubernetes.Après avoir changé le point de terminaison STS, tout a fonctionné, mais j'ai fait un autre changement:
J'ai ajouté la ligne suivante à mon
Aws4PresignerParams
:Ce n'était pas nécessaire, mais l'AWS Java SDK v1 d'origine a fait quelque chose avec une horloge quand il l'a spécifié
SdkClock.STANDARD
, etZonedDateTime
celui que j'utilise dans la version AWS Java SDK v2 utilise le fuseau horaire UTC.la source
/
j'ai toujours un jeton, mais comme indiqué, cela n'a tout simplement pas fonctionné lorsque j'ai commencé à m'intégrer à Kubernetes.Unauthorized
réponse.