AWS Secrets Manager: Not authorized to perform BatchGetSecretValue
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 74
Description
### Describe the bug
I'm attempting to retrieve secrets using [BatchGetSecretValue](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_BatchGetSecretValue.html).
In my CDK app, I've created a [`NodejsFunction`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs.NodejsFunction.html) Lambda.
Then, I retrieve the secrets as follows, and grant read access to the lambda:
```ts
const mySecret = Secret.fromSecretNameV2(
this,
`${mySecretName}Secret`,
mySecretName
)
mySecret.grantRead(myLambda)
```
This worked fine when I had only one secret and was retrieving it using [GetSecretValueCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-secrets-manager/Class/GetSecretValueCommand/).
However, now I've switched to using [BatchGetSecretValueCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/secrets-manager/command/BatchGetSecretValueCommand/), and it seems I no longer have access to the secrets.
I get this error when attempting the batch retrieval:
```ts
{
"name": "AccessDeniedException",
"$fault": "client",
"$metadata": {
"httpStatusCode": 400,
"requestId": "123456",
"attempts": 1,
"totalRetryDelay": 0
},
"__type": "AccessDeniedException",
"message": "User: arn:aws:sts::123456 is not authorized to perform: secretsmanager:BatchGetSecretValue because no identity-based policy allows the secretsmanager:BatchGetSecretValue action"
}
```
I've only shown one secret in the examples above, but in the actual app I'm repeating this process for the few secrets I have and granting read access for each one.
I found [this](https://docs.aws.amazon.com/secretsmanager/latest/userguide/auth-and-access_examples.html#auth-and-access_examples_batch) documentation that mentions adding the following as a permission:
```ts
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:BatchGetSecretValue",
"secretsmanager:ListSecrets"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": [
"SecretARN1",
"SecretARN2",
"SecretARN3"
]
}
]
}
```
If I look at my lambda in the AWS Console, I can see that it does only have these action permissions for each secret:
`Allow: secretsmanager:DescribeSecret`
`Allow: secretsmanager:GetSecretValue`
And clearly `secretsmanager:BatchGetSecretValue` is not part of this.
So I attempted the following:
```ts
myLambda.addToRolePolicy(new PolicyStatement(
{
effect: Effect.ALLOW,
actions:
[
'secretsmanager:BatchGetSecretValue',
'secretsmanager:GetSecretValue',
],
resources:
[
mySecret1.secretFullArn || mySecret1.secretArn,
mySecret2.secretFullArn || mySecret2.secretArn,
mySecret3.secretFullArn || mySecret3.secretArn,
mySecret4.secretFullArn || mySecret4.secretArn
]
}))
```
And still got the same error. When I look in the AWS Console, the ARNs now don't include the final six characters. When I used `grantRead`, the ARNs ended in `-??????`. Now they don't.
I even attempted to add it back in like this:
```ts
`${mySecret1.secretArn}-??????`
```
And it made no difference.
---
Overall, I can't figure out how to retrieve secrets in a batch.
More specifically, what possible reason could there be for `grantRead` to provide access to read and retrieve a secret individually but not as part of a batch? If I use `grantReadWriteData` to grant the same lambda access to a DynamoDB table, I can see clearly in the Console that it includes batch-related actions. So why is there an exception for secrets? If there is permission to read it individually, what is the risk of reading it as part of a batch? This should be the default behavior, just like DynamoDB, or at least there should be an opt-in.
I've read in the docs that using the `grant*` functions is best practice over providing specific policies like the one I attempted above. There should be an option to use a `grant*` function for this. Having to specify a policy like the one attempted above is never a better option over something like `grant*`.
### Regression Issue
- [ ] Select this option if this issue appears to be a regression.
### Last Known Working CDK Version
_No response_
### Expected Behavior
I expected `grantRead` would cover batch retrieval as well as non-batch retrieval.
### Current Behavior
It does not cover that action and my lambda does not have permission to retrieves secrets by batch, although it has been granted read-related permissions to each secret in question.
### Reproduction Steps
Please see above.
### Possible Solution
`grantRead` should cover batch retrieval.
### Additional Information/Context
_No response_
### CDK CLI Version
2.159.1 (build c66f4e3)
### Framework Version
_No response_
### Node.js Version
v20.16.0
### OS
MacOS
### Language
TypeScript
### Language Version
5.6.2
### Other information
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.