¿Cómo puedo obtener un token de autenticación de Kubernetes de AWS EKS con AWS Java SDK v2? Un token de autenticación que luego puede usarse para autenticarse con Kubernetes usando un SDK de Kubernetes. En otras palabras, quiero obtener un token de autenticación de EKS para usarlo para la autenticación con Kubernetes para no tener que crear una "configuración de kube".
De hecho, obtuve una solución trabajando con AWS Java SDK v1 (no v2) mirando los ejemplos de código en el siguiente número abierto . También hay un ejemplo de código Python aquí, PERO no estoy teniendo éxito con AWS Java SDK v2. Mi intento de hacerlo con 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);
}
}
Genera un token, pero cuando uso el token en mi cliente Kubernetes (el SDK oficial de Java Kubernetes) obtengo una respuesta "no autorizada", así que me falta algo que no puedo señalar ...
La versión AWS Java SDK v1 se parece a esto: (Del tema abierto mencionado anteriormente)
Lo hice funcionar, pero estoy luchando por obtener algo similar al trabajo en 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;
}
}
Respuestas:
Bien, finalmente lo conseguí funcionando.
La versión AWS Java SDK v2:
El problema estaba en mi punto final STS Uri:
Tenga
/
en cuenta elpath
argumento en el (tercer) para elURI
objeto. La versión AWS Java SDK v1 no creó el URI de esa manera, pero especificó el/
resto. Si ahora imprimo elURI
como una cadena que obtengohttps://sts.eu-west-1.amazonaws.com/
, mientras que la versión original en la pregunta acaba de regresarhttps://sts.eu-west-1.amazonaws.com
Lo suficientemente interesante: la versión original también generó un token, pero el token fue rechazado por Kubernetes. Uno debería esperar un comportamiento similar si la fecha de vencimiento está demasiado lejos en el futuro: obtendrá un token, pero dará lugar a una
Unauthorized
respuesta del servicio de Kubernetes.Después de cambiar el punto final STS, todo funcionó, pero hice un cambio más:
Agregué la siguiente línea a mi
Aws4PresignerParams
:No era necesario, pero el AWS Java SDK v1 original hizo algo con un reloj cuando lo especificó
SdkClock.STANDARD
, y elZonedDateTime
que uso en la versión AWS Java SDK v2 usa la zona horaria UTC.fuente
/
todavía obtuve un token, pero como se indicó, simplemente no funcionó cuando comencé a integrarme con Kubernetes.Unauthorized
respuesta.