LoginSignup
15
8

Amazon CloudFront の署名付きURL(既定ポリシー)を使って、安全にコンテンツを配信してみた

Last updated at Posted at 2022-02-25

Note

カスタムポリシーを利用した記事もあります。
https://qiita.com/sugimount-a/items/53febd43e4cad7ffdb54

はじめに

Web アプリケーションやモバイルアプリなどを提供する際に、画像などの素材を Amazon Simple Storage Service (Amazon S3) に格納したものを配信できます。セキュリティやパフォーマンスを考慮して、以下の 2 点を実現していきたいユースケースがあります。

  • S3 に格納したファイルは、一部のユーザーに限定して配信したい
  • たくさんのユーザーがいるため、CloudFront を使った配信をしたい

上記を満たすために、CloudFront の署名付き URL や 署名付き Cookie が活用できます。S3 を Private Bucket にしたうえで、CloudFront の署名付き URL や 署名付き Cookie を生成することで、CloudFront のスケーラビリティを活かしながら、一部のユーザーに限定したアクセスが提供できます。Web アプリケーション側で、何らかの認証機能を利用しながら、ログイン済みユーザーに限定して署名付き URL ・署名付き Cookie を発行する仕組みを作り上げることで、実現頂けます。

次の構成図に、概要図を載せています。

  1. ユーザーは、Web アプリケーションに備わっている認証機能でログインを行う
  2. Web アプリケーションはリクエストに応じて、画像データなどに紐づく CloudFront 署名付き URL を生成
  3. Web アプリケーションは、ユーザー側に署名付き URL をレスポンス
  4. ユーザは、署名付き URL にアクセスすることで、Private な S3 Bucket に格納されている画像データなどを取得

image-20220225194535428.png

概要図では、Web アプリケーション側に秘密鍵を持たせて署名付き URL を生成していますが、API Gateway + Lambda を活用したサーバーレス構成の選択肢が有ります。サーバーレス構成は運用負担の軽減といったメリットがあります。

2種類の署名付き URL

署名付き URL は、セキュリティに関するポリシーの違いによって、「規定ポリシー」と「カスタムポリシー」の 2 種類あります。2 つのポリシーの違いを AWS Document に書かれている表から抜粋します。規定ポリシーは、デフォルトの設定になっており、手を加えない分比較的楽に生成できます。一方、カスタムポリシーは自分たちのワークロードに合わせたカスタマイズが可能で、柔軟にコントロールができます。カスタムポリシーの方は、複数のオブジェクトのために再利用出来たり、アクセス元の IP アドレスの制限が出来るため、便利に利用できそうですね。

image-20220225195842898.png

今回の記事では、規定ポリシーを使った署名付き URL を生成する方法を確認していきます。

秘密鍵・公開鍵の作成

署名付き URL を生成するために、秘密鍵・公開鍵の生成が必要です。手元の Linux マシンなどで作成していきましょう。

mkdir ~/temp/cloudfront-presign/
cd ~/temp/cloudfront-presign/

秘密鍵を生成します

openssl genrsa -out private_key.pem 2048

秘密鍵から、CloudFront に登録するための公開鍵を生成します

openssl rsa -pubout -in private_key.pem -out public_key.pem

こんな感じに生成できました

> ls -lha
total 12K
drwxr-xr-x  2 ec2-user docker   51 Feb 25 20:18 .
drwxrwxr-x 36 ec2-user docker 4.0K Feb 25 19:12 ..
-rw-r--r--  1 ec2-user docker 1.7K Feb 25 20:18 private_key.pem
-rw-r--r--  1 ec2-user docker  451 Feb 25 20:18 public_key.pem

CloudFront に公開鍵をアップロード

CloudFront のページに移動して、Create public key を押します

image-20220225202106137.png

公開鍵の中身を確認して、登録をしていきます

cat public_key.pem

image-20220225202319453.png

登録されました。

image-20220225202407849.png

CloudFront に Key Group を作成

Key Group を作成して、アップロードした公開鍵を登録します

