Amazon web services 从帐号的JSON数组构建AWS IAM策略
我有一个AWS帐号列表,我想动态使用它来构建AWS策略。以下是我的例子:Amazon web services 从帐号的JSON数组构建AWS IAM策略,amazon-web-services,terraform,amazon-iam,terraform-provider-aws,Amazon Web Services,Terraform,Amazon Iam,Terraform Provider Aws,我有一个AWS帐号列表,我想动态使用它来构建AWS策略。以下是我的例子: resource "aws_s3_bucket" "splunk-config-bucket" { bucket = "${var.config_bucket_name}" force_destroy = true server_side_encryption_configuration { rule { apply_server_side_encryption_by_defa
resource "aws_s3_bucket" "splunk-config-bucket" {
bucket = "${var.config_bucket_name}"
force_destroy = true
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
kms_master_key_id = "${data.aws_kms_alias.kms_name.arn}"
sse_algorithm = "aws:kms"
}
}
}
tags = {
Product = "Splunk - AWS Config Logs"
Service = "Security"
}
lifecycle_rule {
id = "log"
enabled = true
prefix = "*"
transition {
days = 7
storage_class = "GLACIER"
}
expiration {
days = 14
}
}
policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSConfigAclCheck20150319",
"Effect": "Allow",
"Principal": {
"Service": "config.amazonaws.com"
},
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::${var.config_bucket_name}"
},
{
"Sid": "AWSConfigWrite20150319",
"Effect": "Allow",
"Principal": {
"Service": "config.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": [
"arn:aws:s3:::${var.config_bucket_name}/AWSLogs/123456789/*”,
"arn:aws:s3:::${var.config_bucket_name}/AWSLogs/123456789/*",
"arn:aws:s3:::${var.config_bucket_name}/AWSLogs/123456789/*",
"arn:aws:s3:::${var.config_bucket_name}/AWSLogs/123456789/*",
"arn:aws:s3:::${var.config_bucket_name}/AWSLogs/123456789/*",
"arn:aws:s3:::${var.config_bucket_name}/AWSLogs/123456789/*",
"arn:aws:s3:::${var.config_bucket_name}/AWSLogs/123456789/*",
"arn:aws:s3:::${var.config_bucket_name}/AWSLogs/123456789/*",
"arn:aws:s3:::${var.config_bucket_name}/AWSLogs/123456789/*",
"arn:aws:s3:::${var.config_bucket_name}/AWSLogs/123456789/*"
],
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
]
}
POLICY
}
resource "aws_s3_bucket_notification" "configlogs_bucketnotification" {
bucket = "${var.config_bucket_name}"
queue {
queue_arn = "${aws_sqs_queue.splunk_configlogs_sqs_queue.arn}"
events = ["s3:ObjectCreated:*"]
}
}
我正在尝试使用AWS帐号的动态列表生成策略。我们正试图摆脱硬编码账号,并将其从一个“集中配置”项目中提取出来
以下是我尝试过的:
变量.tf:
locals {
accounts = jsondecode(file("../configuration/envs.json")).accounts
}
Config.tf
"Principal": {
"Service": "config.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": ${jsonencode(formatlist("arn:aws:s3:::${var.config_bucket_name}/AWSLogs/%s/*", local.accounts))}
"Condition": {
当我运行“terraform plan”时,这为我提供了以下输出:
我也试过:
变量.tf
locals {
accounts = jsondecode(file("../configuration/envs.json")).accounts
}
output "example" {
value = jsonencode(formatlist("arn:aws:s3:::${var.config_bucket_name}/AWS/AWSLogs/%s/*", local.accounts))
}
config.tf
"Principal": {
"Service": "config.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": ${local.accounts.output.value}
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
这是我得到的输出:
Error: Unsupported attribute
on central_config.tf line 60, in resource "aws_s3_bucket" "splunk-config-bucket":
60: "Resource": ${local.accounts.output.value}
|----------------
| local.accounts is tuple with 35 elements
This value does not have any attributes.
谢谢,您可以在代码中重新加载动态配置,在配置文件更改时更新帐户列表并调用S3API 为了查看配置文件(帐户列表),您可以使用一些库。我相信“毒蛇”是个不错的选择 而且,如果您担心由于API调用失败或应用程序崩溃而丢失文件中的此类事件,您可以尝试将更新操作列表设为幂等项,并在应用程序启动时或在一段时间间隔内进行更新 这些链接可能会出现: 关于幂等性:
Viper:您可以使用加载文件,然后通过使用解码JSON,然后选择
accounts
键来提取所需的帐户列表
例如:
locals {
accounts = jsondecode(file("accounts.json")).accounts
}
output example {
value = local.accounts
}
这将返回以下内容:
example = [
"1234567890",
"0987654321",
"1029384756",
"6574839201",
"0192837465",
]
如果要将其放入策略中,则需要使用将帐户列表传递为单个字符串格式:
output "example" {
value = formatlist("arn:aws:s3:::bucket_name/AWSLogs/%s/*", local.accounts)
}
这将产生:
example = [
"arn:aws:s3:::bucket_name/AWSLogs/1234567890/*",
"arn:aws:s3:::bucket_name/AWSLogs/0987654321/*",
"arn:aws:s3:::bucket_name/AWSLogs/1029384756/*",
"arn:aws:s3:::bucket_name/AWSLogs/6574839201/*",
"arn:aws:s3:::bucket_name/AWSLogs/0192837465/*",
]
但如果您仔细注意,Terraform在列表中使用尾随逗号,这是无效的JSON,因此会为您的IAM策略创建无效的JSON结构。为了解决这个问题,我们可以使用以下代码将其重新编码为JSON:
然后输出:
example = ["arn:aws:s3:::bucket_name/AWSLogs/1234567890/*","arn:aws:s3:::bucket_name/AWSLogs/0987654321/*","arn:aws:s3:::bucket_name/AWSLogs/1029384756/*","arn:aws:s3:::bucket_name/AWSLogs/6574839201/*","arn:aws:s3:::bucket_name/AWSLogs/0192837465/*"]
不带尾随逗号
总而言之,您可以创建如下IAM策略:
{
"accounts": [
"1234567890",
"0987654321",
"1029384756",
"6574839201",
"0192837465"
]
}
locals {
accounts = jsondecode(file("accounts.json")).accounts
}
resource aws_iam_policy policy {
name = "example"
path = "/"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:PutObject"
],
"Effect": "Allow",
"Resource": ${jsonencode(formatlist("arn:aws:s3:::bucket_name/AWSLogs/%s/*", local.accounts))}
}
]
}
EOF
}
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AWSConfigAclCheck20150319"
Effect = "Allow"
Principal = {
Service = "config.amazonaws.com"
}
Action = "s3:GetBucketAcl"
Resource = "arn:aws:s3:::${var.config_bucket_name}"
},
# etc, etc
]
})
本地人{
accounts=jsondecode(文件(“accounts.json”)).accounts
}
资源aws_iam_策略{
name=“示例”
path=“/”
policy=在ydaetskcoR的帮助下,我成功地实现了这一点:
这是我的变量文件:
locals {
accounts = jsondecode(file("../configuration/envs.json")).accounts
config = jsonencode(formatlist("arn:aws:s3:::${var.config_bucket_name}/AWSLogs/%s/*", local.accounts))
}
我可以使用Terraform控制台测试输出:
> jsonencode(formatlist("arn:aws:s3:::${var.config_bucket_name}/AWSLogs/%s/*", local.accounts))
["arn:aws:s3:::bby-central-configlogs-splunk/AWSLogs/123456789/*","arn:aws:s3:::bby-central-configlogs-splunk/AWSLogs/123456789/*"]
如您所见,它们周围有[]:
我将以下内容纳入我的政策:
"Principal": {
"Service": "config.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": ${local.config},
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
我想我会给出我的答案:)使用字符串模板正确地编码JSON可能会令人沮丧。除非有充分的理由以特定的方式格式化JSON,否则我们可以通过直接构建所需的数据结构,然后将其传递给jsonencode
来避免对JSON进行模板化,如下所示:
{
"accounts": [
"1234567890",
"0987654321",
"1029384756",
"6574839201",
"0192837465"
]
}
locals {
accounts = jsondecode(file("accounts.json")).accounts
}
resource aws_iam_policy policy {
name = "example"
path = "/"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:PutObject"
],
"Effect": "Allow",
"Resource": ${jsonencode(formatlist("arn:aws:s3:::bucket_name/AWSLogs/%s/*", local.accounts))}
}
]
}
EOF
}
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AWSConfigAclCheck20150319"
Effect = "Allow"
Principal = {
Service = "config.amazonaws.com"
}
Action = "s3:GetBucketAcl"
Resource = "arn:aws:s3:::${var.config_bucket_name}"
},
# etc, etc
]
})
然后,您可以直接使用Terraform的运算符和函数来构造该对象的部分。例如,要生成所需的ARN列表:
policy = jsonencode({
Version = "2012-10-17"
Statement = [
# ...
{
Sid = "AWSConfigWrite20150319"
Effect = "Allow"
Principal = {
Service = "config.amazonaws.com"
}
Action = "s3:PutObject"
Resource = [for acct in local.accounts : "arn:aws:s3:::${var.config_bucket_name}/AWSLogs/${acct}/*"]
},
# ...
]
})
如果策略变得足够复杂,您希望将其分解到单独的模板文件中,您仍然可以使用jsonencode
函数,将整个模板设置为jsonencode
调用:
${jsonencode({
# ...
})}
同时对整个结构使用jsonencode
意味着结果保证是有效的JSON,而无需像构建JSON作为模板时那样担心逗号和其他分隔符的确切位置。您是否在寻找类似本文所述的内容?我不使用AWS,所以我需要一个还有更多。嘿-谢谢参与,我添加了更多细节。谢谢:)这太棒了。谢谢你花时间回复这个问题。我唯一的问题似乎是试图将输出作为另一个“file.tf”的输入返回到我的策略中当它运行时。我可能没有抓住要点。这是可能的还是我应该从另一个角度来处理它?我遇到了这个问题:错误:资源“aws_s3_bucket”“splunk config bucket”中的central_config.tf行61上不支持的属性:61:${local.accounts.formatted_list}|------------------------------local.accounts是包含35个元素的元组。此值没有任何属性。很抱歉,输出更多用于演示。我添加了一个创建IAM策略的更完整示例。更完整的示例在这里有用吗?如果看不到您的问题,很难判断您遇到了什么问题充分工作的示例肯定会满足您的需要,但您可能会在这里遇到另一个问题,因此可能值得编辑您的问题,将其包括在内(如果相关),或者如果您被困在与此特定问题无关的另一个问题上,甚至可以打开另一个问题。明白了-我说得对。感觉我太接近了!我很高兴现在得到以下信息:“Error:“policy”在object key:value对之后包含一个无效的JSON:invalid字符'”,“谢谢你-我会研究它并尝试让它工作:)