AWS Java SDK v2'yi kullanarak AWS EKS'den kimlik doğrulama jetonu alın


11

AWS Java SDK v2'yi kullanarak AWS EKS'ten Kubernetes kimlik doğrulama jetonunu nasıl alabilirim? Daha sonra bir Kubernetes SDK kullanarak Kubernetes ile kimlik doğrulaması yapmak için kullanılabilecek bir kimlik doğrulama belirteci. Başka bir deyişle, bir "kube config" oluşturmak zorunda kalmamam için Kubernetes ile kimlik doğrulaması için kullanmak üzere EKS'den bir kimlik belirteci almak istiyorum.

Aslında aşağıdaki açık sayıdaki kod örneklerine bakarak AWS Java SDK v1 (v2 değil) ile çalışan bir çözüm var . Ayrıca burada bir Python kodu örneği var ama AWS Java SDK v2 ile herhangi bir başarı elde edemiyorum. AWS Java SDK v2 ile yapmaya çalışıyorum:

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);
    }
}

Bir jeton oluşturur, ancak benim Kubernetes istemcimde (resmi Java Kubernetes SDK) jetonu kullandığımda "Yetkisiz" bir yanıt alırım - bu yüzden parmağımı koyamayacağım bir şey eksik ...

AWS Java SDK v1 sürümü şuna benzer: (Daha önce bahsedilen açık sayıdan )

Çalıştım, ama AWS Java SDK v2'de çalışmaya benzer bir şey elde etmek için mücadele ediyorum.

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;
        }
    }

AWS Java SDK v1 sorununda belirtildiği gibi, uygulama çok uzun bir son kullanma tarihi belirtmeye duyarlıdır. Son kullanma tarihi ile biraz oynadım, ancak sorunu çözmedi.
NS du Toit

jeton almak için aws-iam-authenticator yardımcı programını kullanmayı
denedin mi

Daha önce aws-iam-authenticator kullandım, ancak Java kaynak kodundan belirteçler üretebilmeliyim - hiçbir şey yüklemeden. Ve bu şeyleri AWS Java SDK v1 ile çalışmak için aldım, sadece SDK'nın v2 ile sorun yaşıyorum.
NS du Toit

Şu anda belirteci oluşturmak için AWS Java SDK v1 kullanıyorum - ama şimdi benim sınıf yolumda olması gerekir :( Bunu anlayabildiğim anda, SDK'nın v1'ini bağımlılıklardan çıkarabilirim :)
NS du Toit

Hangi Kubernetes sürümünü kullanıyorsunuz? Bu uygulama (küme dışında, içinde) çalıştırmak için nerede?
mewa

Yanıtlar:


2

Tamam, sonunda işe koyuldum.

AWS Java SDK v2 sürümü:

public static String getAuthenticationToken(AwsCredentialsProvider awsAuth, Region awsRegion, String clusterName) {
    try {    
        SdkHttpFullRequest requestToSign = SdkHttpFullRequest
                .builder()
                .method(SdkHttpMethod.GET)
                .uri(StsUtil.getStsRegionalEndpointUri(awsRegion))
                .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())
                .signingRegion(awsRegion)
                .signingName("sts")
                .signingClockOverride(Clock.systemUTC())
                .expirationTime(expirationDate.toInstant())
                .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 authentication token for cluster: " + clusterName;
        logger.error(errorMessage, e);
        throw new RuntimeException(errorMessage, e);
    }
}

Sorun benim STS uç nokta Uri oldu:

public static URI getStsRegionalEndpointUri(Region awsRegion) {
    try {
        return new URI("https", String.format("sts.%s.amazonaws.com", awsRegion.id()), "/", null);
    } catch (URISyntaxException shouldNotHappen) {
        String errorMessage = "An error occurred creating the STS regional endpoint Uri";
        logger.error(errorMessage, shouldNotHappen);
        throw new RuntimeException(errorMessage, shouldNotHappen);
    }
}

Not /olarak pathiçin (üçüncü) bağımsız değişken URInesne. AWS Java SDK v1 sürümü, URI'yi böyle oluşturmadı, ancak /başka bir yerde belirtti . Şimdi URIbir String olarak yazdırırsam https://sts.eu-west-1.amazonaws.com/, sorudaki orijinal sürüm yeni döndüğündehttps://sts.eu-west-1.amazonaws.com

Yeterince ilginç - orijinal sürüm de bir belirteç oluşturdu, ancak belirteç Kubernetes tarafından reddedildi. Son kullanma tarihi geleceğe çok Unauthorizedyakınsa , benzer bir davranış beklenebilir - bir jeton alırsınız, ancak Kubernetes hizmetinden bir yanıt alınmasına neden olur .

STS uç noktasını değiştirdikten sonra her şey çalıştı, ancak bir değişiklik daha yaptım:

Aşağıdaki satırı ekledim Aws4PresignerParams:

.signingClockOverride(Clock.systemUTC())

Bu gerekli değildir, ancak orijinal AWS Java SDK v1 o belirtildiğinde bir saatli bir şey mi yaptım SdkClock.STANDARDve ZonedDateTimeben AWS Java SDK'nın v2 sürümünde kullandığı UTC saat dilimini kullanır.


Yani evet, işe yaradı, ama arkasındaki akıl yürütme hakkında çok fazla bilgim yok. Olmadan bile /hala bir jetonum var, ancak belirtildiği gibi Kubernetes ile entegre olmaya başladığımda işe yaramadı.
NS du Toit

Bir başka ilginç kenara - orijinal AWS Java SDK v1 sorunu, tokenin çok kısa ömürlü olduğunu gösterdi. Son kullanma tarihini 60 saniyeden fazla bir süreye ayarlamaya çalıştığımda aynı şey olur - bir jeton alırım, ancak bir Unauthorizedyanıt verir.
NS du Toit
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.