【问题标题】:java.lang.IllegalArgumentException: hostname cannot be null when trying to obtain AWS ECR Authentication Tokenjava.lang.IllegalArgumentException:尝试获取 AWS ECR 身份验证令牌时主机名不能为空
【发布时间】:2018-06-06 12:16:36
【问题描述】:

我正在尝试使用 aws-java-sdk 版本 1.11.339 从 AWS 获取 ECR 授权令牌。我创建了一个类,如下所示:

public class ECRTokenGetter {
    private static final Logger LOGGER = LoggerFactory.getLogger(ECRTokenGetter.class);
    private static final int SINGLE_ELEMENT_INDEX = 0;


    public static String getEcrAuthorisationToken(Credentials creds, String awsRegion, String registryId) {
        LOGGER.debug("Obtaining temporary authorisation credentials from AWS ECR");

        AmazonECR ecrClient = AmazonECRClientBuilder.standard()
                .withRegion(awsRegion)
                .withCredentials(new AWSStaticCredentialsProvider(new BasicSessionCredentials(
                        creds.getAccessKeyId(),
                        creds.getSecretAccessKey(),
                        creds.getSessionToken())))
                .build();
        return ecrClient.getAuthorizationToken(new GetAuthorizationTokenRequest()
                        .withRegistryIds(registryId))
                .getAuthorizationData().get(SINGLE_ELEMENT_INDEX)
                .getAuthorizationToken();
    }
}

不幸的是,在执行代码时,我收到以下异常:

Exception in thread "main" java.lang.IllegalArgumentException: hostname cannot be null
    at com.amazonaws.util.AwsHostNameUtils.parseRegion(AwsHostNameUtils.java:79)
    at com.amazonaws.util.AwsHostNameUtils.parseRegionName(AwsHostNameUtils.java:59)
    at com.amazonaws.auth.internal.AWS4SignerRequestParams.resolveRegion(AWS4SignerRequestParams.java:121)
    at com.amazonaws.auth.internal.AWS4SignerRequestParams.<init>(AWS4SignerRequestParams.java:103)
    at com.amazonaws.auth.AWS4Signer.sign(AWS4Signer.java:225)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1212)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1058)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:743)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:717)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:699)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:667)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:649)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:513)
    at com.amazonaws.services.ecr.AmazonECRClient.doInvoke(AmazonECRClient.java:1742)
    at com.amazonaws.services.ecr.AmazonECRClient.invoke(AmazonECRClient.java:1718)
    at com.amazonaws.services.ecr.AmazonECRClient.executeGetAuthorizationToken(AmazonECRClient.java:992)
    at com.amazonaws.services.ecr.AmazonECRClient.getAuthorizationToken(AmazonECRClient.java:966)
    at com.mycode.utils.ecr.aws.ECRTokenGetter.getEcrAuthorisationToken(ECRTokenGetter.java:27)
    at com.mycode.utils.ecr.AWSAuthTester.main(AWSAuthTester.java:32)

我还可以观察到 AWS SDK 创建的请求对象在入口点有一个 NULL 主机,如下图所示。

DefaultRequest 对象

我该如何解决这个问题?

【问题讨论】:

  • 我在客户端库版本 1.11.351 的 DynamoDB scan() 中遇到了类似的问题(1.11.351 很好)。

标签: java aws-java-sdk


【解决方案1】:

看来问题在于传递给 awsRegion 参数的字符串。在以下代码中

AmazonECR ecrClient = AmazonECRClientBuilder.standard()
            .withRegion(awsRegion)
            ...

如果 awsRegion 是一个字符串,它应该使用破折号作为分隔符,例如“我们-西-2”, 否则它应该使用 Regions 枚举,例如Regions.US_WEST_2。

替代解决方案涉及使用 withEndpointConfiguration 而不是 withRegion,例如

String ecrEndpoint = "ecr.%s.amazonaws.com";
AmazonECR ecrClient = AmazonECRClientBuilder.standard()
            .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(String.format(ecrEndpoint, awsRegion), awsRegion))
            ...

【讨论】:

    【解决方案2】:

    我刚刚遇到了同样的问题。

    问题在于 URL 有下划线 (_)。

    AmazonWebServiceClient类中有一个方法叫computeSignerByURI,在我使用的版本中,代码如下:

    private Signer computeSignerByURI(URI uri, String signerRegionOverride, boolean isRegionIdAsSignerParam) {
        if (uri == null) {
            throw new IllegalArgumentException("Endpoint is not set. Use setEndpoint to set an endpoint before performing any request.");
        }
        String service = getServiceNameIntern();
        String region = AwsHostNameUtils.parseRegionName(uri.getHost(), getEndpointPrefix());
        return computeSignerByServiceRegion(service, region, signerRegionOverride, isRegionIdAsSignerParam);
    }
    

    如您所见,在 URI 中有一个对 .getHost() 方法的调用,当它被计算时,它不接受下划线,因此它返回 nullHere 你可以检查一下。

    【讨论】:

    • 这很有帮助。错误消息令人困惑。
    【解决方案3】:

    枚举区域的值应使用其方法 getName() 转换为字符串。 否则枚举的方法 name()toString() 会返回一个值作为文本(带有大写字母和下划线):

    //Wrong conversion to a String
    System.out.println(Regions.US_EAST_1);                     // result: US_EAST_1
    System.out.println(String.format("%s",Regions.US_EAST_1)); // result: US_EAST_1
    System.out.println(Regions.US_EAST_1.toString());          // result: US_EAST_1
    System.out.println(Regions.US_EAST_1.name());              // result: US_EAST_1
    
    //Correct conversion to a String
    System.out.println(Regions.US_EAST_1.getName());           // result: us-east-1
    

    因此 - 为请求定义的 URL 无效:

    【讨论】:

      猜你喜欢
      • 2020-05-22
      • 2015-09-14
      • 1970-01-01
      • 2021-04-21
      • 2014-06-27
      • 2021-05-15
      • 2013-12-04
      • 2015-06-01
      • 2020-07-31
      相关资源
      最近更新 更多