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变化不会刷新已启动实例的环境变量。
配置说明与完整示例(按需展开)
前置: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"