Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws_s3/aws_lambda/aws_iam: Cyclic reference when bucket and policy in stack A are referenced by role/lambda in stack B #26539

Open
fushi opened this issue Jul 27, 2023 · 2 comments
Labels
@aws-cdk/aws-iam Related to AWS Identity and Access Management bug This issue is a bug. effort/medium Medium work item – several days of effort p2

Comments

@fushi
Copy link

fushi commented Jul 27, 2023

Describe the bug

Stack A

  • S3 Bucket
  • IAM Policy

Stack B

  • Lambda (which references S3 bucket in environment variables)
  • Role (that adds the policy from Stack A)

This results in a cyclic dependency error: Error: 'BucketStack' depends on 'LambdaStack' (BucketStack -> LambdaStack/IAM - Role (Lambda Execution)/Resource.Ref). Adding this dependency (LambdaStack -> BucketStack/S3 - Bucket/Resource.Ref) would create a cyclic reference

Expected Behavior

The app should synth properly.

Current Behavior

Error: 'BucketStack' depends on 'LambdaStack' (BucketStack -> LambdaStack/IAM - Role (Lambda Execution)/Resource.Ref). Adding this dependency (LambdaStack -> BucketStack/S3 - Bucket/Resource.Ref) would create a cyclic reference

Reproduction Steps

#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import {
  aws_iam as iam,
  aws_lambda as lambda,
  aws_s3 as s3
} from 'aws-cdk-lib'
import { Construct } from 'constructs';

const env = { account: '123456789012', region: 'us-east-1' }
class StorageStack extends cdk.Stack {
  bucket: s3.Bucket;
  bucketPolicy: iam.Policy;

  constructor(scope: Construct, id: string, props: cdk.StackProps) {
    super(scope, id, props);

    this.bucket = new s3.Bucket(this, 'S3 - Bucket', {});
  
    const listAllBucketsPolicyStatement = new iam.PolicyStatement({
      actions: ['s3:ListAllMyBuckets'],
      resources: ['*']
    });
  
    this.bucketPolicy = new iam.Policy(this, 'IAM - Policy (S3 Bucket Access)', {
      statements: [ listAllBucketsPolicyStatement ]
    });
  }
}

class LambdaStack extends cdk.Stack {
  constructor(scope: Construct, id: string, stackProps: cdk.StackProps, bucketName: string, policy: iam.Policy) {
    super(scope, id, stackProps);

    const lambdaExecutionrole = new iam.Role(this, 'IAM - Role (Lambda Execution)', {
      assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
    })
  
    lambdaExecutionrole.attachInlinePolicy(policy); // Comment out this line
  
    new lambda.Function(this, 'Lambda - Function', {
      runtime: lambda.Runtime.NODEJS_18_X,
      handler: 'index.handler',
      code: lambda.Code.fromAsset('./Lib/Lambda'),
      role: lambdaExecutionrole,
      environment: { bucketName } // Comment out this line
    });
  }
}

const app = new cdk.App();

const storageStack = new StorageStack(app, 'BucketStack', { env });

new LambdaStack(app, 'LambdaStack', { env }, storageStack.bucket.bucketName, storageStack.bucketPolicy)

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.87.0 (build 9fca790)

Framework Version

No response

Node.js Version

v18.16.1

OS

macOS 13.2.1 (22D68)

Language

Typescript

Language Version

typescript@5.1.6

Other information

Error: 'BucketStack' depends on 'LambdaStack' (BucketStack -> LambdaStack/IAM - Role (Lambda Execution)/Resource.Ref). Adding this dependency (LambdaStack -> BucketStack/S3 - Bucket/Resource.Ref) would create a cyclic reference.
    at LambdaStack._addAssemblyDependency (/Users/john.towler/source/personal/cdk-bug/node_modules/aws-cdk-lib/core/lib/stack.js:1:10330)
    at operateOnDependency (/Users/john.towler/source/personal/cdk-bug/node_modules/aws-cdk-lib/core/lib/deps.js:1:1649)
    at addDependency (/Users/john.towler/source/personal/cdk-bug/node_modules/aws-cdk-lib/core/lib/deps.js:1:321)
    at LambdaStack.addDependency (/Users/john.towler/source/personal/cdk-bug/node_modules/aws-cdk-lib/core/lib/stack.js:1:7442)
    at resolveValue (/Users/john.towler/source/personal/cdk-bug/node_modules/aws-cdk-lib/core/lib/private/refs.js:1:3259)
    at resolveReferences (/Users/john.towler/source/personal/cdk-bug/node_modules/aws-cdk-lib/core/lib/private/refs.js:1:870)
    at prepareApp (/Users/john.towler/source/personal/cdk-bug/node_modules/aws-cdk-lib/core/lib/private/prepare-app.js:1:586)
    at synthesize (/Users/john.towler/source/personal/cdk-bug/node_modules/aws-cdk-lib/core/lib/private/synthesis.js:1:922)
    at App.synth (/Users/john.towler/source/personal/cdk-bug/node_modules/aws-cdk-lib/core/lib/stage.js:1:2052)
    at process.<anonymous> (/Users/john.towler/source/personal/cdk-bug/node_modules/aws-cdk-lib/core/lib/app.js:1:1448)
@fushi fushi added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Jul 27, 2023
@github-actions github-actions bot added the @aws-cdk/aws-iam Related to AWS Identity and Access Management label Jul 27, 2023
@pahud
Copy link
Contributor

pahud commented Jul 31, 2023

I think this is not a CDK bug but a cyclic dependency you need to break.

You can consider to put your policy and policy statement in the LambdaStack.

Is there any reason you have to place in the StorageStack?

@pahud pahud added p2 effort/medium Medium work item – several days of effort and removed needs-triage This issue or PR still needs to be triaged. labels Jul 31, 2023
@fushi
Copy link
Author

fushi commented Jul 31, 2023

Creating a policy that only refers to the S3 bucket, in the same stack as the S3 Bucket, should not create a cyclic dependency when using that policy in other stacks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-iam Related to AWS Identity and Access Management bug This issue is a bug. effort/medium Medium work item – several days of effort p2
Projects
None yet
Development

No branches or pull requests

2 participants