![如何修复 Terraform 无效的 JSON 策略](https://linux22.com/image/781468/%E5%A6%82%E4%BD%95%E4%BF%AE%E5%A4%8D%20Terraform%20%E6%97%A0%E6%95%88%E7%9A%84%20JSON%20%E7%AD%96%E7%95%A5.png)
我正在尝试在 terraform 中使用包含负载均衡器 iam 策略的文件来为我的 AWS 使用。但是,当我运行 terraform 脚本时,出现以下错误:
Error: "policy" contains an invalid JSON policy
│
│ with module.iam.aws_iam_policy.test-AWSLoadBalancerControllerIAMPolicy,
│ on ../resources/IAM/main.tf line 77, in resource "aws_iam_policy" "test-AWSLoadBalancerControllerIAMPolicy":
│ 77: policy = jsonencode(var.policy_file)
我正在使用 jsonencode 函数导入策略文件的内容。
resource "aws_iam_policy" "test-AWSLoadBalancerControllerIAMPolicy" {
name = var.aws_loadbalancer_controller_policy
policy = jsonencode(var.policy_file)
}
上面的 iam_policy_file 变量的值像这样传入file("../resources/IAM/policy.json")
,该文件的内容如下所示,我已经检查过这个 json 文件是否在线解析为有效的 json,并且确实如此,但是 Terraform 抛出错误,好像它的格式不正确。
策略.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:CreateServiceLinkedRole"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:AWSServiceName": "elasticloadbalancing.amazonaws.com"
}
}
},
{
"Effect": "Allow",
"Action": [
"ec2:DescribeAccountAttributes",
"ec2:DescribeAddresses",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeInternetGateways",
"ec2:DescribeVpcs",
"ec2:DescribeVpcPeeringConnections",
"ec2:DescribeSubnets",
"ec2:DescribeSecurityGroups",
"ec2:DescribeInstances",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeTags",
"ec2:GetCoipPoolUsage",
"ec2:DescribeCoipPools",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:DescribeLoadBalancerAttributes",
"elasticloadbalancing:DescribeListeners",
"elasticloadbalancing:DescribeListenerCertificates",
"elasticloadbalancing:DescribeSSLPolicies",
"elasticloadbalancing:DescribeRules",
"elasticloadbalancing:DescribeTargetGroups",
"elasticloadbalancing:DescribeTargetGroupAttributes",
"elasticloadbalancing:DescribeTargetHealth",
"elasticloadbalancing:DescribeTags"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"cognito-idp:DescribeUserPoolClient",
"acm:ListCertificates",
"acm:DescribeCertificate",
"iam:ListServerCertificates",
"iam:GetServerCertificate",
"waf-regional:GetWebACL",
"waf-regional:GetWebACLForResource",
"waf-regional:AssociateWebACL",
"waf-regional:DisassociateWebACL",
"wafv2:GetWebACL",
"wafv2:GetWebACLForResource",
"wafv2:AssociateWebACL",
"wafv2:DisassociateWebACL",
"shield:GetSubscriptionState",
"shield:DescribeProtection",
"shield:CreateProtection",
"shield:DeleteProtection"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ec2:AuthorizeSecurityGroupIngress",
"ec2:RevokeSecurityGroupIngress"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ec2:CreateSecurityGroup"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ec2:CreateTags"
],
"Resource": "arn:aws:ec2:*:*:security-group/*",
"Condition": {
"StringEquals": {
"ec2:CreateAction": "CreateSecurityGroup"
},
"Null": {
"aws:RequestTag/elbv2.k8s.aws/cluster": "false"
}
}
},
{
"Effect": "Allow",
"Action": [
"ec2:CreateTags",
"ec2:DeleteTags"
],
"Resource": "arn:aws:ec2:*:*:security-group/*",
"Condition": {
"Null": {
"aws:RequestTag/elbv2.k8s.aws/cluster": "true",
"aws:ResourceTag/elbv2.k8s.aws/cluster": "false"
}
}
},
{
"Effect": "Allow",
"Action": [
"ec2:AuthorizeSecurityGroupIngress",
"ec2:RevokeSecurityGroupIngress",
"ec2:DeleteSecurityGroup"
],
"Resource": "*",
"Condition": {
"Null": {
"aws:ResourceTag/elbv2.k8s.aws/cluster": "false"
}
}
},
{
"Effect": "Allow",
"Action": [
"elasticloadbalancing:CreateLoadBalancer",
"elasticloadbalancing:CreateTargetGroup"
],
"Resource": "*",
"Condition": {
"Null": {
"aws:RequestTag/elbv2.k8s.aws/cluster": "false"
}
}
},
{
"Effect": "Allow",
"Action": [
"elasticloadbalancing:CreateListener",
"elasticloadbalancing:DeleteListener",
"elasticloadbalancing:CreateRule",
"elasticloadbalancing:DeleteRule"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"elasticloadbalancing:AddTags",
"elasticloadbalancing:RemoveTags"
],
"Resource": [
"arn:aws:elasticloadbalancing:*:*:targetgroup/*/*",
"arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*",
"arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*"
],
"Condition": {
"Null": {
"aws:RequestTag/elbv2.k8s.aws/cluster": "true",
"aws:ResourceTag/elbv2.k8s.aws/cluster": "false"
}
}
},
{
"Effect": "Allow",
"Action": [
"elasticloadbalancing:AddTags",
"elasticloadbalancing:RemoveTags"
],
"Resource": [
"arn:aws:elasticloadbalancing:*:*:listener/net/*/*/*",
"arn:aws:elasticloadbalancing:*:*:listener/app/*/*/*",
"arn:aws:elasticloadbalancing:*:*:listener-rule/net/*/*/*",
"arn:aws:elasticloadbalancing:*:*:listener-rule/app/*/*/*"
]
},
{
"Effect": "Allow",
"Action": [
"elasticloadbalancing:ModifyLoadBalancerAttributes",
"elasticloadbalancing:SetIpAddressType",
"elasticloadbalancing:SetSecurityGroups",
"elasticloadbalancing:SetSubnets",
"elasticloadbalancing:DeleteLoadBalancer",
"elasticloadbalancing:ModifyTargetGroup",
"elasticloadbalancing:ModifyTargetGroupAttributes",
"elasticloadbalancing:DeleteTargetGroup"
],
"Resource": "*",
"Condition": {
"Null": {
"aws:ResourceTag/elbv2.k8s.aws/cluster": "false"
}
}
},
{
"Effect": "Allow",
"Action": [
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:DeregisterTargets"
],
"Resource": "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*"
},
{
"Effect": "Allow",
"Action": [
"elasticloadbalancing:SetWebAcl",
"elasticloadbalancing:ModifyListener",
"elasticloadbalancing:AddListenerCertificates",
"elasticloadbalancing:RemoveListenerCertificates",
"elasticloadbalancing:ModifyRule"
],
"Resource": "*"
}
]
}
我从 AWS 文档中下载了这个文件这里
我也尝试通过从 http 响应中读取文件来使其工作,如下所示,但我仍然遇到同样的问题JSON 无效
data "http" "policy_json" {
url = "https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.4/docs/install/iam_policy.json"
}
resource "aws_iam_policy" "test-AWSLoadBalancerControllerIAMPolicy" {
name = var.aws_loadbalancer_controller_policy
policy = data.http.policy_json.request_body
}
答案1
您必须确保您分配的字符串包含对象的 JSON 表示形式。
根据您的描述,很难准确了解您的设置方式,但您应该检查以下一些潜在问题:
- 如果
var.policy_file
包含文件名,则 JSON 编码该文件名将生成包含文件名的 JSON 字符串。例如,如果var.policy_file
是../resources/IAM/policy.json
,则 JSON 编码将生成字面上的"../resources/IAM/policy.json"
,这不是有效的 IAM 策略。 - 如果
var.policy_file
包含直接结果,file("../resources/IAM/policy.json")
则表示您要求 Terraform 创建已包含 JSON 内容的字符串的 JSON 编码。例如,如果您的文件包含{"Version": "2012-10-17"}
JSON 编码,则会产生"{\"Version\": \"2012-10-17\"}"
-- 一个恰好包含更多 JSON 的 JSON 字符串,这也不是有效的 IAM 策略。
在上述两种情况下,您jsonencode
根本不需要使用,因为该文件大概已经包含 JSON 内容。
对于情况 1,您可以说policy = file(var.policy_file)
直接分配文件的内容。
对于情况 2,您可以说policy = var.policy_file
直接分配该变量中的 JSON 字符串。
jsonencode
仅当您打算分配尚未分配的 Terraform 对象值时才需要使用已经经过 JSON 编码,如下所示:
policy = jsonencode({
"Version" = "2012-10-17"
# ...
})
在这种情况下,jsonencode
需要将非字符串 Terraform 对象值转换为参数policy
所需的 JSON 字符串。