CloudFront+S3 で署名付き URL を用いたコンテンツアクセスをしてみた 2023

API アクセスが TLS1.2 未満は非対応となる対応として、S3 へアクセスする際に CloudFront を通して署名付き URL を用いる方法を紹介します。
2023.05.02

はじめに

猫とアポロチョコと Systems Manager が好きな m.hayakawa です。

TLS 1.2 未満での AWS API エンドポイントへの接続が2023年6月28日以降、不可能になります。

TLS 1.2 がすべての AWS API エンドポイントへの接続に必要な最小バージョンになります | Amazon Web Services ブログ

今後 Transport Layer Security (TLS) の技術の進化と規制基準に対応するため、すべての AWS サービス API エンドポイントの TLS 構成において、最小バージョンを TLS 1.2 に更新する予定です。この更新は、2023 年 6 月 28 日までにすべての AWS リージョンで、すべての AWS API で TLS バージョン 1.0 と 1.1 が使用できなくなることを意味します。

そのため、TLS 1.0 や TLS 1.1 プロトコルを用いて S3 へアクセスを行うクライアントについて、更新が必要になります。

しかしながら、S3 へアクセスするクライアントが TLS 1.2 以上に対応できない場合があります。

回避策として CloudFront を通じて S3 にアクセスすることで、TLS 1.0 や TLS 1.1 のクライアントでも対応ができるといった記事がありましたので、今回は署名付き URL を用いた方法で検証をしてみます。

古い TLS を使用するお客様が S3 バケットにアクセスできるようにする | AWS re:Post

Amazon CloudFront では、CloudFront ディストリビューションと Amazon S3 の間で使用されている TLS プロトコルからお客様を抽象化することで、古い TLS バージョンを使用できます。

なお、Origin Access Control を用いる方法については、下記のブログが参考になります。

[NEW] CloudFrontからS3への新たなアクセス制御方法としてOrigin Access Control (OAC)が発表されました! | DevelopersIO

やってみた

キーペアを作成する

ここでは CloudShell を用いて、OpenSSL を用いてキーペアを作成します。

CloudShell には OpenSSL がインストールされていないため、インストールします。

$ sudo yum -y install openssl

その後、秘密鍵を作成し、その秘密鍵から公開鍵を作成します。

$ mkdir key
$ cd key
$ openssl genrsa -out tls12test.private.pem 2048
$ openssl rsa -pubout -in tls12test.private.pem -out tls12test.pub.pem
$ ls
tls12test.private.pem  tls12test.pub.pem

キーペアは任意の S3 バケットに保存しておきます。

$ aws s3 sync . s3://<キーペア保存バケット>

CloudFront にパブリックキーを登録

CloudFront コンソールからパブリックキーを開き、パブリックキーを作成します。

キーにはtls12test.pub.pemの内容を転記します。

キーグループの作成

CloudFront コンソールからキーグループを作成します。

以下の画面の通り、設定します。

S3 バケットを作成する

デフォルト設定で S3 バケットを作成します。

アクセスの検証用に、test_picture.png をバケットにアップロードしておきます。

test_picture.png

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

CloudFront コンソールへ移動し、ディストリビューションの作成ボタンを押下します。

オリジンを先ほど作成した S3 にします。

CloudFront の署名付きリクエストを有効にする

オリジンアクセスをOrigin access control settings (recommended)にします。

「コントロール設定を作成」ボタンを押下し、署名動作に署名リクエスト (推奨)を選択し、「作成」ボタンを押下します。

デフォルトのキャッシュビヘイビアにて、ビューワーのアクセスを制限するをYes、信頼された認可タイプをTrusted key groups (recommended)、キーグループを先ほど作成したキーグループにします。

最後に「ディストリビューションを作成」ボタンを押下します。

S3 バケットポリシーを更新する

ディストリビューションの作成後に、バケットポリシーの更新を促す画面が出ますので、それに従い、手動でバケットポリシーを更新します。

生成されるバケットポリシーの内容としては、CloudFront サービスからのアクセスで、特定のCloudFront ディストリビューションからの GetObject アクションの許可がされているといったものとなります。

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::cloudfront-tls12-test/*",
            "Condition": {
                "StringEquals": {
                  "AWS:SourceArn": "arn:aws:cloudfront::<AccountID>:distribution/<DistributionID>"
                }
            }
        }
    ]
 }

CloudFront の事前署名付き URL を使用してオブジェクトにアクセスする

試しに、下記の URL でオリジンの S3 にアクセスをしてみますが、失敗しました。

$ curl https://<DistributionDomain>.cloudfront.net/test_picture.png
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>SAMPLE</RequestId><HostId>sample</HostId></Error>

では、CloudShell で署名付き URL を発行します。

$ aws cloudfront sign \
--url https://<DistributionDomain>.cloudfront.net/test_picture.png \
--key-pair-id <KeyPairID> \
--private-key file://./tls12test.private.pem \
--date-less-than $((`date "+%s"` + 86400))

動作チェック

取得した署名付き URL へアクセスします。

アクセスできました!

留意点

この対応を行う場合、S3 へのアクセスについては、S3 の URL ではなく、CloudFront の URL か、代替ドメインを使用する必要があります。

そのため、クライアント側でアクセス先の URL の変更を行う必要がある点については、ご留意ください。

参考資料

CloudFront+S3で署名付きURLでプライベートコンテンツを配信する | DevelopersIO