Secrets Manager / SSM / IRSA:秘密管理做對了嗎?
你的 DB 密碼放在哪裡?環境變數?.env 檔?git repo 裡?如果答案是後兩個,你的系統已經有資安破口了。
先講結論
Secrets Manager 適合存高價值秘密(DB 密碼、API key),支援自動 rotation。SSM Parameter Store 適合存一般設定(feature flag、endpoint URL),免費額度大。IRSA(IAM Roles for Service Accounts)讓 EKS 的 Pod 用 IAM Role 而不是 Access Key 存取 AWS 服務。三個搭起來,你的秘密管理就安全了。
Secrets Manager:高價值秘密的家
什麼該放 Secrets Manager
- DB 密碼
- 第三方 API key(Stripe、SendGrid)
- OAuth client secret
- TLS 私鑰
# 建立 Secret
aws secretsmanager create-secret \
--name prod/database/postgres \
--description "Production PostgreSQL credentials" \
--secret-string '{"username":"dbadmin","password":"SuperSecretPass123!","host":"prod-postgres.xxx.ap-northeast-1.rds.amazonaws.com","port":5432,"dbname":"appdb"}'
# 讀取 Secret
aws secretsmanager get-secret-value --secret-id prod/database/postgres \
--query SecretString --output text | jq .
# 更新 Secret
aws secretsmanager update-secret --secret-id prod/database/postgres \
--secret-string '{"username":"dbadmin","password":"NewPassword456!"}'自動 Rotation
Secrets Manager 的殺手功能是自動 rotation——定期幫你換密碼,不用人工介入:
# 設定 RDS 密碼自動 rotation(每 30 天)
aws secretsmanager rotate-secret \
--secret-id prod/database/postgres \
--rotation-lambda-arn arn:aws:lambda:ap-northeast-1:123456789012:function:SecretsManagerRDSPostgreSQLRotation \
--rotation-rules AutomaticallyAfterDays=30AWS 提供了 RDS rotation 的 Lambda template,幾乎不用自己寫 code。
在 ECS 裡使用 Secrets Manager
{
"containerDefinitions": [{
"name": "app",
"image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/web-app:1.0.0",
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:prod/database/postgres:password::"
},
{
"name": "STRIPE_KEY",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:prod/stripe-api-key"
}
]
}]
}ECS 在啟動 Task 的時候會自動從 Secrets Manager 拉 secret 注入環境變數。你的 code 只要讀 process.env.DB_PASSWORD 就好。
SSM Parameter Store:一般設定的家
Secrets Manager vs SSM Parameter Store
| Secrets Manager | SSM Parameter Store | |
|---|---|---|
| 費用 | $0.40/secret/月 + API call 費 | 免費(Standard tier) |
| 自動 Rotation | 內建 | 要自己寫 |
| 版本管理 | 有 | 有 |
| 加密 | KMS 加密 | 可選 KMS |
| 跨帳號存取 | 支援 | 支援 |
| 適合 | 密碼、API key | Feature flag、config、endpoint URL |
# 存一般設定(String)
aws ssm put-parameter \
--name /prod/app/feature-flags/dark-mode \
--type String \
--value "enabled"
# 存機敏設定(SecureString,用 KMS 加密)
aws ssm put-parameter \
--name /prod/app/smtp-password \
--type SecureString \
--value "SmtpPass123!"
# 讀取
aws ssm get-parameter --name /prod/app/feature-flags/dark-mode --query Parameter.Value --output text
# 讀取加密的(要加 --with-decryption)
aws ssm get-parameter --name /prod/app/smtp-password --with-decryption --query Parameter.Value --output text
# 批次讀取某個路徑下的所有參數
aws ssm get-parameters-by-path --path /prod/app/ --recursive --with-decryption在 ECS 裡使用 SSM
{
"containerDefinitions": [{
"name": "app",
"secrets": [
{
"name": "FEATURE_DARK_MODE",
"valueFrom": "arn:aws:ssm:ap-northeast-1:123456789012:parameter/prod/app/feature-flags/dark-mode"
}
]
}]
}IRSA:讓 EKS Pod 用 IAM Role
傳統做法:把 AWS Access Key 放在環境變數裡。問題是 key 會洩漏、不好 rotate、所有 Pod 共用同一個 key。
IRSA(IAM Roles for Service Accounts)讓每個 K8s ServiceAccount 綁定一個 IAM Role,Pod 透過 ServiceAccount 自動拿到臨時 credentials——不需要 Access Key。
設定 IRSA
# 1. 啟用 OIDC Provider(EKS cluster 建立時自動有)
eksctl utils associate-iam-oidc-provider \
--cluster prod-cluster --approve
# 2. 建立 IAM Role + K8s ServiceAccount
eksctl create iamserviceaccount \
--cluster prod-cluster \
--namespace default \
--name s3-reader \
--attach-policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
--approve
# 3. 在 Pod spec 裡使用這個 ServiceAccount# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
serviceAccountName: s3-reader # 綁定 IRSA
containers:
- name: app
image: my-app:1.0.0
# 不需要 AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY
# SDK 會自動透過 IRSA 拿到臨時 credentialsIRSA 的好處
- Pod 層級權限:不同 Pod 有不同 IAM Role,不是整台 Node 共用
- 臨時 credentials:每 12 小時自動 rotate,不需要管理 Access Key
- 最小權限:S3 讀取的 Pod 就只能讀 S3,不能碰 RDS
- 審計:CloudTrail 能看到哪個 Pod 做了什麼 AWS API call
最佳實踐
秘密分層
/prod/
/database/
postgres → Secrets Manager(自動 rotation)
redis → Secrets Manager
/api-keys/
stripe → Secrets Manager
sendgrid → Secrets Manager
/app/
feature-flags/ → SSM Parameter Store(免費)
endpoints/ → SSM Parameter Store
smtp-password → SSM SecureString
不要做的事
- 不要把 secret 放在 git repo 裡(即使是 private repo)
- 不要把 secret 硬寫在 code 裡
- 不要用同一個 Access Key 給所有服務
- 不要忘記設 secret 的 rotation
自架 vs AWS
| 面向 | 自架 | AWS |
|---|---|---|
| 秘密管理 | HashiCorp Vault | Secrets Manager |
| 設定管理 | .env + Consul | SSM Parameter Store |
| 自動 Rotation | Vault + cronjob | 內建 Lambda rotation |
| Pod 權限 | K8s ServiceAccount + RBAC | IRSA(IAM + ServiceAccount) |
| 審計 | Vault audit log | CloudTrail |
| 加密 | Vault Transit / Sealed Secrets | KMS |
如果你讀過 Secrets & Config 和 Secrets & Certificate Management,Secrets Manager 就是 Vault 的 AWS 版——功能沒有 Vault 全面,但零維護。
K8s 映射
| AWS 秘密管理 | K8s 對應 |
|---|---|
| Secrets Manager | K8s Secret(建議用 External Secrets Operator 同步) |
| SSM Parameter Store | ConfigMap / K8s Secret |
| IRSA | ServiceAccount + RBAC |
| KMS | Sealed Secrets(加密 Secret) |
| Secret rotation | External Secrets Operator 自動同步 |
在 EKS 上最佳實踐:用 External Secrets Operator 把 Secrets Manager 的 secret 自動同步到 K8s Secret,Pod 直接讀 K8s Secret——這樣既有 AWS 的安全性,又保持 K8s 原生的使用方式。詳見 K8s 配置管理。
系列導覽
| 上一篇 | 下一篇 |
|---|---|
| Container Insights | EventBridge |
你的系統有多安全,取決於你最弱的那個秘密怎麼管理。