在使用AWS的Terraform时,可以通过实例配置文件进行角色扮演

要在AWS上使用terraform apply,最现实的做法是给予所有的AWS操作权限。否则,每次尝试使用未使用过的服务或新服务时都需要进行策略修正。

即使准备一个专门用于terraform作业的实例,也不能始终开启太强大的权限。作为一个实例配置文件,我们只需切换到ReadOnlyAccess这种更轻量级的权限,并且只在执行terraform命令时赋予完全权限。我在尝试中遇到了一些问题,所以在这里做一些记录。

将Terraform操作员的IAM用户设为MFA必需,并通过该用户进行assume-role可能是最佳平衡点。本文介绍的是在此之前的步骤。假设assume-role的方法应该是共享的。

只读角色

    • Usecase: EC2

instance-profile として使える role
これを terraform作業用instance のIAM roleとして割り当てる

ReadOnlyAccess AWS 管理ポリシー
ProfileOnlyPolicy

instance-profile:ReadOnly-Role の instanceでの利用でなければ何もさせない

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Resource": "*",
            "Action": "*",
            "Effect": "Deny",
            "Condition": {
                "ArnEquals": {
                    "ec2:InstanceProfile": "arn:aws:iam::<account-id>:role/ReadOnly-Role"
                }
            }
        }
    ]
}

角色/地形变形角色

    • AdministratorAccess AWS 管理ポリシー

Terraform用に原則全部の操作を可能とする

ProfileOnlyPolicy

instance-profile:ReadOnly-Role の instanceでの利用でなければ何もさせない

PolicyDocument

role/ReadOnly-Role からの switch だけを許す

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<account-id>:role/ReadOnly-Role"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

提供者.tf

provider "aws" {
  region  = "ap-northeast-1"
  version = ">1.56.0"
  profile = "terraform-role"
}

terraform {
  backend "s3" {
    bucket = "foo-terraform"
    key    = "bar/terraform.tfstate"
    region = "ap-northeast-1"
    skip_metadata_api_check = true
    profile = "terraform-role"
  }
}

~/.aws/credentials可以被本地化为”家目录下的.aws文件夹中的credentials文件”。

[terraform-role]
role_arn = arn:aws:iam::<account-id>:role/Terraform-Role
credential_source = Ec2InstanceMetadata

政策/角色/資格的操作驗證

首先,我们需要验证在没有使用terraform的情况下能够查看的范围。

$ aws sts get-caller-identity
{
    "Account": <account-id>,
    "UserId": "xxxx:<instance-id>",
    "Arn": "arn:aws:sts::<account-id>:assumed-role/ReadOnly-Role/<instance-id>"
}
$ aws sts get-caller-identity --profile terraform-role
{
    "Account": <account-id>,
    "UserId": "xxxx:botocore-session-1598506181",
    "Arn": "arn:aws:sts::<account-id>:assumed-role/Terraform-Role/botocore-session-1598506181"
}

执行terraform应用程序

通过向现有资源添加新的标签,或者稍微更改注释标签的字符串,使用terraform apply命令。

一個選項的中文的翻譯為:迷住點

将terraform state保存在S3中的backend “s3″块十分棘手。

考虑到Terraform操作员的数量增加以及Terraform作业实例可能因故障或误操作而丢失,无法排除使用S3进行存储的必要性。

然而,无论在provider块中指定profile还是使用export AWS_PROFILE=设置环境变量,都会导致错误。

Failed to save state: failed to upload state: AccessDenied: Access Denied

尽管已经在资源中反映出为验证目的而添加的标签和标签字符,所以应该已经成功执行了assume-role。

如同代码块所示,backend块中也需要指定profile。后端保存操作似乎与提供者块的credential设置是独立的。此外,这里还需要添加skip_metadata_api_check = true选项。

参考问题
terraform-providers/terraform-provider-aws#5018

s3后端不使用提供者块。

下次遇到类似情况时,也试试这个。

我使用 TF_LOG=DEBUG 运行 terraform init。

bannerAds