创建 IAM 角色时出错。 MalformedPolicyDocument:已禁止字段资源。地形

Posted

技术标签:

【中文标题】创建 IAM 角色时出错。 MalformedPolicyDocument:已禁止字段资源。地形【英文标题】:Error creating IAM Role. MalformedPolicyDocument: Has prohibited field Resource. Terraform 【发布时间】:2020-09-10 05:55:24 【问题描述】:

我看过几个链接,但我必须看一个例子。 我有:

resource "aws_iam_role" "role" 
  name = "role"

  assume_role_policy = <<-EOF

    "Version": "2012-10-17",
    "Statement": [
      
        "Sid": "Stmt1590217939125",
        "Action": "s3:*",
        "Effect": "Allow",
        "Resource": "arn:aws:s3:::wwe"
      ,
      
        "Sid": "Stmt1590217939125",
        "Action": "s3:*",
        "Effect": "Allow",
        "Resource": "arn:aws:s3:::wwe/*"
      ,
      
        "Sid": "Stmt1577967806846",
        "Action": [
          "secretsmanager:DescribeSecret",
          "secretsmanager:GetRandomPassword",
          "secretsmanager:GetResourcePolicy",
          "secretsmanager:GetSecretValue",
          "secretsmanager:ListSecretVersionIds",
          "secretsmanager:ListSecrets"
        ],
        "Effect": "Allow",
        "Resource": "*"
      
    ]

  EOF
  tags = 
    Name        = wwe
    Environment = STAGE
  

当我在制作时,

terraform apply

我看到了:

  # aws_iam_role.role will be created
  + resource "aws_iam_role" "role" 
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            
              + Statement = [
                  + 
                      + Action   = "s3:*"
                      + Effect   = "Allow"
                      + Resource = "arn:aws:s3:::wwe"
                      + Sid      = "Stmt1590217939125"
                    ,
                  + 
                      + Action   = "s3:*"
                      + Effect   = "Allow"
                      + Resource = "arn:aws:s3:::wwe/*"
                      + Sid      = "Stmt1590217939125"
                    ,
                  + 
                      + Action   = [
                          + "secretsmanager:DescribeSecret",
                          + "secretsmanager:GetRandomPassword",
                          + "secretsmanager:GetResourcePolicy",
                          + "secretsmanager:GetSecretValue",
                          + "secretsmanager:ListSecretVersionIds",
                          + "secretsmanager:ListSecrets",
                        ]
                      + Effect   = "Allow"
                      + Resource = "*"
                      + Sid      = "Stmt1577967806846"
                    ,
                ]
              + Version   = "2012-10-17"
            
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + max_session_duration  = 3600
      + name                  = "role"
      + path                  = "/"
      + tags                  = 
          + "Environment" = "STAGE"
          + "Name"        = "wwe"
        
      + unique_id             = (known after apply)
    

之后,当我写yes 时,我看到了:

Error: Error creating IAM Role role: MalformedPolicyDocument: Has prohibited field Resource
        status code: 400

哪里出错了?请不要发布相同问题的链接。我不明白,我哪里有错误,请你写一个例子,我哪里有错误,如果可能的话。 感谢您的关注。

【问题讨论】:

类似的东西,可能会有所帮助:***.com/questions/44565879/… 【参考方案1】:

一个问题是您有两个具有相同 Sid 的语句:Stmt1590217939125

Sid 必须是唯一的。来自docs:

在 IAM 中,Sid 值在 JSON 策略中必须是唯一的

第二个问题是assume_role_policy 用于信任策略。信任策略没有资源。它们有不同的形式。对于instance:

 assume_role_policy = <<EOF

  "Version": "2012-10-17",
  "Statement": [
    
      "Action": "sts:AssumeRole",
      "Principal": 
        "Service": "ec2.amazonaws.com"
      ,
      "Effect": "Allow",
      "Sid": ""
    
  ]

要将您的策略​​添加到角色,必须使用aws_iam_role_policy_attachment。例如,您可以这样做:

