访问密钥与配置
密钥管理这件事,说大不大,说小不小。我在实际项目里见过太多因为密钥泄露导致的事故了——有的直接把线上数据库给拖走了,有的被恶意刷了十几万的短信费。嗯,这章咱们就把密钥怎么拿、怎么存、怎么用,一次说清楚。
密钥的两种形态
Secrets Manager 的 SDK 接入,本质上就靠两样东西:访问密钥(Access Key)和配置环境。
| 类型 | 说明 | 使用场景 |
|---|---|---|
| 长期密钥 | Access Key ID + Secret Access Key | 本地开发、CI/CD、自建服务器 |
| 临时密钥 | STS 颁发的 | 生产环境、短期任务、跨账号授权 |
个人习惯:能不用长期密钥就别用。我一般只在本地开发时用长期密钥,生产环境一律走临时凭据。
密钥从哪里来?
你得先有一个 Secrets Manager 的访问身份。最常见的方式:
- 在云控制台创建一个子账号,赋予 SecretsManager 的读取权限
- 为该子账号生成 Access Key ID 和 Secret Access Key
- 把密钥下载到本地保存好——注意,下载后只有一次机会
讲究点的团队,会把密钥存在内部的密码管理工具里,比如 1Password、Keybase 或者 Vault。我遇到过一个项目,工程师直接把密钥写在代码里提交到 Git 仓库了……结果扫描工具报警,全组人连夜改密码。
千万别这么做:不要把密钥硬编码在源代码、配置文件或者环境变量的日志里。我曾经见过有人因为图方便,在 Dockerfile 里 ENV 直接写 Access Key,镜像一 push 到公共仓库——整个账号就裸奔了。
配置密钥的四种姿势
SDK 怎么知道用哪组密钥?官方 SDK 通常按优先级从高到低查找:
- 环境变量:
AWS_ACCESS_KEY_ID+AWS_SECRET_ACCESS_KEY - 配置文件:
~/.aws/credentials或~/.aws/config - ECS 容器角色:容器或 ECS 任务绑定的 IAM 角色
- 实例元数据:EC2 实例绑定的 IAM 角色
我个人最推荐用环境变量——简单、明确、不容易乱。看看代码怎么写:
// 设置环境变量(Linux/macOS)
export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
export AWS_DEFAULT_REGION=cn-north-1
// 然后你的代码里直接创建客户端
const client = new SecretsManagerClient({ region: "cn-north-1" });
你想想看,这样是不是特别清晰?环境变量跟着进程走,不会污染全局。
配置文件详解
如果你用多套环境(比如开发、测试、生产),配置文件会更方便。位置在 ~/.aws/credentials,格式像下面这样:
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
[dev]
aws_access_key_id = AKIAIDEV123EXAMPLE
aws_secret_access_key = DEVsecretKeyExample123
[prod]
aws_access_key_id = AKIAPROD456EXAMPLE
aws_secret_access_key = PRODsecretKeyExample789
使用时通过环境变量 AWS_PROFILE 切换:
export AWS_PROFILE=prod
node app.js // 此时 SDK 自动读 prod 的密钥
我的经验:开发机上用 default 配置文件,CI 环境用环境变量注入,生产环境全部用 IAM 角色免密。这样能做到密钥零散落在人手里。
密钥安全存储与轮换
拿到了密钥,怎么存才安全?这里有一套我踩过坑总结出来的做法:
- 文件权限:配置文件必须
chmod 600,防止其他进程偷窥 - 不用版本控制:把
.aws/credentials加到.gitignore里 - 定期轮换:设置密钥 90 天过期,用脚本自动生成新密钥并更新到 Secrets Manager 里
- 审计日志:开启 CloudTrail 记录谁调用了密钥相关的 API
我曾经接手过一个遗留系统,密钥三四年没换过,连当初是谁创建的都查不到了……后来我写了个自动轮换脚本,每个月跑一次,再也没出事。
核心逻辑图
下面我把密钥获取与使用流程画出来,你一眼就能看明白:
常见配置陷阱
说几个我真实遇到过的问题,你写代码时能避开:
- 区域不匹配:密钥有绑定区域,比如 cn-north-1 的密钥调用 us-east-1 的 Secrets Manager 会直接 403。记得在客户端构造时显式指定 region。
- 权限过于宽泛:别给子账号配
SecretsManager:*,精确到资源 ARN 和操作。我在一个项目里发现有人配了通配符,结果一个测试账号能删掉所有密钥…… - 缓存过期问题:SDK 客户端会缓存密钥,但 Secrets Manager 的密钥可能被轮换。你如果不用 TTL 刷新,可能读到旧值。建议设置合理的缓存时长,比如 5 分钟。
- 日志泄露:打印
console.log(secret)或者将密钥写进日志文件,这是大忌。我见过线上排查问题时,运维直接把密钥输出到日志里,结果日志平台所有人都能看到。
一个小技巧:调试时可以临时开启 SDK 日志(设置
logLevel: 'debug'),但务必在发布前关掉。我通常会在配置中心加一个开关,只有开发环境才开,生产环境强制静默。
推荐的生产配置组合
如果你现在要搭建一套生产环境,我建议直接用这个模板:
| 环境 | 密钥获取方式 | 配置方式 |
|---|---|---|
| 本地开发 | 长期密钥(只限你自己的机器) | 环境变量 + .env 文件(不提交 Git) |
| 测试环境 | 长期密钥(每个项目独立子账号) | 配置文件 + AWS_PROFILE 切换 |
| 预发布/生产 | 临时密钥(STS 或 IAM 角色) | 自动注入(ECS / EC2 元数据 / Lambda 执行角色) |
这套方案我用了好几年,既灵活又安全。说白了,密钥管理没那么多花活——源头做对,过程加密,运行时自动,基本就不会出大问题。