aws-elixir安全指南:密钥管理、Session Token与签名控制的完整注意事项清单
【免费下载链接】aws-elixirAWS clients for Elixir项目地址: https://gitcode.com/gh_mirrors/aw/aws-elixir
aws-elixir 是为 Elixir 生态提供的 AWS 服务客户端库,一次配置即可调用 S3、DynamoDB、Kinesis 等几乎全部 AWS 服务。本文作为一份 aws-elixir 安全指南,围绕密钥管理、Session Token与签名控制三大核心主题,整理出可直接照做的注意事项清单,帮助你在上线前快速完成安全自检 🔐
为什么 aws-elixir 的密钥管理值得重视?
aws-elixir 将每个 AWS 服务封装为独立的 Elixir 模块(如AWS.S3、AWS.Kinesis),所有请求都通过一个统一的客户端结构体AWS.Client携带凭据发起。凭据管理是否规范,直接决定了你的密钥会不会泄露、权限会不会过大。
核心代码位置:
- 凭据与连接配置:lib/aws/client.ex
- SigV4 请求签名实现:lib/aws/signature.ex
- 请求组装与签名开关:lib/aws/request.ex
- 测试用例(可理解预期行为):test/aws/client_test.exs、test/aws/signature_test.exs
凭据注入:优先用环境变量,而不是硬编码
aws-elixir 支持多种创建客户端的方式,安全性从高到低排列如下:
1. 从环境变量读取(推荐)🌟
调用AWS.Client.create/1只传 region 时,库会自动从环境变量读取凭据,这是最不容易把密钥写死进代码的方式:
| 环境变量 | 作用 |
|---|---|
AWS_ACCESS_KEY_ID | Access Key ID |
AWS_SECRET_ACCESS_KEY | Secret Access Key |
AWS_SESSION_TOKEN | STS 临时会话令牌(可选) |
AWS_ENDPOINT | 自定义 endpoint(AWS 兼容 API) |
AWS_DEFAULT_REGION | 默认 region(create/0依赖它) |
如果缺少 Access Key 或 Secret,create/1会直接抛出RuntimeError(如missing access key id)而不是带着空凭据继续运行,这一点在 lib/aws/client.ex 中可以看到。
2. 显式传参
AWS.Client.create(access_key_id, secret_access_key, region)也支持直接传参,适合凭据由上层配置系统(配置中心、KMS 等)动态下发的场景。注意:不要把真实密钥提交到代码仓库,示例 examples/route53/change_rr.ex 演示了使用环境变量方式的用法。
3. 自建结构体
%AWS.Client{access_key_id: ..., secret_access_key: ..., region: ...}也可以手工构造,功能等价。
⚠️ 无论哪种方式,请遵循 IAM 最小权限原则:只授予应用真正需要的服务与操作权限,并定期轮换密钥。
Session Token 使用注意事项:临时凭据的正确姿势
当你使用 STS 获取临时凭据(Assume Role 等)时,得到的三元组是:临时 Access Key + 临时 Secret Key +Session Token。
在 aws-elixir 中的处理逻辑(见 lib/aws/signature.ex):
- 只要客户端结构体里
session_token不为空,签名时会自动注入X-Amz-Security-Token请求头; - 该头会一并参与 SigV4 签名计算,确保令牌不可被中间人篡改;
- 对应测试用例见 test/aws/signature_test.exs。
注意事项清单:
- ✅ 使用临时凭据时,必须把 token 传给
create/4(或设置AWS_SESSION_TOKEN环境变量),否则请求会被 AWS 拒绝; - ✅ 临时凭据有有效期(通常 15 分钟~12 小时),长驻服务需要实现凭据刷新逻辑,过期后会收到认证失败错误;
- ⚠️ 长期静态密钥只应在无法使用 STS 的场景下使用,能用角色(IAM Role)就尽量用角色。
签名控制:理解 SigV4 与 sign_request? 开关
aws-elixir 底层使用aws_signature依赖实现SigV4 签名(见 mix.exs 中的依赖声明),每个请求的签名要素包括:Access Key、region、服务名、日期与请求内容哈希。几个容易踩坑的点:
全局服务的 region 默认值
对路由 53(Route53)这类"全局服务",即使你的客户端没有设置 region,签名也会回退到us-east-1(lib/aws/signature.ex),这不是 bug,而是 AWS 官方约定。
何时可以关闭签名:sign_request?
REST 类请求支持选项sign_request?(默认true)。当你使用预签名 URL(Presigned URL)等本身已携带签名信息的请求时,可以传sign_request?: false跳过二次签名,见 lib/aws/request.ex。
⚠️ 只有在明确知道"不需要签名"时才关闭它;签名缺失会导致403 Forbidden或SignatureDoesNotMatch错误。
没有凭据则不签名
在 POST 协议路径中,如果客户端没有设置 access key/secret key,请求会以无签名形式发出(lib/aws/request.ex)。对私有资源而言,这等于失败请求,请确保生产环境凭据齐全。
防止密钥泄露:日志与调试的正确打开方式
这是一个很容易忽略但非常实用的设计:AWS.Client在派生Inspect时默认排除了access_key_id、secret_access_key、session_token三个字段(lib/aws/client.ex)。
也就是说,即使你在调试时执行IO.inspect(client)或把 client 结构体打印到日志,密钥也不会出现在输出中。这是 aws-elixir 内置的防泄露机制 ✅
配套建议:
- 避免在错误消息、日志字符串中手工拼接密钥内容;
- 请求体、URL 中的敏感参数同样要注意脱敏,库本身不会替你隐藏业务参数。
传输安全与重试:两条容易忽视的细节
默认走 HTTPS,别降级
客户端默认proto: "https"、端口443(lib/aws/client.ex)。除非明确在做本地调试(region设为"local"会指向localhost,见 lib/aws/request.ex),不要将其改为http——明文传输的凭据极易被截获。
重试与幂等性
开启enable_retries?: true后,库会对 5xx、429 及网络错误做指数退避重试(最多默认 10 次)。对非幂等的写操作(如创建资源),重试可能造成重复调用,请配合业务侧幂等键使用,相关行为可在 test/aws/client_test.exs 中验证。
上线前自检清单 📋
| # | 检查项 | 说明 |
|---|---|---|
| 1 | 密钥未硬编码在代码中 | 优先使用环境变量或配置系统下发 |
| 2 | STS 临时凭据带上了 Session Token | 三元组缺一即认证失败 |
| 3 | 临时凭据有刷新机制 | 过期时间到后能自动续期 |
| 4 | 未误用sign_request?: false | 仅预签名等特殊场景关闭 |
| 5 | 生产环境走 HTTPS 443 | 不降级为明文 HTTP |
| 6 | 日志中确认过密钥不可见 | 依赖Inspect排除机制并抽查日志 |
| 7 | IAM 遵循最小权限 | 定期轮换与审计密钥 |
| 8 | 非幂等请求评估过重试影响 | enable_retries?配合幂等设计 |
总结
aws-elixir 把 AWS 的复杂签名细节封装得足够简单,但安全的责任在调用方:凭据走环境变量或配置系统下发、临时凭据记得带 Session Token 并及时刷新、签名开关只在不需要的场景关闭、日志放心交给 Inspect 的防泄露机制。按照上面的清单逐项核对,你的 aws-elixir 应用就能在密钥管理与签名控制上做到滴水不漏 💪
【免费下载链接】aws-elixirAWS clients for Elixir项目地址: https://gitcode.com/gh_mirrors/aw/aws-elixir
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考