CloudFront+OACでS3へのアクセスを制限してみた
2022年8月26日のAWSアップデートで、CloudFrontにOrigin Access Control(OAC)という機能が追加されました。これまでは、Origin Access Identity(OAI)という機能を使用してS3へのアクセス制限をしていましたが、いくつか制限事項がありました。この制限事項をカバーしたものがOACです。OAIと比較して、OACは以下の点が強化されています(AWS公式サイト引用)。
今回は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)が発表されました!
この記事が気に入ったらサポートをしてみませんか?