当前位置: 首页 > 知识库问答 >
问题:

使用AWS Java SDK v2从AWS EKS获取身份验证令牌

艾飞宇
2023-03-14

如何使用AWS Java SDK V2从AWS EKS获得Kubernetes身份验证令牌?一个身份验证令牌,然后可以使用Kubernetes SDK与Kubernetes进行身份验证。换句话说,我希望从EKS获得一个身份验证令牌,用于对Kubernetes进行身份验证,这样我就不必创建“Kube配置”。

我实际上得到了一个使用AWS Java SDK v1(而不是v2)的解决方案,查看下面开放问题中的代码示例。这里还有一个Python代码示例,但我在AWS Java SDK V2中没有取得任何成功。我尝试用AWS Java SDK V2来实现这一点:

java prettyprint-override">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);
    }
}

AWS Java SDK v1版本如下所示:(来自前面提到的开放问题)

我让它工作了,但我很难得到类似于在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;
        }
    }

共有1个答案

徐卓
2023-03-14

好吧,我终于让它起作用了。

AWS Java SDK v2版本:

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

问题出在我的STS终结点URI中:

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);
    }
}
.signingClockOverride(Clock.systemUTC())

这并不是必需的,但是最初的AWS Java SDK v1在指定sdkclock.standard时确实使用了时钟,而我在AWS Java SDK v2版本中使用的zoneddatetime确实使用了UTC时区。

 类似资料:
  • 我询问了如何建立一个服务呼叫,并在HttpClient上获得了一个很好的信息。然而,虽然这个问题在技术上得到了回答,但我还是被卡住了。 在控制台中,我可以看到我的浏览器向服务发送了什么请求来获取授权令牌。然而,当我尝试在我的服务层中模拟构建请求的调用时,我得到以下错误消息。我在这里犯错的可能性很大。不知道该用谷歌搜索什么,真的。。。 "StatusCode: 500, ReasonPhrase:'

  • 我有一个Rest Spring BootAPI,当用户验证API返回令牌jwt时,我在浏览器中注意到该令牌出现在响应头中 如何通过Reactjs将此令牌存储在本地存储浏览器中? 我的请求代码如下所示:

  • 我有一个LaravelAPI(实际上是LumenAPI)服务于VueJS前端。Vue应用程序允许用户登录到谷歌。然后将Google令牌发送回Lumen API,后者使用Google验证令牌,然后验证电子邮件地址是否为有效用户。然后它生成一个令牌,与用户一起存储在数据库中,并返回用户对象。 我没有使用Passport或jwt auth之类的东西。那么现在,我如何使用默认的Auth中间件来验证(现在已

  • 这是我第一次尝试使用API,API被称为OPS。我希望在python代码中使用API(OAuth 2)获取信息。 资源URL为:http://ops.epo.org/3.2/rest-services/register/{publication}/{EPODOC}/{EP2814089}/biblio 我还收到了: 消费密钥: O220VlTQqA修改fiedsf0YeqgM6c 消费者秘密密钥:

  • 我正在开发一个移动网站,托管Node.js / Express,并通过Firebase电话身份验证“轻微”保护。首次加载时,站点基本上是空的。在初始 Firebase Phone 身份验证后,JWT 令牌将通过 AJAX 调用发送到节点服务器。服务器检查令牌,验证用户是否已获得授权,然后发回站点的 html 内容。 到目前为止,一切都很好。这是保护简单单页Web应用程序上显示内容的好方法。 但这是

  • 我想使用boto3获取访问AWS服务的临时凭据。用例是这样的:我的Cognito用户池中的一个用户登录到我的服务器,我希望服务器代码为该用户提供访问其他AWS服务的临时凭据。 我有一个Cognito用户池,其中存储了我的用户。我有一个Cognito标识池,它不允许未经授权的访问,只允许来自Cognito用户池的用户访问。 下面是我开始的代码: 但是,仅运行这三行代码就会引发异常: 由于我的Cogn