aws / aws/aws-cdk

(aws-key): Secret with KMS that calls secret.grantRead() in another stack causes cyclic reference

Open
#14,213 5 comments 25 reactions 0 assignees View on GitHub
@aws-cdk/aws-kms bug effort/medium p1
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

Calling secret.grantRead() in another stack on a secret encrypted with KMS would result in cyclic reference error.

### Reproduction Steps

```
#!/usr/bin/env node
import cdk = require("monocdk");
import iam = require("monocdk/aws-iam");
import s3 = require("monocdk/aws-s3");
import secret = require("monocdk/aws-secretsmanager");
import key = require("monocdk/aws-kms");

class S3HostStack extends cdk.Stack {
public readonly bucket: s3.Bucket;
public readonly key: key.Key;
public readonly secret: secret.Secret;

constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
this.key = new key.Key(this, 'test-secret-key', {
alias: "test-secret-key",
removalPolicy: cdk.RemovalPolicy.DESTROY
});
this.secret = new secret.Secret(this, 'test_secret', {
secretName: 'test_secret',
encryptionKey: this.key,
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
}
}

class S3ConsumerStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, s3HostStack: S3HostStack) {
super(scope, id);

const accessRole = new iam.Role(this, "Access", {
assumedBy: new iam.ServicePrincipal("ecs-tasks.amazonaws.com"),
});

this.addDependency(s3HostStack); //required as seen at https://github.com/aws/aws-cdk/issues/3732#issuecomment-571708554

// s3HostStack.secret.grantRead(accessRole); //this creates cyclic reference
//workaround since secret.grantRead() have issues
accessRole.addToPolicy(new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["secretsmanager:*", "kms:*"],
resources: [s3HostStack.secret.secretArn, s3HostStack.key.keyArn],
}));
}
}

const app = new cdk.App();
const host = new S3HostStack(app, 'S3HostStack');
new S3ConsumerStack(app, 'S3ConsumerStack', host);
```
### What did you expect to happen?

able to grant read permission to secrets encrypted with KMS successfully

### What actually happened?

```
Error: 'S3HostStack' depends on 'S3ConsumerStack' (S3HostStack -> S3ConsumerStack/Access/Resource.Arn). Adding this dependency (S3ConsumerStack -> S3HostStack/test_secret/Resource.Ref) would create a cyclic reference.
```

### Environment

- **CDK CLI Version :** 1.96.0 (build 39f3df8)
- **Framework Version:** 1.96.0 (build 39f3df8)
- **Node.js Version:** v14.12.0
- **OS :** macOS Catalina 10.15.7
- **Language (Version):** TypeScript (3.6.4)

### Other

Similar issue - https://github.com/aws/aws-cdk/issues/3732

As a workaround, i am calling `addToPolicy()` to grant permission on the secret and key using their ARN. Any better workaround suggestions are welcome.
---

This is :bug: Bug Report

Contributor guide

Open the contributing guide

Research direction

No repository file or test is named. Start by running the minimal two-stack reproduction with CDK 1.96.0, then trace secret.grantRead() and its cross-stack dependency behavior; compare it with the addToPolicy() workaround. Done means granting read access to the KMS-encrypted secret without creating a cyclic stack dependency.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, typescript
Domain
cloud, infrastructure
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.