Secret Manager:授权、注入与轮换

验证:未记录
适用版本
未记录
验证范围
尚未登记验证记录。

保存密码和 API key;Console:Secret Manager。

推荐做法#

  • 应用仅对所需 Secret 授 Secret Accessor;发布者与 Secret 管理者分开。
  • Cloud Run 环境变量注入固定数字版本;轮换后发布并验证所有消费者。
  • 先在数据库 / 外部服务生成新凭证,再存 Secret;切换确认后撤销旧凭证。

常用操作#

替换为实际资源;本段不依赖 lab.env。

PROJECT_ID='REPLACE_PROJECT_ID'
SECRET='REPLACE_SECRET'

gcloud secrets versions list "$SECRET" --project="$PROJECT_ID"
gcloud secrets get-iam-policy "$SECRET" --project="$PROJECT_ID"

容易踩的坑#

禁用 Secret version 只阻止后续读取,不会注销数据库密码或清除已有连接/缓存。 轮换需在实际凭据签发方撤销旧凭证,并验证所有消费者已切换。

  • latest 变化不会刷新已启动实例的环境变量。

GKE Pod 读取 Secret

配置说明与完整示例(按需展开)

前置:IAM。Secret Manager 保存密码与 API token;SA(Service Account)是供应用和自动化任务使用的身份。访问云 API 时优先使用短期凭据;SA key 指 Service Account 的长期私钥,不应作为常规应用秘密保存。Service Account 说明

source lab.env
gcloud services enable secretmanager.googleapis.com
export SECRET_READER="lab-secret-reader@${PROJECT_ID}.iam.gserviceaccount.com"
export HUMAN_EMAIL=$(gcloud config get-value account)
gcloud iam service-accounts create lab-secret-reader
printf 'lab-only-value-v1' | gcloud secrets create lab-secret --data-file=- --replication-policy=automatic
gcloud secrets add-iam-policy-binding lab-secret --member="serviceAccount:$SECRET_READER" --role=roles/secretmanager.secretAccessor
gcloud iam service-accounts add-iam-policy-binding "$SECRET_READER" --member="user:$HUMAN_EMAIL" --role=roles/iam.serviceAccountTokenCreator
gcloud secrets versions access 1 --secret=lab-secret --impersonate-service-account="$SECRET_READER"

以上只使用合成值;真实密码不要出现在 shell 历史、构建日志或应用日志中。

权限边界:读本密钥成功,读其他密钥失败#

管理员另建只含合成值的对照密钥,不给 SECRET_READER 授权。预期拒绝必须出现在 Secret 访问阶段,而不是无法 impersonate SA:

printf 'synthetic-other-value' | gcloud secrets create lab-secret-other --data-file=- --replication-policy=automatic
gcloud secrets versions access 1 --secret=lab-secret --impersonate-service-account="$SECRET_READER" >/dev/null
# 预期 PERMISSION_DENIED;非零退出时核对错误类别。
gcloud secrets versions access 1 --secret=lab-secret-other --impersonate-service-account="$SECRET_READER" >/dev/null

再撤销本密钥的资源权限,以相同身份重测,传播完成后应拒绝:

gcloud secrets remove-iam-policy-binding lab-secret --member="serviceAccount:$SECRET_READER" --role=roles/secretmanager.secretAccessor
gcloud secrets versions access 1 --secret=lab-secret --impersonate-service-account="$SECRET_READER" >/dev/null
# 用管理员身份恢复实验授权,继续下面的轮换。
gcloud secrets add-iam-policy-binding lab-secret --member="serviceAccount:$SECRET_READER" --role=roles/secretmanager.secretAccessor

若仍可访问,检查 Project、Folder、Organization 上的授权及其他 binding,不盲目等待。生产按 Secret 资源授权;密钥管理员负责版本生命周期,应用仅访问所需秘密,发布者不默认拥有读取密码的权限。

轮换与验收#

printf 'lab-only-value-v2' | gcloud secrets versions add lab-secret --data-file=-
gcloud secrets versions access latest --secret=lab-secret --impersonate-service-account="$SECRET_READER"
gcloud secrets versions disable 1 --secret=lab-secret
# 预期失败:版本已禁用
gcloud secrets versions access 1 --secret=lab-secret --impersonate-service-account="$SECRET_READER"

应用更新至 v2 后再禁用 v1。环境变量方式注入 Secret 的 Cloud Run revision 建议固定版本号;已有实例的环境变量不会因为 latest 指向变化自动刷新。Cloud Run 密钥

恢复演练:gcloud secrets versions enable 1 --secret=lab-secret,确认旧版恢复可读。真实数据库密码轮换必须同时处理数据库、Secret 和连接池,单独新增 Secret 版本不够。

企业轮换:秘密版本与真实凭证一起切换#

阶段 放行条件与失败处理
准备 盘点 API、worker、定时任务和外部消费者;记录固定版本、凭证实际签发方、刷新方式和恢复窗口
生成新凭证 先在数据库/外部服务建立有效凭证,再存新 Secret 版本;仅新增一个字符串不会改变数据库密码
分批切换 用真实业务路径验证新连接、权限与事务,更新全部消费者;环境变量需滚动替换,连接池需刷新
撤销旧凭证 确认没有旧消费者,先按系统原生方式撤销旧登录能力,再禁用旧 Secret 版本;必要时结束旧数据库会话
故障恢复 旧凭证仍安全有效时可回退版本并重建消费者;已泄漏或已吊销的凭证不重新启用,改为签发新凭证
收尾 观察业务和认证错误,保存版本及消费者清单;保留恢复窗口后再销毁旧版本

禁止把“旧 Secret 读不到”当作旧密码已经失效;复制到应用内存、缓存或连接池的值不会被远程擦除。若系统不支持两套凭证并存,应安排已验证的原子更新或维护窗口,不能承诺无停机轮换。Secret Manager 最佳实践。

清理独立实验资源#

gcloud secrets delete lab-secret-other
gcloud secrets delete lab-secret
gcloud iam service-accounts delete "$SECRET_READER"

搜索文档

输入关键词,搜索所有文档。

↑ ↓ 选择 · Enter 打开 · Esc 关闭