image-20220225202500082.png

名前や公開鍵の名前を選択します

image-20220225202545446.png

作成されました

image-20220225202614643.png

S3 Bucket の作成

適当な名前で Private な S3 Bucket を作成して、うちの猫の写真をアップロードします。この写真を、署名付き URL のアクセス確認に使っていきます。

image-20220225203426231.png

CloudFront の Distribution の作成

署名付き URL を利用するために、Create distributon を押します。

image-20220225203558305.png

  • Distribution の Origin として、作成した S3 Bucket を指定
  • OAI を利用して、S3 Bucket のアクセスを CloudFront のみに制限

image-20220225203852078.png

Restrict viewer access を有効にして、署名付き URL が無いとアクセスできないように設定します

image-20220225204031423.png

Create Distribution を押します

image-20220225204128034.png

Deploy プロセスが走りました

image-20220225204209601.png

署名付きURLの生成

今回は、AWS CLI を使って CloudFront の署名付き URL を生成していきましょう。実際の環境では、SDK を使ったプログラムから署名付き URL を生成すると思います。次の Document にサンプルコードがあるので参考にできます。

aws cloudfront sign \
--url https://d31z1elfcc2o1s.cloudfront.net/mycat.jpg \
--key-pair-id K1DYHGI8XWLXZL \
--private-key file:///home/ec2-user/temp/cloudfront-presign/private_key.pem \
--date-less-than 2022-02-25T20:50:00+09:00

実行例

> aws cloudfront sign \
      --url https://d31z1elfcc2o1s.cloudfront.net/mycat.jpg \
      --key-pair-id K1DYHGI8XWLXZL \
      --private-key file:///home/ec2-user/temp/cloudfront-presign/private_key.pem \
      --date-less-than 2022-02-25T20:50:00+09:00
https://d31z1elfcc2o1s.cloudfront.net/mycat.jpg?Expires=1645789800&Signature=lteo65gt~7K2UFPyG9KEOhIEkTYid2Zn9IKG6Ync605wwnygvo~dUWjwX~N~8BmGiAPnMavtADL-mf-24aGRQa~xRSgLm6tPvoyqeX6rSptXvkrPMqtQ9HOiaHPMY8PuzMkj3CQLb-0O53CwD5HJNUeQbAers6IFvxeJoEgtWTn1YE8J1umezTxHlsHuRl7Eq0soT8iktFXaRKE0AQFjYvT5UvmkgShA2j7eqtcIW~mmKHT2LQ5XSSxztiZj5OWzFXLyET9va0Amj2t7~EOxA21n~7AWamrmU9xNCKO5bnuz31dV4L5fKSVQdxl5jFddXk6~qyxDP2r26JgXtYFMJA__&Key-Pair-Id=K1DYHGI8XWLXZL⏎

アクセス確認

通常のアクセス

まず、通常通り、署名付き URL なしで CloudFront にアクセスしてみます。想定通り、エラーになりました。

image-20220225204956139.png

署名付き URL でアクセス

AWS CLI で生成した URL にアクセスしてみます。S3 Bucket にアップロードした、家猫の写真が見えました。かわいい。

image-20220225205102181.png

有効期限切れ

署名付き URL の有効期限が切れた後にアクセスしてみた結果です。これも想定通りエラーになりました。

image-20220225205130622.png

検証を通じてわかったこと

  • 秘密鍵・公開鍵を生成して、CloudFront に公開鍵をアップロードする必要がある
  • 署名付き URL を生成するために、秘密鍵を持っているコンピュートリソース (EC2, Lambda, ECS, App Runner など) を用意する方式が考えられる

参考URL

AWS Document : 署名付き URL の使用
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-urls.html

Python のサンプルコード
https://github.com/boto/boto3/blob/develop/boto3/examples/cloudfront.rst

【AWS】CloudFrontで署名付きURLの設定方法(プライベートコンテンツの配信)
https://zenn.dev/may_solty/articles/807dbad3a30de8

15
8
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
15
8