Amazon CloudFront の署名付き URL とは
署名付き URL を使用する - Amazon CloudFront
署名付き URL には、有効期限切れ日時など、追加の情報も含まれており、コンテンツへのアクセスをより詳細に制御できます。
CloudFront におけるコンテンツへのアクセス制限のひとつです。
機能概要
- URL の有効期間やアクセス可能な IP アドレスを指定可能
- 既定ポリシーとカスタムポリシーが存在する
- 既定ポリシーでは IP アドレス制限などができない
- カスタムポリシーでは IP アドレス制限などが可能
- 同じディストリビューションで両ポリシーを使用することが可能
- 署名付き URL は署名付き Cookie よりも優先される
署名付き Cookie との比較
署名付き URL を使用するか、署名付き Cookie を使用するかを決定する - Amazon CloudFront
それぞれ以下のようなユースケースがあります。
- 署名付き URL
- 単一コンテンツへのアクセス
- Cookie をサポートしていないクライアント
- 署名付き Cookie
- 複数コンテンツへのアクセス
- 現在の URL を変更できない
署名付き URL の仕組み
AWS Black Belt Online Seminar Amazon CloudFront 基礎編
主に以下のフローでコンテンツにアクセスします。
- クライアントは認証サイトで認証
- 認証サイトが署名付き URL を発行
- クライアントは署名付き URL からコンテンツにアクセス
より詳細な仕組みについては以下のドキュメントをご参照ください。
署名付き URL を使用する - Amazon CloudFront
試してみた
S3 バケットのコンテンツへのアクセスで署名付き URL を使用してみました。
01. S3 バケットの作成
デフォルト設定で作成しました。

S3 バケットの作成後、任意の画像を 1 枚アップロードしました。

02. CloudFront ディストリビューションの作成
以下の設定で作成しました。
- プラン: Free
- オリジン: Amazon S3
- S3 origin: 手順 01 で作成した S3 バケット
上記以外はデフォルト設定で作成しました。





03. 鍵の作成
CloudShell で公開鍵と秘密鍵のペアを作成します。
# 秘密鍵作成
$ openssl genrsa -out private_key.pem 2048
# 公開鍵を公開
$ openssl rsa -pubout -in private_key.pem -out public_key.pem
$ ls
private_key.pem public_key.pem
$ cat public_key.pem
-----BEGIN PUBLIC KEY-----
xxx
-----END PUBLIC KEY-----
04. CloudFront に公開鍵を登録
CloudFront コンソールから公開鍵を登録します。
Key には手順 03 の cat コマンドで出力された内容を入力します。



05. キーグループの作成
CloudFront コンソールからキーグループを作成します。
Public keys には手順 04 で登録したキーを指定します。



06. アプリケーションの作成
CloudShell で以下のコマンドを実行します。
$ cat > sign_url.py << 'EOF'
import sys
import json
from datetime import datetime, timedelta
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.backends import default_backend
import base64
from urllib.parse import quote_plus
def sign_url(url, key_pair_id, private_key_path, expire_minutes=60):
expire_date = datetime.utcnow() + timedelta(minutes=expire_minutes)
expire_timestamp = int(expire_date.timestamp())
policy = {
"Statement": [{
"Resource": url,
"Condition": {
"DateLessThan": {
"AWS:EpochTime": expire_timestamp
}
}
}]
}
policy_json = json.dumps(policy, separators=(',', ':'))
with open(private_key_path, 'rb') as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
signature = private_key.sign(
policy_json.encode('utf-8'),
padding.PKCS1v15(),
hashes.SHA1()
)
def cloudfront_base64_encode(data):
encoded = base64.b64encode(data).decode('utf-8')
return encoded.replace('+', '-').replace('=', '_').replace('/', '~')
encoded_signature = cloudfront_base64_encode(signature)
encoded_policy = cloudfront_base64_encode(policy_json.encode('utf-8'))
separator = '&' if '?' in url else '?'
signed_url = f"{url}{separator}Policy={encoded_policy}&Signature={encoded_signature}&Key-Pair-Id={key_pair_id}"
return signed_url
if __name__ == "__main__":
if len(sys.argv) != 4:
print("使い方: python3 sign_url.py <URL> <Key-Pair-ID> <private_key.pem>")
sys.exit(1)
url = sys.argv[1]
key_pair_id = sys.argv[2]
private_key_path = sys.argv[3]
signed_url = sign_url(url, key_pair_id, private_key_path)
print("\n署名付きURL:")
print(signed_url)
EOF
$ pip3 install cryptography
07. 動作確認
CloudShell で以下のコマンドを実行します。
ディストリビューションドメイン名は手順 02 で作成したディストリビューションのドメイン名です。
$ python3 sign_url.py \
"https://<ディストリビューションドメイン名>/test.png" \
"<手順 04 で登録した公開鍵の ID>" \
"private_key.pem"
署名付きURL:
https://d2phun9qmp33n.cloudfront.net/test.png?Policy=xxx&Signature=xxx&Key-Pair-Id=xxx
発行された署名付き URL にブラウザからアクセスして手順 01 でアップロードした画像が表示されれば成功です。

08. 署名付き URL でのアクセスのみに制限
CloudFront ディストリビューションのビヘイビアで署名付き URL でのアクセスのみに制限します。

ディストリビューションのデプロイ完了後、デフォルトのドメイン名にブラウザからアクセスして以下のような画面が表示されればアクセス制限できています。
<Error>
<Code>MissingKey</Code>
<Message>Missing Key-Pair-Id query parameter or cookie value</Message>
</Error>

エラーコードは 403 であることも確認できました。
curl -o /dev/null -s -w "%{http_code}\n" https://d2phun9qmrp33n.cloudfront.net/test.png
403
まとめ
今回は Amazon CloudFront の 署名付き URL について紹介しました。
どなたかの参考になれば幸いです。
Discussion