问题
I am trying to obtain ECR authorisation token from AWS using aws-java-sdk version 1.11.339. I have created a class to do so as below:
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();
}
}
Unfortunately, when executing the code, I am getting following exception:
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)
I can also observe the request object created by AWS SDK has a NULL host in the entrypoint, as can be seen in the picture below.
DefaultRequest object
How can I overcome this issue?
回答1:
It appears that the issue lied down in the String passed to the awsRegion parameter. In the following code
AmazonECR ecrClient = AmazonECRClientBuilder.standard()
.withRegion(awsRegion)
...
if awsRegion is a String, it should use dashes as separators, e.g. "us-west-2", otherwise it should use Regions enum, e.g. Regions.US_WEST_2.
Alternative solution involves using withEndpointConfiguration instead of withRegion, e.g.
String ecrEndpoint = "ecr.%s.amazonaws.com";
AmazonECR ecrClient = AmazonECRClientBuilder.standard()
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(String.format(ecrEndpoint, awsRegion), awsRegion))
...
回答2:
I've just encountered the same issue.
The problem is that the URL has underscores (_
).
In the class AmazonWebServiceClient
there is a method called computeSignerByURI
, that in the version I am using, this is the code:
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);
}
As you can see, there is a call to the .getHost()
method in URI, that, when it's computed, it does not accept underscores, so, it returns null
. Here you can check that.
回答3:
Values of a enum Regions should be converted to Strings with its method getName(). Otherwise enum's method name() or toString() returns a value as a text (with capital letters and underscores):
//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
As a result - the URL, defined for the request, is invalid:
来源:https://stackoverflow.com/questions/50720197/java-lang-illegalargumentexception-hostname-cannot-be-null-when-trying-to-obtai