プログラミングメカブログ

Adults cling to the past, Children want to escape to the future

プログラミングメカブログ

Adults cling to the past, Children want to escape to the future

1月

16

S3+CloudFrontで期限付きURL

  • POSTED BY 小谷松 丈樹 IN 創作
  • 1 Comment

期限付きURL

今回の要件としては、URLを時限式でexpireさせる事で、
URLを叩けばいくらでもアクセス出来るのを防ぐ事を目的としています。

AWS構成

  • EC2
  • S3
  • CloudFront

事前準備

CloudFrontのOriginをS3に向けてあり、
S3とCloudFrontのURLどちらを叩いても同じ内容が表示されている状態にしてあります。

テスト用に、Windows 7に標準で入ってる画像をアップロードしてあるので、アクセスしてみましょう。
スクリーンショット 2015-01-14 16.33.53
どちらも同じ内容が表示されます。

実装

構想

期限付きのURLをEC2から発行し、CloudFrontを経由してS3からコンテンツを取得し配信する。
CDP:Private Cache Distributionパターンというやつらしいです。

CloudFront、S3の設定変更

今はただアクセスするだけで表示されてしまうので、
設定を変更し、署名付きのURLでないとアクセスが出来ないように、
AWSコンソールから各設定の変更を行います。

CloudFront

まずはCloudFrontの Originsタブ から、基本設定を変更します。
スクリーンショット 2015-01-16 10.38.38

  • Restrict Bucket Access
    • YesにするとS3に対するアクセス制限をかけられる
  • Origin Access Identity
    • CloudFrontがS3にアクセスするために必要なID Yesにすると新規作成
  • Grant Read Permissions on Bucket
    • YesにするとS3の設定(Bucket Policy)をCloudFrontから自動で書き換える

次に Behaviorsタブ から、動作設定を変更します。
スクリーンショット 2015-01-14 18.38.50
この一番下の、Restrict Viewer Access(Use Signed URLs) が今回のキモとなる設定です。
これを「Yes」にすると、新しい設定項目が出てきます。
スクリーンショット 2015-01-14 18.54.52
Trusted Signers 説明:Choose whether you want to use the current AWS account and/or other AWS accounts to create signed URLs.
うーん。。。Specify Accountsに変更するシーンってどんなのだろう?
大規模で他社が絡む開発とか?何かしらの政治的な理由?うーむ・・・
とりあえず、同一アカウントから署名付きURLを発行するので、Selfとして設定完了です。

反映されるまで、少し時間がかかるようです。
CloudFrontの表示を更新して、署名キーが無いため表示されない事を確認。
スクリーンショット 2015-01-14 19.25.03
CloudFrontの方はこれで設定完了です。

S3

S3の方はまだ見られる状態なので、いくらCloudFront経由のアクセスに制限がかけられても、
S3に直でアクセスされたら普通に表示されてしまうためアウトです。

バケット名を右クリックして Properties を開いて、Edit bucket policy で設定を変更します。
スクリーンショット 2015-01-16 11.34.59

すると Bucket Policy Editor が開かれて、JSON形式の設定情報が表示されます。

Statementの14行目以下が、CloudFrontの設定変更により自動で付け加えられた設定でしょう。
おそらく上位優先でアクセスの許可が下りてしまい、まだ表示が可能のようですね。
という事で、マークが付いてる5〜13行目の設定を消して設定をすると・・・
スクリーンショット 2015-01-16 11.46.42
403 Forbidden。これで普通にアクセスするだけで表示する事は出来なくなりました。

CloudFront 暗号化鍵

署名付きURLを作成するために、CloudFront用のキーペアを取得する必要があります。
スクリーンショット 2015-01-16 12.05.50

アカウントのプルダウンメニューから Security Credentials をクリックして、
CloudFront Key Pairs のメニューから、Create New Key Pair をクリック。
スクリーンショット 2015-01-16 12.11.04
秘密鍵(pk-xxxx.pem)、公開鍵(rsa-xxxx.pem)共にダウンロードしておきましょう。
公開鍵は別にダウンロードしなくてもいいのかな?以後登場しません。
で、秘密鍵はEC2内のどこかに適当に配置しておきましょう。

開発

さて、では準備が完了したのでSDKの説明書きを参考に開発を進めます。
といっても、署名付きURLを作る、というための項目が既に用意されていますね。
Signing CloudFront URLs for Private Distributions を見て、下記の通り10行足らずで実装可能でした。

ソースのポイントとしては、

  • $_cf_accesskey_id が、ダウンロード直後の秘密鍵ファイル名とキーペアIDと一緒だから、ダウンロードしたのをそのまま任意のディレクトリに置けば良い
  • 期限付きURLにランダムな値をパラメータとして付与する事で、実行の度に別のURLを作成出来る
  • 動画をストリーミングで取得する場合は、$cloudFront->getSignedUrl() に渡すURLのプロトコルを ‘rtmp://’ とすれば良い

という感じでしょうか。

実行

先のソースを key.php として保存して実行。

なっがーいURLが出力されました。
上記が署名&期限付きのURLとなります。
では早速アクセスしてみましょう。
スクリーンショット 2015-01-16 15.52.37
表示されました!

では、先のソースでは strtotime('+1 minutes') として、
1分間の期限を設けていたので、1分待ってもう一度アクセスしてみましょう。
スクリーンショット 2015-01-16 15.56.06

うんうん、アクセス拒否のXMLが出力されました。期限付きURLはちゃんと機能していますね。

余談

CloudFrontの設定で、パラメータを無視してキャッシュを保存出来る機能ってあったような…?
あれば、期限付きの毎回異なるURLを出力しながら、
データの配信にはキャッシュを利用して負荷軽減が出来たりとかするのかな。
これはこれで別で調べてみよう!

Tags : |

Comment ( 1 )

コメントを残す

Please type the characters of this captcha image in the input box

Please type the characters of this captcha image in the input box