エンジニアのはしがき

プログラミングの日々の知見を書き連ねているブログです

S3の署名付きURLへリクエストする際の注意点

f:id:tansantktk:20211023211018p:plain

AWSを触って3年近くなりました。 勝手が分かってきた頃に便利な新サービスが登場したり、まだまだ学ぶことが多いなと思いながら最近はStepFunctionsを触っています。

さて、今回は先日S3のファイルを参照する際に微妙にハマってしまったことについて書いていきたいと思います。

やりたかったこと

  • AWS SDKでS3の署名付きURLを発行
  • 署名付きURLにGETリクエストしてS3のオブジェクトを取得する
  • S3のパブリックアクセスは全て禁止

セキュリティ上、外部から直接S3を参照させたくはないけど、必要な時に必要なオブジェクトのURLを発行して参照するという方法です。

数分で組めると高を括っていたところ、今回もハマりました🤤

まずはGETリクエスト用の署名付きURLの発行

下記はC#(.NET Core)での実装例です。 AmazonS3Client.GetPreSignedURL (GetPreSignedUrlRequest)を実行することで、S3をGETリクエストで参照する為の署名付きURLが発行できます。 設定した有効期限を超過するとリクエストは失敗します。

他の言語のAWS SDKでも似た名前のメソッドが実装されていると思います。

GetPreSignedUrlRequest request = new GetPreSignedUrlRequest
{
    // 参照バケット名
    BucketName = "<bucketName>",
    // 参照するS3のオブジェクトのパス
    Key = "<objectPath>",
    // 有効期限をDateTimeで指定
    Expires = DateTime.Now.AddMinutes(10)
};
urlString = s3Cli.GetPreSignedURL(request);

詳細な仕様は公式ドキュメントを参照ください。

docs.aws.amazon.com

あとはGETリクエストするだけなのですが、ここからが問題でした。

今回のハマりどころ

S3のCORS設定が必要

S3には「Cross-Origin Resource Sharing (CORS)」という設定があります。 GETリクエスト用の署名付きURLの場合、GETリクエストのCORSを許可するよう記載をしないと、PreflightリクエストでCORSエラーが返されてしまいます。

以下はGETリクエストのCORSを許可する設定です。

Cross-Origin Resource Sharing (CORS)

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]

AllowedOriginsを"*"にしている為、全てのオリジンのリクエストが許可されますが、あくまでサンプルとしての記述ですので、必要最低限のオリジンを設定しておく方が良いと思います。

不要なリクエストヘッダは外す

署名付きURLへGETリクエストする際、Authorizationヘッダ等を付けている場合、ステータスコード400でレスポンスされてしまいます。

フロントエンドで認証用に常にAuthorizationヘッダを付与する処理をリクエスト前に挟んでいたことが仇となりました。