amazon-web-services - 将主体附加到存储桶策略文档而不是覆盖它
问题描述
我正在开发一个包含多个环境的 SPA:dev、preprod、prod
每个 env 都有一个对应的 CloudFront 分配和存储桶网站。
我们还有一个带有用户手册的静态网站,在行为 /documentation/* 上提供
此静态网站存储在单独的存储桶中
所有环境共享相同的文档,因此所有环境只有一个存储桶。
该项目是一个公司门户,因此不应公开访问用户文档。
为了实现这一点,我们使用了 OAI,因此只能通过CloudFront 访问存储桶(lambda@edge 确保用户拥有有效的令牌,否则将他重定向,因此文档是私有的)。
当我使用 dev 部署时一切都很好
terraform workspace select dev
terraform apply -var-file=dev.tfvars
但是当我尝试在 preprod 上部署时
terraform workspace select preprod
terraform apply -var-file=preprod.tfvars
Terraform 以这种方式更改 OAI ID
# module.s3.aws_s3_bucket_policy.documentation_policy will be updated in-place
~ resource "aws_s3_bucket_policy" "documentation_policy" {
bucket = "my-bucket"
~ policy = jsonencode(
~ {
~ Statement = [
~ {
Action = "s3:GetObject"
Effect = "Allow"
~ Principal = {
~ AWS = "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E3U64NEVQ9IQHH" -> "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E3ORU58OAALJAP"
}
Resource = "arn:aws:s3:::my-bucket/*"
Sid = ""
},
]
Version = "2012-10-17"
}
)
}
而我希望校长以这种方式添加:
# module.s3.aws_s3_bucket_policy.documentation_policy will be updated in-place
~ resource "aws_s3_bucket_policy" "documentation_policy" {
bucket = "my-bucket"
~ policy = jsonencode(
~ {
Statement = [
{
Action = "s3:GetObject"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E3U64NEVQ9IQHH"
}
Resource = "arn:aws:s3:::my-bucket/*"
Sid = ""
},
+ {
+ Action = "s3:GetObject"
+ Effect = "Allow"
+ Principal = {
+ AWS = "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E3ORU58OAALJAP"
+ }
+ Resource = "arn:aws:s3:::my-bucket/*"
+ Sid = ""
+ },
]
Version = "2012-10-17"
}
)
}
有没有办法使用 terraform 0.13.5 来实现这一点
有关信息,这是我documentation-bucket.tf
在创建后在每个工作区中导入的
resource "aws_s3_bucket" "documentation" {
bucket = var.documentation_bucket
tags = {
BillingProject = var.billing_project
Environment = var.env
Terraform = "Yes"
}
logging {
target_bucket = var.website_logs_bucket
target_prefix = "s3-access-logs/${var.documentation_bucket}/"
}
lifecycle {
prevent_destroy = true
}
}
data "aws_iam_policy_document" "documentation" {
statement {
actions = ["s3:GetObject"]
resources = ["${aws_s3_bucket.documentation.arn}/*"]
principals {
type = "AWS"
identifiers = [aws_cloudfront_origin_access_identity.origin_access_identity.iam_arn]
}
}
}
resource "aws_s3_bucket_policy" "documentation_policy" {
bucket = aws_s3_bucket.documentation.id
policy = data.aws_iam_policy_document.documentation.json
}
最好的祝福
解决方案
假设:
根据您所说的,您似乎在不同的状态文件中管理相同的资源(基于“[...] 我在创建后在每个工作区中导入的假设”)
你这样做基本上造成了脑裂的情况。
假设二:您正在部署一个 S3 存储桶,并且多个 CloudFront 分配访问这个存储桶都在同一个 AWS 账户中。
回答:
虽然这样做完全没问题,但这不是它应该设置的方式。单个资源应仅由单个 terraform 状态(工作区)管理,否则您将看到这种预期但不希望出现的不稳定状态行为。
我建议在单个工作区配置中管理 S3 存储桶,甚至创建一个名为“共享”的新工作区。
在此工作区中,您可以使用terraform_remote_state 数据源导入其他工作区的状态并构建一个策略,包括从其他状态中提取的所有 OAI。当然,您可以在不创建新的共享工作区的情况下这样做。
我希望这会有所帮助,虽然它可能不是预期的解决方案 - 也许我的假设是错误的。
最后的话:
在环境之间共享资源不被认为是好的做法,因为当您停用环境时数据很可能会保留,并且管理访问可能会变得复杂且不安全。
更好地保持环境版本尽可能接近,例如12 因素应用程序的 Dev/Prod Parity,但尽量不要共享资源。如果您觉得需要共享资源,请花一些时间,再次挑战您的架构。
推荐阅读
- javascript - 如何使用谷歌时间线图以天而不是日期显示轴
- python - Dockerized Python Flask REST API 显示“页面不工作
- machine-learning - 如何使用 PyTorch 在自定义图像数据集中创建训练验证拆分?
- java - 如何在 PreferenceScreen 中为 PreferenceSwitch 设置 TapTargetView
- wikidata - 获取 wikidata 最旧和最新的修订时间戳
- javascript - 自带搜索框,x按钮不隐藏
- c# - Bot Framework V4 依赖注入不起作用
- node.js - 是否可以创建 orderByChild 并等于获取这些标签?
- assembly - 64 位处理器中 NULL 选择器的混淆
- javascript - 我可以在对象上解构以整数命名的属性吗?