执行 terraform plan 时出现 Terraform 403 Forbidden 错误

8
我们目前使用S3作为保留tf状态文件的后端。在执行terraform plan时我们收到以下错误:
Error: Forbidden: Forbidden
        status code: 403, request id: 18CB0EA827E6FE0F, host id: 8p0TMjzvooEBPNakoRsO3RtbARk01KY1KK3z93Lwyvh1Nx6sw4PpRyfoqNKyG2ryMNAHsdCJ39E=

我们已启用调试模式,下面是我们注意到的错误消息。
2020-05-31T20:02:20.842+0400 [DEBUG] plugin.terraform-provider-aws_v2.64.0_x4: Accept-Encoding: gzip
2020-05-31T20:02:20.842+0400 [DEBUG] plugin.terraform-provider-aws_v2.64.0_x4: 
2020-05-31T20:02:20.842+0400 [DEBUG] plugin.terraform-provider-aws_v2.64.0_x4: 
2020-05-31T20:02:20.842+0400 [DEBUG] plugin.terraform-provider-aws_v2.64.0_x4: -----------------------------------------------------
2020/05/31 20:02:20 [ERROR] <root>: eval: *terraform.EvalRefresh, err: Forbidden: Forbidden
        status code: 403, request id: 2AB56118732D7165, host id: 5sM6IwjkufaDg1bt5Swh5vcQD2hd3fSf9UqAtlL4hVzVaGPRQgvs1V8S3e/h3ta0gkRcGI7GvBM=
2020/05/31 20:02:20 [ERROR] <root>: eval: *terraform.EvalSequence, err: Forbidden: Forbidden
        status code: 403, request id: 2AB56118732D7165, host id: 5sM6IwjkufaDg1bt5Swh5vcQD2hd3fSf9UqAtlL4hVzVaGPRQgvs1V8S3e/h3ta0gkRcGI7GvBM=
2020/05/31 20:02:20 [TRACE] [walkRefresh] Exiting eval tree: aws_s3_bucket_object.xxxxxx
2020/05/31 20:02:20 [TRACE] vertex "aws_s3_bucket_object.xxxxxx": visit complete
2020/05/31 20:02:20 [TRACE] vertex "aws_s3_bucket_object.xxxxxx: dynamic subgraph encountered errors
2020/05/31 20:02:20 [TRACE] vertex "aws_s3_bucket_object.xxxxxx": visit complete

我们尝试过将代码和tfstate文件回滚到可行版本,也删除了本地的tfstate文件。但仍然出现相同的错误。
s3存储桶策略如下:
{
            "Sid": "DelegateS3Access",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::xxxxxx:role/Administrator"
            },
            "Action": [
                "s3:ListBucket",
                "s3:GetObject",
                "s3:GetObjectTagging"
            ],
            "Resource": [
                "arn:aws:s3:::xxxxxx/*",
                "arn:aws:s3:::xxxxxx"
            ]
        }

terraform在执行时承担了相同的角色,但仍然失败。我已清空存储桶策略并尝试过,但没有看到任何成功。我知道这与存储桶策略本身有关,但不确定如何修复。

非常感谢您提供解决此问题的任何指针。


在审查S3存储桶策略时,确保使用虚假占位符掩盖策略中的帐户ID、KMS密钥ID或其他个人身份信息(如人名或公司名称),这将有助于理解策略。 - Alain O'Dea
请同时发布IAM用户或IAM角色STS会话的组合IAM策略,当您运行Terraform时提供其凭证。 - Alain O'Dea
1
已更新存储桶策略的描述,请查看。 - Vamshi Siddarth
2个回答

8

在运行Terraform之前,需要检查您从AWS API角度看是谁:

aws sts get-caller-identity

如果输出结果是这样的,则表示您已经通过身份验证,但作为IAM用户,无法访问存储桶,因为该存储桶授予的是IAM角色而不是IAM用户:
{
    "UserId": "AIDASAMPLEUSERID",
    "Account": "123456789012",
    "Arn": "arn:aws:iam::123456789012:user/DevAdmin"
}

在这种情况下,您需要配置AWS CLI以假定 arn:aws:iam::xxxxxx:role/Administrator 角色。
[profile administrator]
role_arn = arn:aws:iam::xxxxxx:role/Administrator
source_profile = user1

在此过程中阅读更多相关信息:

https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html

如果 get-caller-identity 返回类似于此的内容,则表示您正在使用 IAM 角色,并且问题可能出在 Bucket 策略中的操作上。
{
    "UserId": "AIDASAMPLEUSERID",
    "Account": "123456789012",
    "Arn": "arn:aws:iam::123456789012:assumed-role/Administrator/role-session-name"
}

根据S3文档中的后端类型, 您还需要 s3:PutObject。
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::mybucket"
    },
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject"],
      "Resource": "arn:aws:s3:::mybucket/path/to/my/key"
    }
  ]
}

虽然我不清楚为什么在计划中需要使用PutObject,但这可能是导致Forbidden错误的原因。

如果启用了CloudTrail,您还可以在其中查找被拒绝的S3操作。


1
我们正在使用一个单一的S3存储桶作为多个模块的后端,所有其他模块的计划和应用都正常工作。只有在管理CDN和S3存储桶时才会出现问题。此外,我们已经尝试了放置和获取权限,但效果不大。将按建议查看CloudTrail日志。 - Vamshi Siddarth
1
谢谢。我已经在我的答案中添加了一些其他内容,关于使用IAM用户与IAM角色诊断和解释权限问题可能是这里的情况。 - Alain O'Dea
1
这个答案让我找到了一个相关原因。AWS有不同的凭证配置文件,而我使用了错误的配置文件。发现我的terraform支持的s3块允许我指定配置文件,所以我这样做了,然后它就起作用了。 - Andrew Allaire

2
问题已经解决。我们之前进行了一次s3复制操作,将所有的s3对象从A账户复制到B账户。问题在于复制命令总是将对象与相同的用户权限一起移动,这使得当前用户角色无法访问这些新复制的对象,导致返回403禁止错误。
我们清除了存储桶中的所有对象,并使用aws sync命令代替cp命令,这为我们解决了问题。感谢Alain提供详细的说明,这些确实帮助我们解决了这个问题。
这里提供的链接帮助我们找到了正确的问题。
所遵循的步骤如下:
  1. 备份所有s3对象。
  2. 清空存储桶。
  3. 运行terraform plan
  4. 对存储桶进行更改后,运行aws sync命令。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接