LoginSignup
0
0

More than 3 years have passed since last update.

aws-sdk-goでS3のオブジェクトを取得しようとして「SignatureDoesNotMatch」と言われたら

Last updated at Posted at 2020-05-13

signed urlを使っているわけでもないのにSignatureDoesNotMatchと言われる

ACLを設定していない、signed urlも使っていないバケットに対して接続してオブジェクトの取得をするコードを実装したら、 SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method. と言われてしまいました。
同じようなエラーにハマった人の手助けになれば幸いです。

TL;DR

  • バケット名に / を含めないようにする。

コード

コードは適当ですが雰囲気はこんな感じです.go
func hogehoge() error {
    config := aws.Config{
        Region: aws.String(os.Getenv("REGION")),
    }
    sess := session.New(&config)
    d := s3manager.NewDownloader(sess)
    n, err := d.Download(file, &s3.GetObjectInput{
        Bucket: aws.String("hogehoge/"), //!!!!!!!
        Key:    aws.String("piyopiyo/year=2020/month=04/fugafuga.gz"),
    })
    if err != nil {
        return err //エラーになる
    }
    fmt.Printf("downloaded %d bytes", n)
}

エラーになる場合と、ならない場合

コードに書いてある通りですが、バケット名の後ろに間違えて / をつけてしまっています。
このバケット名から / を取り除けばすべての場合において正しく動作します。
ただし、 / をつけていると、少し不思議な動作をしました。

エラーにならない

  • バケットに対してListObjects を実行し、オブジェクトのリストを取得できる。
  • 上記で取得したオブジェクトのメタ(keyとか)を参照できる。
  • keyに=を含まないS3オブジェクトをDLできる。

エラーになる

  • keyに=を含むS3オブジェクトがDLできない。

直接的な原因はわかりませんでしたが、aws-sdk-go内部の実装を見る限りS3オブジェクトをDLする際はGETリクエストを発行しているようですので、パラメータのURLencode時に =が悪さしているのではないかなと考えました。
https://github.com/aws/aws-sdk-go/issues/3110
また、こちらのissueで言及されているように、「バケット名として /= は使用できない。」というS3自体のルールがあります。
aws-sdk-goでもその前提に則って実装した結果、今回のように「DLできたり、できなかったりする」不思議な挙動が起きたのではないかと考えられます。:thinking:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0