【Python】CloudFront 署名付きURLを生成

目次

Pythonを使った、CloudFront署名付きURLの生成方法です。

本件は、S3の前にCloudFrontを配置し、署名付きURLを介してS3オブジェクトをブラウザで表示してみるという構成になっています。

環境(前提)

代替ドメインを使わずCloudFrontのドメインをそのまま使用する場合は、Pythonが使えたらだいたい出来ます。

CloudFrontに代替ドメインを使用する場合、バージニア北部のACMで証明書を発行する必要があるので注意。バージニア北部!

CloudFrontの準備

キーペアとS3バケットの準備

  1. ここを参考に
    1. パブリックとプライベートのキーペアを作成
    2. パブリックキーを CloudFront にアップロード
    3. パブリックキーをキーグループに追加する
  2. テキトーにS3バケット作成(作成済みならスキップ)

CloudFront ディストリビューションを作成

CloudFront のホームを開き、ディストリビューションを作成する。

「オリジン」の項目にて

  1. 「Origin domain」で先ほど作成したS3バケットを選択。このとき「名前」が自動的に入力されるのでそのままにしておく。
  2. 「オリジンアクセス」で、Origin access control settings (recommended)
  3. 適宜「Create new OAC」をクリックして作成。OACの入力欄はデフォルトのままでよい。

(S3バケットポリシー更新は、ディストリビューション作成後に行う)

「デフォルトのキャッシュビヘイビア」の項目にて

  1. ビューワーのアクセスを制限する:「Yes」
  2. 信頼された認可タイプ:「Trusted key groups (recommended) 」を選択し、事前に作成したキーグループをチェック
  3. 作成

画面上部に出るメッセージの「S3バケットの権限に移動してポリシーを更新する」
または、手動で以下のように

  1. 「ポリシーをコピー」をクリックしてコピー
  2. Origin domainで選択したS3バケットを開き、バケットポリシーを編集して保存

Pythonサンプルコード

必要なライブラリをインストールする。

pip install cryptography botocore

以下のソースコードで署名付きURLを生成する。

# -*- coding:utf-8 -*-
from datetime import datetime, timedelta, UTC
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from botocore.signers import CloudFrontSigner


def rsa_signer(message):
    with open('cloudfront_private_key.pem', 'rb') as key_file:
        private_key = serialization.load_pem_private_key(
            key_file.read(),
            password=None,
            backend=default_backend()
        )
    return private_key.sign(message, padding.PKCS1v15(), hashes.SHA1())


key_id = 'パブリックキーID'
domain = 'https://xxxyyyzzz.cloudfront.net'
object_key = 'icon.png' # S3にアップロード済みのファイル

# 署名付きにしたいURL
url = f"{domain}/{object_key}"

# URLを30分間有効にする
expire_date = datetime.now(UTC) + timedelta(minutes=30)

cloudfront_signer = CloudFrontSigner(key_id, rsa_signer)
signed_url = cloudfront_signer.generate_presigned_url(url, date_less_than=expire_date)

print(signed_url)

※例なのでパブリックキーIDなど直書きしています。

代替ドメインで署名付きURLを生成する場合

AWS側での追加作業

  1. CloudFront ディストリビューションの 一般>設定 を編集
    1. 「Alternative domain name (CNAMEs) - optional」で任意のドメインを入力
    2. 「Custom SSL certificate」で任意の証明書を選択
  2. Route53でCloudFrontディストリビューションと代替ドメインを Aタイプのコードで紐づける

あとは、サンプルコードの domainを任意のドメインに変えて実行する。