Google Cloud Secret Manager:核心概念与架构归纳

说实话,这三朵云里,GCP 的 Secret Manager 是我用得最顺手的。为啥?因为它把 KMS 和 Secret 管理拆得很干净,又用 IAM 统一了权限。嗯,今天咱们就把它掰开来看看。

Secret Manager 的底层逻辑

Secret Manager 本质上是一个版本化的键值存储。你存的是一个密钥值,但它会帮你保留多个版本,每个版本不可变。

我记得有次生产上出了事故——有人把旧密钥覆盖了,导致回滚要靠备份文件。GCP 这种设计,让每次变更都留下历史快照,回滚就是换个版本号的事。

一个小习惯:我通常会在创建 Secret 时,把第一版叫做 "v1-init",后面轮转时自动生成递增版本。这样看审计日志时一目了然。

资源模型:Secret → Secret Version → Payload

结构很清晰,就三层:

  • Secret:逻辑容器,包含元数据(标签、轮转周期、复制策略)。
  • Secret Version:不可变的版本快照,每个版本有唯一 ID(如 "1"、"2"、"latest")。
  • Payload:实际存储的密文(最大 64KB,二进制或文本)。

你想想看,这种设计有什么好处?版本之间完全隔离,你永远不用担心「改了一个版本,其他版本跟着乱掉」。

组件特点常见操作
Secret可设标签、轮转策略、复制区域创建、删除、更新元数据
Secret Version创建后不可修改新增、禁用、销毁(Destroy)、启用
Payload明文只存在于 API 请求中读取(需解密权限)、写入(需加密权限)
注意:Secret Manager 不会自动清理旧版本。如果你不定期清理已禁用的版本,项目里的 Secret 数量会蹭蹭往上涨,超过配额后就会报错。我曾经因为忘清理,导致 CI/CD 管道集体失败。

权限模型:IAM + 细粒度控制

GCP 的权限体系和 AWS 不同:它没有资源策略,全靠 IAM 角色绑定。你可以在项目级、"Secret 级"甚至版本级授予权限。

我习惯的权限拆分:

  • secretmanager.secrets.create:只给管理员,用来新建 Secret。
  • secretmanager.versions.access:只给应用运行时账号,只能读取最新版本。
  • secretmanager.versions.destroy:只有安全团队才能销毁旧版本。

说白了,你把 "读" 和 "写" 分开,事故率至少降一半。我做审计时发现,很多泄漏都是因为给了一个「roles/secretmanager.admin」给整个团队。

避坑指南:我曾经给 GKE 的 Workload Identity 绑定了一个 "secretmanager.secretVersionAdder" 角色,结果应用只在启动时读一次密钥,完全不需要写权限。给最小权限,真的能救命。

自动轮转:Clock + Pub/Sub 组合拳

GCP 的自动轮转依赖Cloud Scheduler + Pub/Sub 触发 Cloud Functions 或 Cloud Run。流程是:

  1. 你设置一个轮转周期(比如 30 天)。
  2. 到时间后,Scheduler 发消息到 Pub/Sub Topic。
  3. 一个 Cloud Function 监听到消息,生成新版本并禁用旧版本。
  4. 应用通过 监听 Pub/Sub 事件或不断轮询,拿到新版本。

嗯,这里要注意:GCP 不提供内置的限时有效期自动销毁。你只能自己写逻辑,在新建版本 30 天后把旧版本销毁掉。

# 一个简单的轮转 Cloud Function 示例(Python)
import os
from google.cloud import secretmanager

def rotate_secret(event, context):
    client = secretmanager.SecretManagerServiceClient()
    secret_name = os.environ['SECRET_NAME']
    project_id = os.environ['PROJECT_ID']
    parent = f"projects/{project_id}/secrets/{secret_name}"
    # 添加新版本
    payload = os.urandom(32)  # 示例:生成随机密钥
    version = client.add_secret_version(
        request={"parent": parent, "payload": {"data": payload}}
    )
    print(f"Created version: {version.name}")
    # 禁用除最新外的所有旧版本
    versions = client.list_secret_versions(request={"parent": parent})
    for v in versions:
        if v.state == secretmanager.SecretVersion.State.ENABLED and v.name != version.name:
            client.disable_secret_version(request={"name": v.name})
我的习惯:轮转函数里不要直接把旧版本销毁,先禁用保留 7 天。万一新密钥有问题,还能手动启用旧版本回滚。

审计与监控:日志 + VPC Service Controls

每次访问 Secret Manager,都会产生Audit Logs(数据访问日志)。你可以用这个来看谁、在什么时间、读了哪个版本。

  • 默认只记录管理活动(创建、删除 Secret)。
  • 需要手动开启数据访问日志,才能看到谁读了 Payload。
  • 日志会包含调用者身份、版本号、响应大小(不包含明文)。

另外,GCP 有 VPC Service Controls,可以限制 Secret Manager 只能在你的 VPC 内访问。我在金融机构做合规项目时,这个功能是必须开的——防止数据通过互联网泄露。

小心!数据访问日志产生大量日志,尤其在微服务架构下。如果每个 Pod 每分钟读一次密钥,日志费用可能比密钥本身还贵。我建议只开启采样日志或只在轮转期间开启全量审计。

核心架构图

下面这张图概括了 Secret Manager 的核心组件和交互流程。注意看版本之间的状态转换,以及轮转触发路径。

Google Cloud Secret Manager 核心架构 Secret (逻辑容器) Version 1(当前) Version 2(禁用) Version 3(销毁) IAM 权限模型 secretmanager.* Cloud Scheduler 每30天触发 Pub/Sub Topic: rotate-secret Cloud Function 添加新版本+禁用旧版本 审计日志 谁、何时、读了哪个版本 应用运行时 读取 latest 版本 不可变版本 创建后不可修改

几个关键差异(对比 AWS/Azure)

如果你用过其他云,这里几个点可以快速对比:

  • 版本管理:GCP 没有「暂存版本」概念,所有版本要么启用、禁用或销毁。AWS Secrets Manager 有「待处理版本」,Azure Key Vault 分「当前版本」和「旧版本」。
  • 自动轮转:GCP 需要你自己写轮转函数;AWS 提供原生 Lambda 轮转模板;Azure 用 Key Vault 的自动轮转(仅限部分第三方集成)。
  • 跨区域复制:GCP 通过Secret 策略指定副本区域,AWS 用复制规则,Azure 用软删除+异地备份。
  • 定价:GCP 按版本数量 + API 调用收费;AWS 按存储 + 版本数;Azure 按密钥数 + 操作次数。嗯,GCP 其实是最便宜的,尤其当你的密钥数量大但读取频率低时。
避坑指南:我曾经在 GCP 上误操作,把整个 Secret 删除了。GCP 默认有软删除,但只保留 30 天。如果你在 30 天内没恢复,数据就彻底没了。所以 —— 我建议在部署前先跑个 terraform destroy 模拟一下,看看会不会删错。

好了,这就是 GCP Secret Manager 的核心概念。简单总结一下:不可变版本 + IAM 细粒度 + 手动轮转 + 清晰审计。实际用起来,只要把权限和版本生命周期管好,基本不会出大问题。下一个章节咱们聊聊 Azure Key Vault,到时候你会发现它的资源模型和这里完全不同。