You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为SOPS配置AWS别名,实现跨账号密钥部署与状态分离?

问题描述

我有一套可用的SOPS方案:使用aws_sops AWS账号的KMS加密文件,再将密钥部署到aws_secrets AWS账号的Secrets Manager中。

当前方案通过连接aws_sops账号,让.sops.yaml指向其KMS,并借助Provider别名完成密钥部署。但该方案会将aws_secrets工作区的状态保存到aws_sops账号的状态文件中,导致无法在已托管于aws_secrets账号的Terraform工作区部署此方案。

想调整方案,为aws_sops配置Provider别名,直接连接aws_secrets账号,但不清楚如何指定SOPS使用此AWS别名而非默认配置。

当前可行但不满意的方案

provider "aws" {
  alias   = "development"
  profile = "development"
}

provider "aws" {}
provider "sops" {}

terraform {
  backend "s3" {
    bucket  = "xxx-statefile"
    encrypt = true
    key     = "pat/terraform.tfstate"
  }
}

data "sops_file" "sops-secret" {
  source_file = "../secrets.json"
}

resource "aws_secretsmanager_secret" "pipeline" {
  provider                       = aws.development
  name                           = "service-accounts/pipeline/resource-access-pat"
  recovery_window_in_days        = 0
  force_overwrite_replica_secret = true
}

resource "aws_secretsmanager_secret_version" "pipeline" {
  provider  = aws.development
  secret_id = aws_secretsmanager_secret.pipeline.id
  secret_string = jsonencode(
    {
      "pat" : data.sops_file.sops-secret.data["token"]
  })
}

尝试过的失败方案

方案1:给sops_file数据源添加Provider别名

移除密钥资源的Provider别名,将别名配置到sops_file数据源块中,出现如下错误:

│ 错误:无效的数据源
│ 
│   在../data.tf第1行,data "sops_file" "test"块中:
│    1: data "sops_file" "test" {
│ 
│ HashiCorp/aws提供商不支持数据源"sops_file"。

该错误符合预期,因为sops_file仅用于读取本地文件。

方案2:为KMS添加IAM角色

给aws_sops的KMS配置拥有管理权限的IAM角色,配置如下:

"sops": {
        "kms": [
            {
                "arn": "arn:aws:kms:eu-west-2:xxx:key/xxx",
                "role": "arn:aws:iam::xxx:role/TerraformAccountAccessRole",
                "created_at": "2023-02-10T13:53:05Z",
                "enc": "xx==",
                "aws_profile": ""
            }

同时尝试添加aws_profile配置:

"sops": {
        "kms": [
            {
                "arn": "arn:aws:kms:xxx:xxx:key/xxx",
                "role": "arn:aws:iam::xxx:role/TerraformAccountAccessRole",
                "created_at": "2023-02-10T13:53:05Z",
                "enc": "xx==",
                "aws_profile": "aws_sops"
            }

但出现权限错误:

│ 错误:获取解密SOPS文件所需的数据密钥失败。
│ 
│ 组0:失败
│   arn:aws:kms:xxx:xxx:key/xxx: 失败
│     - | 创建AWS会话时出错:无法扮演角色
│       | "arn:aws:iam::xxx:role/TerraformAccountAccessRole":
│       | 访问被拒绝:用户:
│       | arn:aws:sts::089449186373:assumed-role/AWSReservedSSO_DevOps_xxx/xxx@xxx.com
│       | 无权执行:sts:AssumeRole 操作,资源:
│       | arn:aws:iam::xxx:role/TerraformAccountAccessRole
│       |       状态码:403,请求ID:
│       | d9327e8c-8ffc-4873-9279-112c1c8c7258
│ 
│ 恢复失败,因为没有主密钥能够解密文件。SOPS要恢复文件,至少需要一个密钥解密成功,但所有密钥均失败。

解决方案

核心思路

让SOPS通过角色切换访问aws_sops账号的KMS,同时将Terraform状态托管在aws_secrets账号,避免状态跨账号存储问题。

步骤1:修复IAM角色信任关系

解决方案2中的403权限错误:在aws_sops账号的TerraformAccountAccessRole角色的信任策略中,添加当前Terraform执行身份(即arn:aws:sts::089449186373:assumed-role/AWSReservedSSO_DevOps_xxx/xxx@xxx.com)的信任许可,允许其调用sts:AssumeRole。

示例信任策略:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:sts::089449186373:assumed-role/AWSReservedSSO_DevOps_xxx/xxx@xxx.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

步骤2:调整Terraform配置

修改配置,让默认AWS Provider连接aws_secrets账号,Terraform状态存储在该账号的S3桶中,部署Secrets Manager无需额外别名,SOPS通过文件内的角色配置自动切换身份解密:

# 默认Provider连接aws_secrets账号,用于状态存储和Secrets Manager部署
provider "aws" {
  profile = "aws_secrets" # 替换为你的aws_secrets账号本地配置名
}

# sops Provider保持默认,自动读取本地配置和环境变量
provider "sops" {}

terraform {
  backend "s3" {
    bucket  = "aws-secrets-state-bucket" # aws_secrets账号下的状态存储桶
    encrypt = true
    key     = "pat/terraform.tfstate"
    region  = "eu-west-2" # 替换为你的区域
  }
}

data "sops_file" "sops-secret" {
  source_file = "../secrets.json"
  # 无需指定Provider,SOPS会根据文件内的KMS角色配置切换身份
}

resource "aws_secretsmanager_secret" "pipeline" {
  name                           = "service-accounts/pipeline/resource-access-pat"
  recovery_window_in_days        = 0
  force_overwrite_replica_secret = true
}

resource "aws_secretsmanager_secret_version" "pipeline" {
  secret_id = aws_secretsmanager_secret.pipeline.id
  secret_string = jsonencode(
    {
      "pat" : data.sops_file.sops-secret.data["token"]
    })
}

步骤3:确认SOPS文件配置

确保加密后的secrets.json中,SOPS配置指向aws_sops账号的KMS和已配置信任关系的IAM角色,无需指定aws_profile:

"sops": {
    "kms": [
        {
            "arn": "arn:aws:kms:eu-west-2:xxx:key/xxx", # aws_sops账号的KMS ARN
            "role": "arn:aws:iam::xxx:role/TerraformAccountAccessRole", # aws_sops账号的目标角色
            "created_at": "2023-02-10T13:53:05Z",
            "enc": "xx=="
        }
    ]
}

验证步骤

  1. 手动执行角色假设命令,确认权限配置生效:
    aws sts assume-role --role-arn arn:aws:iam::xxx:role/TerraformAccountAccessRole --role-session-name test-sops
    
  2. 用SOPS手动解密文件,确认解密正常:
    sops decrypt ../secrets.json
    
  3. 运行terraform init和terraform apply,确认部署流程正常。

内容的提问来源于stack exchange,提问作者Staggerlee011

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 09:45:28