question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Use of KMS keys across nested stacks create circular dependencies

See original GitHub issue

I have a separate nested stack that creates and associates security related resources including IAM resources and KMS CMKs. Let’s refer to this nested stack as SecurityNestedStack.

I have a nested stack which contains lambdas and SQS queues. Let’s refer to this nested stack as LambdaNestedStack.

These queues are using KMS CMKs and using an IAM role from SecurityNestedStack. Everything for the role and cmk has been preconfigured in SecurityNestedStack including policies for SQS IAM access, KMS IAM access, and CMK key policy.

Setting up the SQSEventSource in LambdaNestedStack calls grantConsumeMessages which in turn adds two new IAM policies to the queue’s IAM role. This happens in the wrong stack and causes a circular dependency.

This is helpful for ease of setting up events, roles, and key policies for the queue. It’s problematic in more advanced use cases and larger stacks that must be split up (200 resource limit in stacks).

Reproduction Steps

See above. I can post code if necessary.

Error Log

CloudFormation reports that all nested stacks have circular dependencies. Not completely true but there is a circular dependency across nested stacks.

Environment

  • CLI Version : 1.19.0
  • Framework Version: 1.19.0
  • OS : macOS
  • Language : TypeScript

Other

My workaround right now is to call addEventSourceMapping and pass in batchSize and eventSourceArn myself OR import the role.


This is 🐛 Bug Report

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:5
  • Comments:8 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
nija-atcommented, Jan 16, 2020

Here’s the smallest code needed to reproduce -

import { App, Construct, Stack } from '@aws-cdk/core';
import { NestedStack } from '@aws-cdk/aws-cloudformation';
import { Key } from '@aws-cdk/aws-kms';
import { Code, Function, Runtime } from '@aws-cdk/aws-lambda';

export class MainStack extends Stack {
  constructor(scope: App, id: string) {
    super(scope, id);

    const firstStack = new FirstNestedStack(this, 'FirstNestedStack');
    new SecondNestedStack(this, 'SecondNestedStack', firstStack);
  }
}

class FirstNestedStack extends NestedStack {
  public readonly key: Key;

  constructor(scope: Construct, id: string) {
    super(scope, id);

    this.key = new Key(this, 'Key');
  }
}

class SecondNestedStack extends NestedStack {
  constructor(scope: Construct, id: string, firstStack: FirstNestedStack) {
    super(scope, id);

    const fn = new Function(this, 'function', {
      code: Code.fromInline('foo'),
      runtime: Runtime.NODEJS_10_X,
      handler: 'index.handler'
    });

    firstStack.key.grantDecrypt(fn);
  }
}

const app = new App();
new MainStack(app, 'MainStack');

On further debugging, the issue isn’t with SQSEventSource, it’s got to do with KMS.

Since the key is defined in FirstStack but used in the SecondStack, there’s a dependency created where SecondStack depends on FirstStack Next, the call to KMS key grantDecrypt now seems to create a dependency where the FirstStack depends on the SecondStack.

I suspect that the code somewhere in the grant method doesn’t account for nested stacks.

cc @skinny85 who is the last major change to this area of code.

0reactions
abbottdevcommented, Feb 16, 2021

We’re also hitting this problem - but with a slightly different use case - we’re trying to define our KMS keys in a Stack for our SNS/SQS resources; we then have an ECS Stack which contains other resources. We’re trying to use the QueueProcessingFargateService construct; however this does a similar grant See here: https://github.com/aws/aws-cdk/blob/e8801a0ddb04e75de87ba34f3a58b1adebae5301/packages/%40aws-cdk/aws-ecs-patterns/lib/base/queue-processing-service-base.ts#L312

This happens when trying to use an existing queue as a prop passed in to the ECS task. This causes the same circular dependency as provided in the simple example.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Handling circular dependency errors in AWS CloudFormation
When you get a circular dependency error, the first step is to examine the resources that are outlined and ensure that AWS CloudFormation...
Read more >
CloudFormation Cyclic dependency - Stack Overflow
I am creating a KMS key using a CloudFormation template which is then used to create an IAM role in another template since...
Read more >
Resolving Circular Dependency between multiple AWS ...
Solution: As a solution, we can create the third template and declare the resources from the core.yaml that the resources.yaml is importing or...
Read more >
CloudFormation Nested Stacks Archives
CloudFormation template can be used to set up the resources consistently and repeatedly over and over across multiple regions ...
Read more >
What are some reasons that AWS CloudFormation fails to ...
Circular Dependency : Although the stack couldn't have been created if a circular dependency is in place (self refering, or a pair of...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found