0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWSのS3署名付きURLを利用してハマったこと

Posted at

はじめに

外部クラウドストレージにアップロードしたファイルを、期限付きでダウンロード可能とする機能。これがAWSのS3だと簡単にできる。だが、いざやってみたらハマったのでここに備忘として残す。

公式の文献

デフォルトでは、すべての Amazon S3 オブジェクトはプライベートであり、オブジェクトの所有者のみがアクセスできます。ただし、オブジェクトの所有者は、署名付き URL を作成することで、他のユーザーとオブジェクトを共有できます。署名済み URL は、セキュリティ認証情報を使用してオブジェクトをダウンロードするアクセス許可を期限付きで付与します。署名付き URL をブラウザに入力するか、プログラムで使用してオブジェクトをダウンロードできます。署名付き URL で使用される認証情報は、URL を生成した AWS ユーザーのものです。

S3でパブリックアクセスなしのプライベートで作成しても、署名付きURLを生成することで、期限をつけて対象オブジェクト(ファイル)だけ公開できると言っている。

S3 コンソールの使用
Amazon S3 コンソールで次の手順に従い、オブジェクトを共有するための署名付き URL を生成できます。コンソールを使用した場合、署名付き URL の最大有効期限は作成時点から 12 時間です

AWS CLI を使用する場合
次の例では、AWS CLI コマンドにより、Amazon S3 バケットのオブジェクトを共有するための署名付き URL を生成します。AWS CLI を使用する場合、署名付き URL の最大有効期限は、作成時点から 7 日間です。

AWS CLIで作ると7日間の期限を設定できるが、マネジメントコンソールからだと12時間期限しか設定できない。であればAWSCLIで作る他ない。

CloudShellを開いて、公式サイトに記載されている以下コマンドを実行する。

aws s3 presign s3://my-bucket/testdir/mydoc.txt --expires-in 604800

しかしアクセスするとエラーとなり、そもそも共有できていない。
そこで公式の文献を改めて読むと以下記載が・・・。

注記
2019 年 3 月 20 日より後に開設されたすべての AWS リージョンでは、リクエストで endpoint-url と AWS リージョンを指定する必要があります。すべての Amazon S3 のリージョンとエンドポイントのリストについては、「AWS 全般のリファレンス」の「リージョンとエンドポイント」を参照してください。

aws s3 presign s3://amzn-s3-demo-bucket/mydoc.txt --expires-in 604800 --region af-south-1 --endpoint-url https://s3.af-south-1.amazonaws.com

なんじゃそれ、というわけで、リージョン名を記載して再度以下コマンドを実行。

aws s3 presign s3://my-bucket/testdir/mydoc.txt --expires-in 604800 --region ap-northeast-1 --endpoint-url https://s3.ap-northeast-1.amazonaws.com

実行するとプロンプトが返り、同時に以下のようなURLが生成される。

https://s3.ap-northeast-1.amazonaws.com/my-bucket/testdir/mydoc.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=XXXXX%2F20250513%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Date=YYYYMMDDDHHSSZ&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=XXX

これが署名付きURLとなる。このURLにブラウザなどでアクセスすると、s3://my-bucket/testdir/mydoc.txtの内容を参照することができた。
だがしかし、ここでまた困ったことが。

5~10分で期限が切れて見れなくなる

ようやく署名付きURLでS3にアップロードしたファイルを見れるようになったと思いきや、数分で期限切れに。AWSCLIで署名付きURLを生成したら、7日間まで見れるんじゃないの?という期待はあっさり裏切られた。

そこで調べると以下ブログ記事を発見。

・AWS Identity and Access Management (IAM) インスタンスプロファイル: 最大 6 時間有効
・AWS Security Token Service (STS): 最大 36 時間有効 (AWS アカウントユーザーや IAM ユーザーの認証情報など、永続的認証情報を使用して署名した場合)
・IAM ユーザー: 最大 7 日間有効 (AWS 署名バージョン 4 を使用した場合)

という記述があることから最大 7 日間なのかーという部分しか確認せずにExpiresIn=604800を指定してみましたが、残念ながら有効期限より前に失効する状況は改善しませんでした。

それもそのはずで、よく読めば利用している認証情報で有効期限の最大値が決まり、その最大値で有効期限が失効するということになります。

AWS LambdaだとIAM role を利用しているので、AssumeRole アクションにてAWS STS から一時トークンを取得し、その一時トークンで認証を行なっていることになります。

そのため、上記ドキュメントに記載のSTS 利用時に合致し指定している7日を待たずに失効する形になっていました。

なんとまあ難しい制約で、ブログ主の方のようにLambdaを使った場合や、私のようにCloudShellを使って署名付きURLを生成した場合、AWS Security Token Service (STS)の認証を使ったと判断され、7日間分である604800秒を指定しても、その指定時間は無視されてしまう。STSは最大 36 時間有効のURLを生成できるが、デフォルト値がおそらく5-10分でそれが適用されてしまう、というからくり。

IAM ユーザー: 最大 7 日間有効 (AWS 署名バージョン 4 を使用した場合)

上記の記載の通り、IAMユーザーかつAWS署名バージョン4.で署名付きURLを生成する必要がある。

というわけで対応

自分のクライアント、端末にAWSCLIをインストールする。

IAMで利用するIAMユーザーの作成(コンソールログインなし)

署名付きURL生成専用ユーザーを作る。自分の普段使っているユーザーでもよいが、強めの権限がついていると、漏れた時に特権を取られるので、署名付きURL専用ユーザーを別途作る。
image.png

S3読取IAMポリシー作成

先に作成した署名付きURL専用ユーザーの権限を作成する。ポリシーの作成をクリック。
image.png


リソースをアップロードしたS3バケットのみにGetとListが操作できる権限を指定して、バケット配下をアスタリスクですべて許可しているが、ディレクトリもさらに限定して許可範囲を絞りたい場合、さらにResource部分のS3のARNを追記修正する。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:Get*",
                "s3:List*"
            ],
            "Resource": [
                "arn:aws:s3:::my-bucket",
                "arn:aws:s3:::my-bucket/*"
            ]
        }
    ]
}

IAMで利用するIAMユーザーにポリシー割り当て

署名付きURL生成専用ユーザーに、S3読取IAMポリシーを割り当てる。
当該IAMユーザーのIAM設定画面で、以下のようにIAMポリシーを追加する。
image.png

IAMで利用するIAMユーザーにアクセスキーを生成

署名付きURL生成専用ユーザーにアクセスキーとシークレットキーを生成する。当該IAMユーザーのIAM設定画面で、以下のように生成。

セキュリティ認証情報をクリック。
image.png


アクセスキーを生成をクリック。
image.png


CLIを選択。
image.png


アクセスキーとシークレットキーを生成したら、絶対に漏れない場所にアクセスキーとシークレットをメモしておく。漏れたら再生成する。
image.png


クライアントのAWSCLIに認証情報(変数)を指定

注意)わたしの環境はWindowsクライアントのコマンドプロンプトを使っています。

$ aws configure
AWS Access Key ID [None]: AWS_ACCESS_KEY_ID
AWS Secret Access Key [None]: AWS_SECRET_ACCESS_KEY
Default region name [None]: AWS_DEFAULT_REGION
Default output format [None]: 

Default output formatは自由。
アクセスキーとシークレットを変数に指定したら、次に移る。

クライアントのAWSCLIにて、現在のセッションのみにアクセスキーを設定

お使いのクライアントのOS環境に応じて、コマンドは変更。ここでIAMで生成したアクセスキーとシークレットを「=」以降に入力する。

set AWS_ACCESS_KEY_ID=AKIXXXXXXXXX
set AWS_SECRET_ACCESS_KEY=ZZZZZZZZZZZZZ
set AWS_DEFAULT_REGION=ap-northeast-1

ap-northeast-1は自身のリージョンに変更。

AWS CLI のS3 署名にsigv4 を利用するように設定

現在はデフォルトでS3署名をsigv4になっているそうだが、念のために実施しておく。
Default プロファイルの場合、以下。

aws configure set default.s3.signature_version s3v4

個別のプロファイルの場合、以下。

aws configure set profile.your_profile_name.s3.signature_version s3v4

S3確認

認証情報の設定ができたため、対象S3にアクセスができるかを確認する。

aws s3 ls s3://my-bucket/testdir/

2025-05-08 20:51:49          0
2025-05-08 21:17:23     204995 mydoc.txt

署名付きURL(7日間期限)発行

署名付きURL生成専用ユーザーで認証情報が通ったため、署名付きURLを発行する。
604800は7日間の秒換算となる。

aws s3 presign s3://my-bucket/testdir/mydoc.txt --expires-in 604800 --region ap-northeast-1 --endpoint-url https://s3.ap-northeast-1.amazonaws.com

実行するとプロンプトが返り、同時に以下のようなURLが生成される。

https://s3.ap-northeast-1.amazonaws.com/my-bucket/testdir/mydoc.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIXXXX%2F20250513%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Date=YYYYMMDDDHHSSZ&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=XXX

これが署名付きURLとなる。t?X-Amz-Algorithm=AWS4-HMAC-SHA256&がS3 署名にsigv4 を利用している意味となる。
X-Amz-Credential=AKIXXXXにアクセスキーが入る。これで7日間期限の署名付きURLを生成することができた。

注意

署名付きURL生成専用ユーザーでアクセスキーとシークレットキーを生成したが、アクセスキー生成は漏洩して特権を奪われた事件などがあり、AWSが非推奨としている。非推奨にしているからといって、署名付きURL生成してすぐに(7日間期限以内に)アクセスキーを消すと、署名付きURLが見れなくなる。このため、7日間期限が終わってからアクセスキーを消すようにする。仮に漏洩してもIAMポリシーでS3の参照権限だけにしているため、大きな問題はないが・・・。
image.png


まとめ

「AWSだと簡単にできますよ!」というのは、驕り。世の中そんな簡単じゃない。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?