最近terraformを書いてインフラを構築する機会がありました。S3におけるバケットポリシーの書き方をまとめます。
前提
以下の二つです。
(1)ロードバランサーのログをS3に保存する。
(2)投稿した画像を加工するために、外部サーバーへ画像(そのURL)を渡します。その際外部の特定のサーバーがS3アクセスできるようにしなければなりません。
S3はアクセスコントロールのために3つの方法があります。
・ACL(アクセスコントロールリスト)
・バケットポリシー
・IAMポリシー
(1)に関して、はIAMユーザレベルの制御なので、バケットポリシーかIAMポリシーを使用します(今回は、書きやすそうなバケットポリシー)
(2)に関して、外部のサーバからのアクセスのため、ACLを利用します。
参考: (https://qiita.com/ryo0301/items/791c0a666feeea0a704c)
TFのコード
(1)ロードバランサーのログに関して、
data "aws_iam_policy_document" "alb_log" {
statement {
effect = "Allow"
actions = ["s3:PutObject"]
resources = ["arn:aws:s3:::${aws_s3_bucket.alb_log.id}/*"]
principals {
type = "AWS"
# Principalには、東京リージョン(ap-northeast-1)を指すElastic Load Balancing アカウント ID(582318560864)を記載する
identifiers = ["582318560864"]
}
}
}
resource "aws_s3_bucket" "alb_log" {
bucket = "${var.service}-${var.environment}-alb-log"
lifecycle_rule {
enabled = true
// logの保存期間は180日
expiration {
days = "180"
}
}
}
resource "aws_s3_bucket_policy" "alb_log" {
bucket = aws_s3_bucket.alb_log.id
policy = data.aws_iam_policy_document.alb_log.json
}
のようにかけます。
真ん中のaws_s3_bucketにより、alb_logという名前のバケットを生成します。
ログの保存期間は、180日にするため、lifecyecleを有効(enabled = true)にし、
expirationにdays=180を指定します。
また、一番上のaws_iam_policy_documentを書くことで、alb_logという名の、ポリシードキュメントを定義できます(これは任意です)。
statement内部に設定を書いていきます。
effectには、AllowかDenyが入ります(デフォは、Allow)、今回は許可するためAllow。
actionsには、上で許可(拒否)した、アクションを入れます。今回は、ログを入れるためs3:PutObject。
resourcesには、どのS3に対して、許可したかを指定します。今回は、上で作成したalb_log以下に保存するため、arn:aws:s3:::${aws_s3_bucket.alb_log.id}/*
その下のprincipals引数には、ステートメントが適用されるユーザーを定義します(適用しない場合は、not_principals)。
typeには、AWS。ELBを設定しているリージョンのID(東京の場合は、582318560864).
(ちなみに、リージョンとIDの対応表はhttps://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-access-logs.html)
最後に、aws_s3_bucket_policyから、S3にドキュメントをデータソースをJSON文字列にして、アタッチします。
(2)二つ目の外部サーバーからのアクセスに関して、
resource "aws_s3_bucket" "private-files" {
bucket = "${var.service}-${var.environment}-private-files"
}
resource "aws_s3_bucket_acl" "private-files" {
bucket = aws_s3_bucket.private-files.id
acl = "private"
}
のように書きます。
アクセス制御はacl(デフォルトはprivate)を利用し、
private(所有者に FULL_CONTROL が付与される)を指定。
(その他参考https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/acl-overview.html#canned-acl)
その後アタッチして終了。
参考文献
aws_iam_policy_documentの書き方に関して
・https://zenn.dev/junkin_au/scraps/43af950cadf396
・https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration
IAMロールのprincipalに関して
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_principal.html
S3の設定に関して
https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html
S3のアクセス制御に関して、https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_access_point