AWS CloudFrontの署名付きURLを使ってみる (+ AWS CLIでCloudFrontの署名付きURLを作る)
CloudFrontの機能で、一定時間のみS3バケットに対してPUT/GET可能なURLを作って使ってみます
手順1. キーペアを作成
以下コマンドで公開鍵 public_key.pem
と秘密鍵 private_key.pem
を作成。
公開鍵の中身は -----BEGIN PUBLIC KEY-----
で始まる文字列。秘密鍵の中身は -----BEGIN RSA PRIVATE KEY-----
で始まる文字列。
以下の記事を参考にさせていただきました。
【AWS】CloudFrontで署名付きURLの設定方法(プライベートコンテンツの配信) - Qiita
手順2. CloudFrontにパブリックキーを登録
CloudFrontの画面 → 左メニューの『パブリックキー』 → 右上の『パブリックキーを作成』ボタンを押す。
名前は任意のものを入力し、キーは public_key.pem
の中身をコピペする。
作成が完了したら、パブリックキー一覧の『ID』列の値 (K始まり14桁) をメモしておく。
手順3. CloudFrontのキーグループを作成
CloudFrontの画面 → 左メニューの『キーグループ』 → 右上の『キーグループを作成』ボタンを押す。
名前は任意のものを入力する。パブリックキーは先程作成したものを選択する。
手順4. S3バケットを作成
パブリックアクセス不可のS3バケットが必要なので作成する。
「パブリックアクセスをすべてブロック」がチェックONならば、それ以外の設定はデフォルトでOK。(現時点では全部デフォルトでいいはず)
手順5. CloudFrontディストリビューションを作成
CloudFrontの画面 → 左メニューの『ディストリビューション』 → 右上の『ディストリビューションを作成』ボタンを押す。
以下の通りに入力してディストリビューションを作成する。記載が無い箇所は任意でよい。
オリジン
- オリジンドメイン … 先程作成したS3バケットのドメインを選択
- オリジンパス … 任意、このサンプルでは空欄
- S3バケットアクセス … 「はい、OAIを使用します (バケットは CloudFront のみへのアクセスとなるように制限できます)」
- オリジンアクセスアイデンティティ … 「新しいOAIを作成」ボタンを押して任意の名前で作成
- バケットポリシー … 「はい、バケットポリシーを自動で更新します」
OAIを使用することで、パブリックアクセス不可のバケットにCloudFront経由でアクセスできるようになる。併せてバケットポリシーの方でOAIのアクセスを許可する必要があるが、バケットポリシーを自動更新するよう選択しておけば自動でやってくれる。
デフォルトのキャッシュビヘイビア
- ビューワープロトコルポリシー … 任意、ここでは「HTTP and HTTPS」
- 許可されたHTTPメソッド … ここでは「GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE」
- ビューワーのアクセスを制限する … 「Yes」
- 信頼された認可タイプ … 「Trusted key groups (recommended)」
- キーグループを追加 … 先程作成したキーグループを選択
- キャッシュキーとオリジンリクエスト … 「Cache policy and origin request policy (recommended)」
- キャッシュポリシー … 任意、ここでは「CachingDisabled」
- オリジンリクエストポリシー … 任意、ここでは未設定
「ビューワーのアクセスを制限する」は過去に「Restrict Viewer Access」と呼ばれていたもので、Yesにすると署名付きURL以外でのアクセスを拒否するようになる。Yesにしないと署名付きURLの意味が無いのでYesにする。
許可されたHTTPメソッドで「GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE」を選択すると、CloudFrontの署名付きURLでファイルのGETだけでなくPUTも行えるようになる。ただしバケットポリシーに手動で設定を追加する必要があるので、次項の手順を必ず行うこと。ファイルのGETしか行わない場合は「GET, HEAD」でよい。
キャッシュとオリジンリクエストの設定は任意だが、動作確認するならキャッシュは無効化しておいた方が楽かも。オリジンリクエストを設定するなら、リクエストヘッダ Host
を転送しないように注意。詳しくは下記の記事を参照。
CloudFrontのS3 Originにはhostヘッダーを転送してはいけない - KAYAC engineers' blog
手順6. バケットポリシーを修正 (PUTを行う場合)
S3の画面 → CloudFront経由でアクセスするバケット → 上部の『アクセス許可』タブを押す。ページ中央上部あたりに表示されているバケットポリシーは以下の通りのはず。
これは前項のCloudFrontディストリビューション作成時に設定した「はい、バケットポリシーを自動で更新します」による設定で、OAIによるアクセスを許可している。
ただし Action
で s3:GetObject
しか許可されていないので、このままだとCloudFront経由でのPUTが行えない。Access Denied
と言われて弾かれてしまう。
なのでバケットポリシー右上の『編集』ボタンを押し、以下の通りバケットポリシーの Action
を配列に変更して s3:PutObject
を追加して保存する。
以上で準備は完了。
動作確認
ここではAWS CLIの aws cloudfront sign
コマンドを使ってCloudFrontの署名付きURLを作り、ファイルのGETとPUTを行ってみる。
sign — AWS CLI 2.4.9 Command Reference
署名付きURLを作るときは、オプション url
でアクセス先のURLを、key-pair-id
でキーペアIDを、private-key
で秘密鍵のファイルパスを、date-less-than
で有効期限を指定する必要がある。
以下のコマンドは、CloudFront経由のURL https://dxxxxxxxxxxxxx.cloudfront.net/example.txt
にキーペア KXXXXXXXXXXXXX
で署名した署名付きURLを発行するもの。このコマンドは公開鍵 private_key.pem
が存在するディレクトリで実行すること。オプション date-less-than
は、ここではUNIX時間で現在日時の1時間後を指定している。
成功すると、以下のような署名付きURLが作成される。
では、署名付きURLの期限が切れる前に動作確認を行っていく。
以下コマンドで、動作確認用のテキストファイル piyopiyo
を作成して署名付きURLにPUTする。署名付きURLは、署名に記号がいっぱい含まれてるのでダブルクォーテーションで囲うこと。
ステータスコード200で成功した場合、S3バケットにオブジェクト example.txt
が作成されているはず。作成されるオブジェクト名は、ローカルのファイル名に関わらず署名付きURLの発行時にURLとして指定したものになる。
リクエストヘッダに X-Amz-Acl: bucket-owner-full-control
を付与してるのは、オブジェクトの所有者をバケットに移すことで、他のプログラムから当該オブジェクトを操作できるようにするため。この記事ではコマンドラインからしか操作しないので、実際のところ必須ではないけど、知ってた方がいいのでつけておいた。詳しくは以下のページを参照。
S3 のオブジェクトの所有権を使用したアップロードされたオブジェクトの所有権の管理 - Amazon Simple Storage Service
次に以下コマンドで、当該ファイルをGETして表示してみる。
そしたら最初にPUTしたファイルの内容と同じ ぴよぴよ
が表示されるはず。
以上で動作確認は完了。
なお、有効期限切れ後の署名付きURLにアクセスすると、ステータスコード403と以下のレスポンスボディが返却される。