针对带count启用资源的aws_iam_policy_document的DRY方案咨询
最初实现方案
data "aws_iam_policy_document" "lambda_read_secrets" { statement { actions = [ "secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret", "secretsmanager:ListSecretVersionIds" ] effect = "Allow" resources = [ "${var.enable_test_users == true ? aws_secretsmanager_secret.test_user[0].arn : ""}", "${var.enable_prod_users == true ? aws_secretsmanager_secret.prod_user[0].arn : ""}" ] } statement { effect = "Allow" actions = ["secretsmanager:ListSecrets"] resources = ["*"] } }
上述配置运行时报错如下:
Error: error creating IAM policy test-lambda-logging20211011172058509500000003: MalformedPolicyDocument: Resource must be in ARN format or "*". status code: 400, request id: c5c62446-eba7-450d-b97d-505be530ba2d on ../../../../module/lambda/iam.tf line 58, in resource "aws_iam_policy" "lambda_read_secrets": 58: resource "aws_iam_policy" "lambda_read_secrets" {
报错原因是resources数组中存在条件判断返回的空字符串,不符合IAM策略的资源格式要求。
现有解决方案
当前采用的方案是分别声明data "aws_iam_policy_document" "dev_lambda_read_secrets"和data "aws_iam_policy_document" "prod-lambda_read_secrets"两份数据源,再根据部署环境做条件判断选用对应策略。
该方案的问题是需要重复声明几乎完全一致的策略,仅资源列表存在差异,不符合DRY原则。
最优实现方案
不需要拆分多份策略声明,用Terraform内置函数处理动态资源列表即可,有两种常用实现方式:
方案1:使用compact()函数过滤空值
直接在资源列表外层包裹compact()函数,自动移除数组内的空字符串元素:
data "aws_iam_policy_document" "lambda_read_secrets" { statement { actions = [ "secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret", "secretsmanager:ListSecretVersionIds" ] effect = "Allow" resources = compact([ var.enable_test_users ? aws_secretsmanager_secret.test_user[0].arn : "", var.enable_prod_users ? aws_secretsmanager_secret.prod_user[0].arn : "" ]) } statement { effect = "Allow" actions = ["secretsmanager:ListSecrets"] resources = ["*"] } }
方案2:使用concat()拼接动态数组
直接根据条件返回对应元素的数组,条件不成立时返回空数组,拼接后不会生成空值:
data "aws_iam_policy_document" "lambda_read_secrets" { statement { actions = [ "secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret", "secretsmanager:ListSecretVersionIds" ] effect = "Allow" resources = concat( var.enable_test_users ? [aws_secretsmanager_secret.test_user[0].arn] : [], var.enable_prod_users ? [aws_secretsmanager_secret.prod_user[0].arn] : [] ) } statement { effect = "Allow" actions = ["secretsmanager:ListSecrets"] resources = ["*"] } }
两种方案都可以生成符合IAM规范的策略,不需要重复声明多份策略配置,完全符合DRY原则。
内容的提问来源于stack exchange,提问作者AlexLordThorsen
相关产品推荐
相关产品推荐

