aws-sdk-go: GetBucketLocation fails if region specified does not match the region the bucket is in.

There seems to be a regression of this issue: #380.

This is my code:-

awsSession := session.New()
s3Service := s3.New(awsSession, &aws.Config{
  LogLevel: aws.LogLevel(aws.LogDebugWithHTTPBody),
})

resp, err := s3Service.GetBucketLocation(&s3.GetBucketLocationInput{
  Bucket: aws.String(c.String("bucket")),
})
if err != nil {
  return cli.NewExitError(fmt.Sprintf("%s", err), 1)
}

When I set the AWS_REGION environment variable be different (us-east-1) to that of the bucket (eu-west-1), I get 403 errors:-

2016/06/11 15:06:31 DEBUG: Request s3/GetBucketLocation Details:
---[ REQUEST POST-SIGN ]-----------------------------
GET http://s3.amazonaws.com/s3up-test?location= HTTP/1.1
Host: s3.amazonaws.com
User-Agent: aws-sdk-go/1.1.34 (go1.6; darwin; amd64)
[… AWS auth headers …]
Accept-Encoding: gzip


-----------------------------------------------------
2016/06/11 15:06:32 DEBUG: Response s3/GetBucketLocation Details:
---[ RESPONSE ]--------------------------------------
HTTP/1.1 403 Forbidden
Transfer-Encoding: chunked
Content-Type: application/xml
Date: Sat, 11 Jun 2016 14:06:31 GMT
Server: AmazonS3
X-Amz-Id-2: EGxuZn97P1HxAYJQLVZBqsyFM3zxgdJd2G7oIR1gGK9fZ1MH2r7D0fMx3wZo4IGdPR1TS83oAyM=
X-Amz-Request-Id: 54E6B7601DD1DC3B

f3
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>54E6B7601DD1DC3B</RequestId><HostId>EGxuZn97P1HxAYJQLVZBqsyFM3zxgdJd2G7oIR1gGK9fZ1MH2r7D0fMx3wZo4IGdPR1TS83oAyM=</HostId></Error>
0


-----------------------------------------------------
AccessDenied: Access Denied
    status code: 403, request id: 54E6B7601DD1DC3B

When the region is correct, the output is this:-

2016/06/11 15:07:28 DEBUG: Request s3/GetBucketLocation Details:
---[ REQUEST POST-SIGN ]-----------------------------
GET http://s3-eu-west-1.amazonaws.com/s3up-test?location= HTTP/1.1
Host: s3-eu-west-1.amazonaws.com
User-Agent: aws-sdk-go/1.1.34 (go1.6; darwin; amd64)
[… AWS auth headers …]
Accept-Encoding: gzip


-----------------------------------------------------
2016/06/11 15:07:29 DEBUG: Response s3/GetBucketLocation Details:
---[ RESPONSE ]--------------------------------------
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/xml
Date: Sat, 11 Jun 2016 14:07:29 GMT
Server: AmazonS3
X-Amz-Id-2: yz1z8vs+rFrZA+aGKSwSfN/moPNPrDLeYPU4Zh/amT8HoIqhYq9c3MkwL0ixs3aqWFdP/Vgk5KQ=
X-Amz-Request-Id: D949FAF64D0BD627

89
<?xml version="1.0" encoding="UTF-8"?>
<LocationConstraint xmlns="http://s3.amazonaws.com/doc/2006-03-01/">eu-west-1</LocationConstraint>
0


-----------------------------------------------------
{
  LocationConstraint: "eu-west-1"
}

I should be able to use the API/SDK to determine the location of an S3 bucket without knowing the location of the S3 bucket, shouldn’t I?

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 19 (9 by maintainers)

Commits related to this issue

Most upvoted comments

Hi @matthew-andrews The S3 team got back with me and suggested the best API to use is HEAD bucket. GetBucketLocation uses a more complex permissions model where HeadBucket can be called by anyone. The bucket’s region will be returned as a X-Amz-Bucket-Region header.

The HEAD bucket request can be made regardless of request signing, so anonymous (unsigned) requests can be made requesting a bucket’s region.

I’m going to close this issue with this info. Please let us know if you have additional feedback, or issues.

After some discussion with AWS support I found out that the issue I was having with this behavior is the previously recommended solutions do NOT work when you are making cross account requests to HeadBucket and GetBucketLocation. A simple http HEAD does work and requires no credentials or cross account access in all cases for me. Here is my sample go code that I am now using:

func getBucketRegion(bucket string) (string, error) {
	url := fmt.Sprintf("https://%s.s3.amazonaws.com", bucket)
	res, err := http.Head(url)
	if err != nil {
		return "", err
	}
	return res.Header.Get("X-Amz-Bucket-Region"), nil
}

I’m not sure this issue should be closed. I can reproduce this still. If I have to set region to match the bucket location, what is the point of this API call at all? You can access the region from Config, and it must be set: https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config. At this point the only useful purpose to the API call would be to check if the bucket is in the current region and iterate all regions creating a new Session for each region until you found the right one. Hopefully I’m missing something obvious, but for now I’m heading towards the HEAD workaround.

I’m not sure this issue should be closed. I can reproduce this still. If I have to set region to match the bucket location, what is the point of this API call at all? You can access the region from Config, and it must be set: https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config. At this point the only useful purpose to the API call would be to check if the bucket is in the current region and iterate all regions creating a new Session for each region until you found the right one. Hopefully I’m missing something obvious, but for now I’m heading towards the HEAD workaround.

I agree, this should not have been closed. I have reproduced the problem just today when using this dependency:

	<dependency>
		<groupId>com.amazonaws</groupId>
		<artifactId>aws-java-sdk</artifactId>
		<version>1.11.747</version>
	</dependency>

Note: The suggested workaround above to use HeadBucket did not work for me using the Java API. It returned a 400 Bad Request when making the call on a bucket in a region different than the region used to create the AmazonS3 client.

A workaround which does work is to connect to each region in turn to determine which connection allows getBucketLocation to return without throwing an exception. The region which does not throw the exception is the region of the bucket. Pretty poor workaround but it does the job.

Hi @matthew-andrews We’s escalated this issue to the S3 Service team, and they are currently investigating. We’ll update once we have more information.

Hello @matthew-andrews, I’ve reached out to s3 to further investigate this issue. Please let us know if there is anything else we can do for you.