-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GetBucketLocation fails if region specified does not match the region the bucket is in. #720
Comments
Hello @matthew-andrews, thank you for bringing this to our attention. I cannot reproduce this. I've tried creating a bucket in |
@matthew-andrews I've been trying to reproduce this issue. I'm only able to encounter the |
Hi, I've just tried again and can definitely reproduce the issue. I've created a reduced test case here:- Which I have also reproduced on CircleCI (click
The user is a plain empty AWS IAM user with no groups, no policies, etc. It is granted access to a bucket by a bucket policy attached to the bucket itself and that policy is this:-
I believe the go version on both my local system and in CircleCI is 1.6 and I think Circle probably pulls in this sdk from master. I just tested my local machine on Hope this helps! |
Hm, actually that's a different error isn't it… |
OK, try here — https://circleci.com/gh/matthew-andrews/s3-reduced/4 Click
|
Hello @matthew-andrews, I've reached out to |
Hi @matthew-andrews are you still encountering this issue? It may be helpful to ask on the S3 AWS forums. Other users may of experienced the issue you are encountering, and will help get more visibility with your issue with S3. |
I think it's a bug…? |
Hi @matthew-andrews I think this is a S3 service API issue, not SDK. This is why I was suggesting the S3 forums.
The Writing IAM Policies: How to Grant Access to an Amazon S3 Bucket blog post goes through the process needed to grant permission to a bucket, including permission to get a bucket's location. |
Ah you think the IAM permissions are wrong? I'll check that and get back to you. Apologies in advance if that's the case. |
I think that its a possibility, especially since you're able to get the bucket in one region but not another. I'm thinking that it is possible that there is a policy on the bucket that is limiting permissions to a specific region. |
Hi @matthew-andrews any luck identifying if this issue was caused by a policy rule? |
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. |
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 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. |
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:
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. |
Going to echo the previous sentiments and add some more. @jasdel can this be reopened? I just did some more testing with both the HeadBucket path and GetBucketLocation path. First, here is my code:
And here is the output:
You can see here using either method you must have your client region set to the region of the bucket for them to work. I feel like this is counterintuitive to a major (if not the primary) use case for GetBucketLocation: I have a bucket, but I do not know the region it exists in. |
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:
|
@metroidprototype, this approach will throw an error in case your bucket "mutates" the endpoint URL. The only working solution I found is to create a map of clients for each region, check where the bucket resides and use relevant client to perform operations on that bucket 🤯 🔫. Something like: package main
import (
"fmt"
"os"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
)
func main() {
var cli map[string]*s3.S3 = make(map[string]*s3.S3)
for _, partition := range endpoints.DefaultPartitions() {
for region := range partition.Regions() {
cli[region] = s3.New(session.Must(session.NewSession(&aws.Config{
Region: aws.String(region),
})))
}
}
r, err := cli["us-east-1"].ListBuckets(&s3.ListBucketsInput{})
if err != nil {
fmt.Println(err)
os.Exit(1)
}
for _, bucket := range r.Buckets {
l, err := cli["us-east-1"].GetBucketLocation(&s3.GetBucketLocationInput{
Bucket: bucket.Name,
})
if err != nil {
fmt.Println(err)
os.Exit(1)
}
var region string
if l.LocationConstraint == nil {
region = "us-east-1"
} else {
region = *l.LocationConstraint
}
o, err := cli[region].GetBucketTagging(&s3.GetBucketTaggingInput{
Bucket: bucket.Name,
})
if err != nil && !strings.Contains(err.Error(), "The TagSet does not exist") {
fmt.Println(err)
os.Exit(1)
} else if err == nil {
fmt.Println(o.TagSet)
}
}
} I believe the solution should be cross region calls (blog):
But I was not able to operate against |
There seems to be a regression of this issue: #380.
This is my code:-
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:-When the region is correct, the output is this:-
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?
The text was updated successfully, but these errors were encountered: