はじめに
AWSを勉強していると、S3の署名付きURL(Presigned URL) という言葉を目にすることがあります。
一見すると単なる特殊なURLのように見えますが、実際にはAWSの認証情報を利用して、特定のS3オブジェクトへのアクセスを一時的に許可する仕組みです。
本記事では、WebアプリケーションからS3のファイルを取得するケースを例に、署名付きURLがどのように作られ、どのように利用されるのかを整理します。
1. そもそもS3のオブジェクトは誰でも取得できるわけではない
例えば、S3に次のようなファイルが保存されているとします。
my-bucket
└── documents
└── manual.pdf
S3バケットが非公開になっている場合、ユーザーが直接URLにアクセスしても通常はファイルを取得できません。
ブラウザ
↓
S3
↓
「アクセスする権限がありません」
しかし、Webアプリケーションでは次のような要件があります。
「ログインしているユーザーには、このPDFだけダウンロードさせたい」
そこで利用できるのが 署名付きURL(Presigned URL) です。
2. 署名付きURLとは?
署名付きURLとは、簡単にいうと
AWSの権限を持つアプリケーションが生成する、一時的なS3アクセス用URL
です。
URLには単なるファイルの場所だけではなく、AWS Signature Version 4(SigV4)に基づく署名情報などが含まれています。
概念的には次のようなURLになります。
https://my-bucket.s3.amazonaws.com/documents/manual.pdf
?X-Amz-Algorithm=AWS4-HMAC-SHA256
&X-Amz-Credential=...
&X-Amz-Date=...
&X-Amz-Expires=300
&X-Amz-SignedHeaders=host
&X-Amz-Signature=...
このURLを持っているユーザーは、設定された有効期限内であればS3へ直接アクセスしてオブジェクトを取得できます。
3. Webアプリケーションではどのように使われるのか
例えばWeb画面に
「PDFをダウンロード」
というボタンがあるとします。
ユーザーがボタンを押したとき、次のような処理が行われます。
ユーザー
│
│ ① ボタンを押す
▼
ブラウザ
│
│ ② APIサーバへリクエスト
▼
Web/APIサーバ
│
│ ③ 署名付きURLを生成
▼
ブラウザ
│
│ ④ 署名付きURLを受け取る
▼
S3
│
│ ⑤ 署名付きURLでアクセス
▼
ブラウザ
│
└─ ⑥ PDFを表示・ダウンロード
ここで重要なのは、
Web/APIサーバがPDFそのものをブラウザに返す必要はない
という点です。
Web/APIサーバは署名付きURLを生成してブラウザへ返すだけでも構いません。
4. 「ボタンを押す」と何が起きているのか
例えばユーザーがWeb画面で
「PDFを取得」
ボタンを押します。
するとブラウザからWeb/APIサーバへ次のようなリクエストが送られます。
GET /api/documents/manual
Web/APIサーバはユーザーの認証情報などを確認した上で、
「このユーザーにmanual.pdfへのアクセスを許可してよい」
と判断します。
その後、AWS SDKなどを利用して署名付きURLを生成します。
Web/APIサーバ
│
│ 署名付きURLを生成
▼
https://my-bucket.s3.../manual.pdf?...Signature=...
生成したURLをブラウザへ返します。
5. ブラウザは署名付きURLを使ってS3へアクセスする
ここからがポイントです。
ブラウザはWeb/APIサーバから受け取った署名付きURLを使って、S3へHTTPリクエストを送ります。
ブラウザ
│
│ GET
│ 署名付きURL
▼
S3
S3は受け取ったリクエストについて、署名が正しいかなどを確認します。
問題がなければ、
S3
↓
manual.pdf
↓
ブラウザ
という形でオブジェクトが返されます。
つまり、
ファイル本体はWeb/APIサーバを経由せず、ブラウザとS3の間で直接やり取りできる
ということです。
6. 署名付きURLには有効期限を設定できる
署名付きURLには有効期限を設定できます。
例えば、
X-Amz-Expires=300
とすると、概念的には300秒(5分)間有効なURLになります。
そのため、
「このURLを5分間だけ利用できるようにする」
といった制御が可能です。
有効期限を過ぎると、同じURLを使ってS3へアクセスしても取得できなくなります。
7. URLを知っている人ならアクセスできる
ここは署名付きURLを理解する上で重要なポイントです。
例えばユーザーAに署名付きURLを渡したとします。
ユーザーAがそのURLをユーザーBに共有した場合、ユーザーBも同じURLを使ってアクセスできます。
ユーザーA
│
│ 署名付きURLを共有
▼
ユーザーB
│
│ 同じURLを利用
▼
S3
つまり、
署名付きURLを知っている人は、そのURLが有効な間はアクセスできる
と考える必要があります。
そのため、必要以上に長い有効期間を設定しないことが重要です。
8. URLを書き換えて別のファイルを取得できる?
署名付きURLには、アクセス対象となるオブジェクトなどの情報も含めて署名されています。
例えば、
documents/manual.pdf
へのアクセス用に作られた署名付きURLを、
documents/secret.pdf
へ書き換えたとしても署名が一致しなくなります。
結果としてS3はアクセスを拒否します。
署名付きURL
↓
S3
↓
署名を検証
↓
内容が一致しない
↓
アクセス拒否
このように、
URLそのものだけではなく、リクエスト内容も署名によって保護されています。
9. なぜAWSのアクセスキーをユーザーに渡さなくていいのか
署名付きURLの大きなメリットの一つがこれです。
通常、AWS APIを利用する場合はAWSの認証情報が必要です。
しかし、一般ユーザーにAWSのアクセスキーやシークレットアクセスキーを渡すのは危険です。
署名付きURLでは次のような構成にできます。
AWS認証情報
↓
Web/APIサーバだけが保持
↓
署名付きURLを生成
↓
ユーザーへ渡す
つまり、
ユーザー自身がAWS認証情報を持つ必要がありません。
10. 「サーバ経由」と「S3への直接アクセス」の違い
WebアプリからS3のデータを取得する方法は署名付きURLだけではありません。
サーバ経由
ブラウザ
↓
Web/APIサーバ
↓
S3
↓
Web/APIサーバ
↓
ブラウザ
この場合、S3から取得したファイルをWeb/APIサーバが受け取り、それをブラウザへ返します。
署名付きURLを利用
ブラウザ
↓
Web/APIサーバ
↓
署名付きURL
↓
ブラウザ
↓
S3
↓
ブラウザ
この場合、Web/APIサーバはファイル本体を中継するのではなく、アクセス用の署名付きURLを発行する役割を担います。
11. 署名付きURLを使うメリット
特に大きなファイルを扱う場合、署名付きURLは非常に便利です。
例えば100MBのファイルを1,000人がダウンロードするとします。
サーバ経由の場合
S3
↓ 100MB
Web/APIサーバ
↓ 100MB
ユーザー
Web/APIサーバにもファイル転送の負荷がかかります。
署名付きURLを利用する場合
Web/APIサーバ
↓
署名付きURLだけ返す
ユーザー
↓ 100MB
S3
この構成では、
- Web/APIサーバの帯域使用量を削減できる
- サーバ負荷を軽減できる
- S3のスケーラビリティを活用できる
というメリットがあります。
12. 署名付きURLは「S3の権限を変更する」ものではない
ここも重要なポイントです。
署名付きURLを発行したからといって、
「S3のオブジェクトが公開された」
わけではありません。
S3のバケット自体は非公開のままで問題ありません。
イメージとしては次のようになります。
通常
↓
S3「この人にはアクセス権限がない」
署名付きURL
↓
S3「このリクエストは権限を持つ主体によって署名されている。
しかも有効期限内なので許可する」
つまり、
署名付きURLはS3の公開設定を変更する仕組みではなく、特定のリクエストに一時的なアクセス権を与える仕組み
と考えると理解しやすいです。
13. 全体像
ここまでの内容をまとめると、次のようになります。
┌──────────────┐
│ ユーザー │
└──────┬───────┘
│
│ ① ボタン押下
▼
┌──────────────┐
│ ブラウザ │
└──────┬───────┘
│
│ ② APIリクエスト
▼
┌──────────────┐
│ Web/APIサーバ │
│ │
│ AWS権限を持つ │
└──────┬───────┘
│
│ ③ 署名付きURL生成
▼
┌──────────────┐
│ ブラウザ │
└──────┬───────┘
│
│ ④ 署名付きURLでGET
▼
┌──────────────┐
│ S3 │
│ │
│ ⑤ 署名を検証 │
└──────┬───────┘
│
│ ⑥ オブジェクト返却
▼
┌──────────────┐
│ ブラウザ │
└──────────────┘
まとめ
S3の署名付きURLは、
AWSの権限を持つサーバが、特定のS3オブジェクトへのアクセスを一定期間だけ許可するURLを生成し、それをユーザーへ渡す仕組み
です。
ポイントは次の5つです。
- S3のオブジェクトを非公開のまま利用できる
- Web/APIサーバが署名付きURLを生成する
- 署名付きURLをブラウザへ返す
- ブラウザがそのURLを使ってS3へ直接アクセスする
- URLには有効期限があり、期限を過ぎると利用できない
特にWebアプリケーションでは、
「WebサーバがS3のファイルを取得してユーザーへ返す」のではなく、
「Webサーバが署名付きURLを発行し、ユーザーがS3から直接ファイルを取得する」
という構成を実現できることが、署名付きURLの大きな特徴です。
ファイル配信の負荷を下げつつ、安全に非公開データを配布したい場合に非常に有効な仕組みなので、S3を利用する際はぜひ理解しておきたい機能の一つです。