aws / aws/aws-cdk

AWS Secrets Manager: Not authorized to perform BatchGetSecretValue

Open
#31,566 19 comments 0 reactions 1 assignee Claimed by @pahud View on GitHub
@aws-cdk/aws-lambda @aws-cdk/aws-secretsmanager bug p2
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.