AWS环境下如何跨账号存储Terraform状态并执行资源变更
1. 关于assume_role_policy_arns参数的填写说明
你目前存在参数认知误区:assume_role_policy_arns不是用来填写待代入角色ARN的,S3后端相关参数的作用分别是:
role_arn:跨账号访问S3时必填,填写Infrastructure Account(账号ID111)中,拥有S3状态桶读写、DynamoDB锁表读写权限的IAM角色ARN。Terraform操作状态文件时会先代入这个角色获取临时凭证。assume_role_policy_arns:可选参数,仅当你需要给上述role_arn对应的临时会话附加权限边界、缩限默认权限时才需要填写,值为IAM策略的ARN列表;如果你不需要额外缩限权限,这个参数可以直接删除,不需要填任何值。
结合你使用AWS Control Tower + AWS SSO的场景,ControlTower为每个账号预置的SSO管理员角色ARN格式为:arn:aws:iam::<账号ID>:role/aws-reserved/sso.amazonaws.com/<SSO部署区域>/AWSReservedSSO_AWSAdministratorAccess_<随机后缀>
你可以在登录SSO后,在IAM控制台的角色列表找到111账号下对应的管理员角色,复制ARN填入role_arn即可。不过最佳实践是不要直接用管理员角色操作状态文件,建议在111账号新建一个Terraform专用后端角色,仅授予状态桶和锁表的最小必要权限。
修正后的后端配置示例:
terraform { backend "s3" { bucket = "terraform-infrastructure" key = "dev/sqs/terraform.tfstate" region = "us-east-1" # 替换为111账号下用于访问状态文件的角色ARN role_arn = "arn:aws:iam::111:role/aws-reserved/sso.amazonaws.com/us-east-1/AWSReservedSSO_AWSAdministratorAccess_xxxxxx" # 不需要权限缩限的话直接删掉assume_role_policy_arns配置即可 # 建议搭配DynamoDB表开启状态锁,避免并发写冲突 dynamodb_table = "terraform-state-lock" encrypt = true } required_providers { aws = { source = "hashicorp/aws" version = "~> 4.16" } } required_version = ">= 1.2.0" }
2. 关于S3额外配置的判断纠正
你的判断不完全正确,核心原因是Terraform操作S3状态文件的身份,和操作DEV账号资源的身份是完全独立的两套配置:
- 如果你在S3后端块中明确配置了使用111账号内的角色访问S3桶(比如上面示例的
role_arn填111账号内的角色),且该角色本身已经有S3桶的读写权限,那么确实不需要额外配置S3跨账号访问策略,因为这属于账号内角色访问同账号S3资源,默认权限足够。 - 如果你没有配置后端的
role_arn,误用了DEV账号(222)的角色身份去访问111账号的S3桶,那么S3默认会拒绝跨账号访问请求,这时候你必须给S3桶添加桶策略,明确允许222账号的对应角色执行s3:GetObject、s3:PutObject等状态操作必要的权限。
另外建议给状态S3桶做几个基础配置,符合ControlTower安全基线:
- 开启版本控制,避免状态文件误删无法恢复
- 开启SSE-KMS加密,保护状态文件里的敏感数据
- 开启公共访问阻止,避免状态文件泄露
- 搭配同区域DynamoDB表开启状态锁,避免多人同时执行Terraform导致状态文件损坏
3. 补充:AWS Provider配置建议
你当前的provider块只配置了允许的账号ID,还需要补充DEV账号对应的角色ARN,否则Terraform会默认用操作后端的身份去操作DEV账号的资源,会因为权限不足报错。修正后的provider配置示例:
provider "aws" { region = "us-east-1" allowed_account_ids = ["222"] # 替换为222账号下的SSO管理员角色ARN,或专用的Terraform资源操作角色ARN assume_role { role_arn = "arn:aws:iam::222:role/aws-reserved/sso.amazonaws.com/us-east-1/AWSReservedSSO_AWSAdministratorAccess_xxxxxx" } }
执行Terraform操作前,你只需要通过aws sso login登录自己的SSO身份,该身份拥有两个账号的角色代入权限即可,Terraform会自动完成两次角色代入:先代入111账号的角色读写状态,再代入222账号的角色操作资源。
内容的提问来源于stack exchange,提问作者Ashwin Jacob