resource "aws_iam_policy" "policy" 
  name = "my-role"
   description = "My policy"

  policy = <<-EOF

    "Version": "2012-10-17",
    "Statement": [
      
        "Sid": "Stmt1590217939128",
        "Action": "s3:*",
        "Effect": "Allow",
        "Resource": "arn:aws:s3:::wwe"
      ,
      
        "Sid": "Stmt1590217939125",
        "Action": "s3:*",
        "Effect": "Allow",
        "Resource": "arn:aws:s3:::wwe/*"
      ,
      
        "Sid": "Stmt1577967806846",
        "Action": [
          "secretsmanager:DescribeSecret",
          "secretsmanager:GetRandomPassword",
          "secretsmanager:GetResourcePolicy",
          "secretsmanager:GetSecretValue",
          "secretsmanager:ListSecretVersionIds",
          "secretsmanager:ListSecrets"
        ],
        "Effect": "Allow",
        "Resource": "*"
      
    ]

EOF


resource "aws_iam_role_policy_attachment" "test-attach" 
  role       = "$aws_iam_role.role.name"
  policy_arn = "$aws_iam_policy.policy.arn"

【讨论】:

【参考方案2】:

现有代码有什么问题?

aws_iam_role resource 的 assume_role_policy 属性不用于授予调用除 sts:AssumeRole 以外的 API 的权限:

assume_role_policy -(必需)授予实体代入角色权限的策略。

注意:此假设角色策略与标准 IAM 策略非常相似但略有不同,并且不能使用 aws_iam_policy 资源。但是,它可以使用 aws_iam_policy_document 数据源,请参阅下面的示例以了解其工作原理。

我该如何解决?

因此,假设您希望 EC2 可以担任此角色,您将使用 aws_iam_role 来声明 IAM 角色及其 assume_role_policy

resource "aws_iam_role" "role" 
  name = "role"

  assume_role_policy = <<-EOF
  EOF
  tags = 
    Name        = wwe
    Environment = STAGE
  

然后使用 aws_iam_role_policy 将内联策略附加到您希望授予该角色的 IAM 操作(以及资源​​和可能的条件):

resource "aws_iam_role_policy" "policy" 
  name = "policy"
  role = aws_iam_role.role.id

  policy = <<-EOF
  
      "Version": "2012-10-17",
      "Statement": [
        
          "Action": "s3:*",
          "Effect": "Allow",
          "Resource": "arn:aws:s3:::wwe"
        ,
        
          "Action": "s3:*",
          "Effect": "Allow",
          "Resource": "arn:aws:s3:::wwe/*"
        ,
        
          "Action": [
            "secretsmanager:DescribeSecret",
            "secretsmanager:GetRandomPassword",
            "secretsmanager:GetResourcePolicy",
            "secretsmanager:GetSecretValue",
            "secretsmanager:ListSecretVersionIds",
            "secretsmanager:ListSecrets"
          ],
          "Effect": "Allow",
          "Resource": "*"
        
      ]
  
  EOF

你不需要把你的 JSON 塞进边缘,它可以缩进以提高可读性:

Terraform 还接受由 indented heredoc string 变体:

block 
  value = <<-EOT
  hello
    world
  EOT

我建议使用 aws_iam_policy_document 数据源来构建您的 IAM 策略。它避免了令人讨厌的 JSON 怪癖(比如没有尾随逗号),并且更好地支持您需要在构建策略时使用变量的场景(在所有情况下都很难正确地转义它们):

resource "aws_iam_role_policy" "policy" 
  name = "policy"
  policy = data.aws_iam_policy_document.policy_doc.json


data "aws_iam_policy_document" "policy_doc" 
  statement 
    actions = [
      "s3:*",
    ]

    resources = [
      "arn:aws:s3:::wwe",
    ]
  

  statement 
    actions = [
      "s3:*",
    ]

    resources = [
      "arn:aws:s3:::wwe/*",
    ]
  

  statement 
    actions = [
      "secretsmanager:DescribeSecret",
      "secretsmanager:GetRandomPassword",
      "secretsmanager:GetResourcePolicy",
      "secretsmanager:GetSecretValue",
      "secretsmanager:ListSecretVersionIds",
      "secretsmanager:ListSecrets",
    ]

    resources = [
      "*",
    ]
  

【讨论】:

以上是关于创建 IAM 角色时出错。 MalformedPolicyDocument:已禁止字段资源。地形的主要内容,如果未能解决你的问题,请参考以下文章

使用 Terraform 创建 GCP 自定义 IAM 角色

在 Terraform for GCP 中允许帐户和角色时出错

重命名 IAM 角色

如何使用 Terraform 创建没有代入角色策略的 AWS IAM 角色?

在多账户 AWS 环境中,我将如何在 IAM 用户登录时强制他/她承担角色?

AWS IAM 策略允许用户创建具有特定策略/角色的 IAM 用户