The Problem #
Our Lambda functions retrieve secrets using a middleware that lists all secrets, then fetches them one by one with GetSecretValue. This worked fine initially, but as we added more secrets and deployed more Lambda functions, the API calls accumulated quickly. We started hitting AWS Secrets Manager's rate limits with 429 errors.
The Solution: BatchGetSecretValue #
The fix seemed straightforward: use BatchGetSecretValue to retrieve multiple secrets in a single API call, reducing the total number of requests.
The implementation was indeed simple, but I hit an unexpected blocker with IAM permissions.
The Permission Gotcha #
Here's what I learned: BatchGetSecretValue is classified as a list action in AWS IAM, not a read action.
List actions in AWS require wildcard (*) for the resource in IAM policies. You cannot use key-level or prefix-level resource specifications with BatchGetSecretValue.
This won't work:
1{
2 "Effect": "Allow",
3 "Action": "secretsmanager:BatchGetSecretValue",
4 "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:myapp/*"
5}
You must use:
1{
2 "Effect": "Allow",
3 "Action": "secretsmanager:BatchGetSecretValue",
4 "Resource": "*"
5}
After the batch get, individual GetSecretValue calls can still use granular resource-level permissions.
The Fix #
Update your IAM policy to allow BatchGetSecretValue with wildcard resource, while keeping granular permissions for other operations:
1{
2 "Version": "2012-10-17",
3 "Statement": [
4 {
5 "Effect": "Allow",
6 "Action": "secretsmanager:BatchGetSecretValue",
7 "Resource": "*"
8 },
9 {
10 "Effect": "Allow",
11 "Action": "secretsmanager:GetSecretValue",
12 "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:myapp/*"
13 }
14 ]
15}
Result #
By switching to BatchGetSecretValue, we significantly reduced our API call volume and eliminated the 429 rate limit errors. The permission requirement was unexpected but makes sense given how list operations work in AWS IAM.