見出し画像

CloudFront+OACでS3へのアクセスを制限してみた

これは フェンリル デザインとテクノロジー Advent Calendar 2022 16日目の記事です。

2022年8月26日のAWSアップデートで、CloudFrontにOrigin Access Control(OAC)という機能が追加されました。これまでは、Origin Access Identity(OAI)という機能を使用してS3へのアクセス制限をしていましたが、いくつか制限事項がありました。この制限事項をカバーしたものがOACです。OAIと比較して、OACは以下の点が強化されています(AWS公式サイト引用)。

・セキュリティ – OAC は、短期間のクレデンシャル、頻繁なクレデンシャルのローテーション、およびリソースベースのポリシーのような強化されたセキュリティプラクティスで実装されています。

・包括的な HTTP メソッドのサポート – OAC は GET、PUT、POST、PATCH、DELETE、OPTIONS、および HEAD をサポートしています。

SSE-KMS – OAC は、SSE-KMS で暗号化された S3 オブジェクトのダウンロードとアップロードをサポートしています。

・すべての AWS リージョンでの S3 にアクセス – OAC は、既存のリージョンと将来のすべてのリージョンを含む、すべての AWS リージョンでの S3 へのアクセスをサポートしています。

今回はSSE-KMS暗号化に焦点を当てて実際にS3へのアクセス制限を行なってみます。

・OACを使ってみる(暗号化なし)

それではOACを使用してみます。ここではシンプルなパターンとして、S3オリジンへのGETアクセスを行います。このパターンはOAIでも実現可能です。
始めにS3バケットの作成を行います。ACL無効、ブロックパブリックアクセスは全て有効、暗号化なしでS3バケットを作成しました。このS3バケットは静的コンテンツの配信用として使用します。



先ほど作成したS3バケットをオリジンとしてCloudFrontディストリビューションを作成しました。S3バケットアクセスのOrigin accessの項目で「Origin access control settings」を選択します。[コントロール作成を設定]ボタンでOACを新しく作成します。



作成したOACを使用してCloudFrontディストリビューションを作成します


CloudFrontディストリビューション作成後のコンソール画面です。「S3バケットポリシーを更新する必要があります」と表示されるため、「ポリシーをコピー」のボタンでバケットポリシーをコピーします。
「S3バケットの権限に移動してポリシーを作成する」のリンクをクリックすることで、該当するS3バケットのポリシー編集画面に移動します。

移動先S3バケットのアクセス許可画面です。バケットポリシーの「編集」ボタンをクリックしてバケットポリシーを変更します。 

以下が実際のバケットポリシーの内容です。
PrincipalでCloudFrontからのアクセスを許可し、StringEqualsでCloudFrontディストリビューションIDを指定することで、アクセス許可を制限します。

{
	"Version": "2008-10-17",
	"Id": "PolicyForCloudFrontPrivateContent",
	"Statement": [
		{
			"Sid": "AllowCloudFrontServicePrincipal",
			"Effect": "Allow",
			"Principal": {
				"Service": "cloudfront.amazonaws.com"
			},
			"Action": "s3:GetObject",
			"Resource": "arn:aws:s3:::cloudfront-webhosting-misaki/*",
			"Condition": {
				"StringEquals": {
					"AWS:SourceArn": "arn:aws:cloudfront::xxxxxxxxxxxx:distribution/xxxxxxxxxxxxxx”
				}
			}
		}
	]
}

参考までに、OAIを使用した場合のバケットポリシー例が以下になります。
OACのバケットポリシーとは異なり、Principalでアクセスを許可するOAIを設定していることが分かるかと思います。

{
    "Version": "2012-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EH1HDMB1FH2TC"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::cloudfront-webhosting-misaki/*"
        }
    ]
}

OACの設定はこれで終了となります。試しにS3バケット直下に
test.htmlというファイルを配置し、CloudFront経由でアクセスしてみました。「Hello World」と表示されたので、CloudFrontからS3へのアクセスの際にOACが使われている、ということになります。

test.htmlの中身は以下の通りです。

<!DOCTYPE html> 
<html lang="ja">
<head> 
<meta charset="utf-8">
<title>S3 Static Web Hosting</title>
</head> 
<body> 
Hello,World!!
</body> 
</html>

OACを設定せずにアクセスした場合は以下のようなエラーが発生します。エラーメッセージに「Access Denied」とあるので、アクセスが拒否されたことが分かります。


・OACを使ってみる(SSE-KMS暗号化)

続いてOACを使用するメリットの一つであるSSE-KMS対応についてです。
まずはSSE-KMSで暗号化されたS3バケットを作成します。KMSを使用するにあたってKMS CMKの作成から始めています。

続いてS3バケットを作成します。ACL無効、ブロックパブリックアクセスは全て有効、暗号化設定でSSE-KMSによる暗号化を選択します。このS3バケットは静的コンテンツの配信用として使用します。

先ほど作成したS3バケットをオリジンとしてCloudFrontディストリビューションを作成しましょう。Origin設定のOrigin accessの項目で「Origin access control settings」を選択します。[コントロール設定を作成]ボタンで新たなOACを作成します。

CloudFrontディストリビューションの作成後、先ほどと同様にオリジンとなるS3バケットのバケットポリシーを更新します。

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::cloudfront-kms-misaki/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::xxxxxxxxxxxx:distribution/xxxxxxxxxx"
                }
            }
        }
    ]
}

今回のパターンではS3バケットでSSE-KMSの暗号化を行っているため、ここからさらにKMS CMK側の権限変更が必要となります。マネジメントコンソールの該当CMKのキーポリシーで以下を追加します。

        {
            "Sid": "AllowCloudFrontServicePrincipalSSE-KMS",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::xxxxxxxxxxxx:root",
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": [
                "kms:Decrypt",
                "kms:Encrypt",
                "kms:GenerateDataKey*"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::xxxxxxxxxxxx:distribution/xxxxxxxxxxxx"
                }
            }
        }

KMSを使用した場合の手順は、
1.CloudFrontのオリジン設定時にOACを使用
2.S3バケットポリシーでOACを使用しているCloudFrontディストリビューションへのアクセス許可
3.使用しているKMSキーのキーポリシーでCloudFrontディストリビューションへのアクセス許可
となります。この手順を踏んだ後にS3バケット直下に
test.htmlというファイルを配置し、CloudFront経由でアクセスしてみます。「Hello World」と表示されたので、無事CloudFront経由でアクセスができていることが分かります。

まとめ

CloudFront経由での新たなアクセス制限機能としてOACをご紹介しました。以前のOAIと比較してKMSの暗号化をはじめとした追加機能が実装されており、セキュリティ面の強化が見込まれると思います。OAIも利用自体は可能ですが、これからインフラを構築する場合にはOACを使用することを推奨します。

参考

クラスメソッド様ブログ
[NEW] CloudFrontからS3への新たなアクセス制御方法としてOrigin Access Control (OAC)が発表されました!

この記事が気に入ったらサポートをしてみませんか?