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-cloudfront): few questions regarding Lambda@Edge function/stack #12323

Closed
robertd opened this issue Jan 4, 2021 · 14 comments · Fixed by #12702
Closed

(aws-cloudfront): few questions regarding Lambda@Edge function/stack #12323

robertd opened this issue Jan 4, 2021 · 14 comments · Fixed by #12702
Assignees
Labels
@aws-cdk/aws-cloudfront Related to Amazon CloudFront guidance Question that needs advice or information.

Comments

@robertd
Copy link
Contributor

robertd commented Jan 4, 2021

❓ General Issue

The Question

Hello, @njlynch.

I have a few questions regarding the new Lambda@Edge functionality.

  1. When I try to create a L@E function, my stack is named *-us-west-2. Is this expected behavior? My understanding is that L@E stack will be deployed to us-east-1. My default region is us-west-2 when I run cdk doctor.
Successfully synthesized to /Users/robertd/code/cf/static-cloudfront-distributions/cdk.out
Supply a stack id (edge-lambda-stack-us-west-2, demo-appsStaticCFStack) to display its template.
  1. If I create multiple L@E functions for the particular CF distro should I expect to see multiple CFN stacks for L@E functions? I see that everything is lumped under one stack right now.

  2. I'm building a factory-style CDK application that will create multiple CloudFront distros with accompanying L@E functions (per distro) based on the configuration file. If these edge functions are all being lumped under the same stack, how do I keep them siloed (per CF distro) if their stacks are all named the same (i.e.: edge-lambda-stack-us-west-2).

Example (it doesn't paint the whole picture but this is what I'm trying to do):

    const bucket = props.distroConfig.existingBucket ? s3.Bucket.fromBucketName(this, "existing-bucket", props.distroConfig.existingBucket) 
      : createBucket(this, props.distroConfig.stackName, this.account, logBucket);

    const edgeLambdas = props.distroConfig.lambdaEdgeConfig ? props.distroConfig.lambdaEdgeConfig.map((config, index) => {
      const edgeLambda = new cloudfront.experimental.EdgeFunction(this, `${props.distroConfig.stackName}-lambda-edge-${index}`, {
        runtime: config.runtime,
        handler: 'index.handler',
        code: lambda.Code.fromAsset(path.join(__dirname, 'lambda')),
        description: `Lambda Edge function for ${props.distroConfig.stackName}`,
      });
      
      return {
        functionVersion: edgeLambda.currentVersion,
        eventType: cloudfront.LambdaEdgeEventType.ORIGIN_REQUEST,
      }
    }) : undefined;

    const distro = new cloudfront.Distribution(this, "distro", {
      defaultBehavior: {
        origin: new origins.S3Origin(bucket),
        allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
        // cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED, // default: CACHING_OPTIMIZED 24hr
        cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,
        viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
        edgeLambdas,
      },
      certificate,
      comment: `${props.distroConfig.domainNames[0]} cloudfront distribution.`,
      logBucket: logBucket,
      logFilePrefix: `AWSLogs/${this.account}/cloudfront/${props.distroConfig.team}/static/${props.distroConfig.stackName}`,
      logIncludesCookies: true,
      defaultRootObject: "index.html",
      priceClass: cloudfront.PriceClass.PRICE_CLASS_100, // USA & EU
      domainNames: props.distroConfig.domainNames,
    });

Thanks! ✋

Environment

  • CDK CLI Version: 1.82.0
  • Node.js Version: 15.5.0
  • OS: macOS Mojave
  • Language (Version): TypeScript (4.1.3)

Other information

@robertd robertd added guidance Question that needs advice or information. needs-triage This issue or PR still needs to be triaged. labels Jan 4, 2021
@github-actions github-actions bot added the @aws-cdk/aws-cloudfront Related to Amazon CloudFront label Jan 4, 2021
@robertd robertd changed the title (cloudfront): question regarding Lambda@Edge function/stack (aws-cloudfront): question regarding Lambda@Edge function/stack Jan 4, 2021
@robertd
Copy link
Contributor Author

robertd commented Jan 4, 2021

Few more things.... 😅

  1. I just noticed that tags are not being applied to any IAM roles created for L@E resources. Rest of the resources in the stack are having proper tags applied.

  2. Lastly, this one is a major show-stopper for us. We're unable to apply permissions boundary to any of the L@E IAM Roles through a workaround outlined in Applying permissions boundary to aws-cdk globally #3242. Long story short, I've encountered similar error as outlined in Applying permissions boundary to aws-cdk globally #3242 (comment) and I've applied the fix (compared to initial implementation I've been using Applying permissions boundary to aws-cdk globally #3242 (comment)). However, not all the IAM resources created by cloudfront.experimental.EdgeFunction are getting PermissionBoundary applied (i.e.: ones created in edge-lambda-{region} stack). It's really an interesting bug/behavior observed by @ottokruse in Applying permissions boundary to aws-cdk globally #3242 (comment).

Code snippet:

  const stack = new StaticCloudfrontStack(app, `${tags.team}-${distroConfig.stackName}StaticCFStack`, {
    distroConfig,
    env,
    description: `CloudFront distro stack for ${distroConfig.stackName}`,
  });
  
  cdk.Aspects.of(stack).add(new PermissionsBoundary(`arn:aws:iam::${env.account}:policy/csr-Developer-Permissions-Boundary`));
  cdk.Aspects.of(stack).add(new cdk.Tag("poc", tags.poc));
  cdk.Aspects.of(stack).add(new cdk.Tag("team", tags.team));
  cdk.Aspects.of(stack).add(new cdk.Tag("program", tags.program));
  cdk.Aspects.of(stack).add(new cdk.Tag("function", `${tags.team}-${distroConfig.stackName}-${tags.function}`));

I'd really appreciate your help on any of this. Thanks 🙇

@njlynch
Copy link
Contributor

njlynch commented Jan 4, 2021

Thanks for the feedback and questions! Questions 4 and 5 require a slightly deeper look; I expect we'll end up with separate bug/feature requests for each, but let me do a quick probe into them first.

On the subjects of the L@E stack name:

  1. When I try to create a L@E function, my stack is named *-us-west-2. Is this expected behavior? My understanding is that L@E stack will be deployed to us-east-1.
  2. If I create multiple L@E functions for the particular CF distro should I expect to see multiple CFN stacks for L@E functions? I see that everything is lumped under one stack right now.
  3. [...] If these edge functions are all being lumped under the same stack, how do I keep them siloed (per CF distro) if their stacks are all named the same (i.e.: edge-lambda-stack-us-west-2).

Yes, the L@E stack will be deployed to us-east-1. The stack is named *-us-west-2, to indicate its origin. Your "primary"/CloudFront stack is in us-west-2, so the us-east-1 stack gets that name to tell you what region spawned the stack. This maybe wasn't the clearest naming on my part. :/

The current implementation was targeted at "simple" cases with a single CloudFront distro (per region), which is the most common app type I've seen; as such, I picked a naming convention I thought was simplest for the "base case". However, in your case, this clearly won't work terribly well. One solution might be a bug fix to have the stack named better (perhaps using the "parent" stack name as a seed); I'm open to suggestions here on what naming might make sense. The other approach for this case is #12136, which will allow you to explicitly specify the stack name for each L@E stack (this will go out with the next release).

@robertd
Copy link
Contributor Author

robertd commented Jan 4, 2021

Thanks for the feedback and questions! Questions 4 and 5 require a slightly deeper look; I expect we'll end up with separate bug/feature requests for each, but let me do a quick probe into them first.

Sounds good. I'll provide you with the working example for my use case. We're operating under permissions boundary and any creation of IAM resources needs to be "blessed" by our permissions boundary. I'm not 100% sure why workaround in #3242 is not working. Thanks again for looking into this and let me know if I need to create separate issues. 👍

Yes, the L@E stack will be deployed to us-east-1. The stack is named *-us-west-2, to indicate its origin. Your "primary"/CloudFront stack is in us-west-2, so the us-east-1 stack gets that name to tell you what region spawned the stack. This maybe wasn't the clearest naming on my part. :/

The current implementation was targeted at "simple" cases with a single CloudFront distro (per region), which is the most common app type I've seen; as such, I picked a naming convention I thought was simplest for the "base case". However, in your case, this clearly won't work terribly well. One solution might be a bug fix to have the stack named better (perhaps using the "parent" stack name as a seed); I'm open to suggestions here on what naming might make sense. The other approach for this case is #12136, which will allow you to explicitly specify the stack name for each L@E stack (this will go out with the next release).

In our case, we have multiple teams using the same AWS account and we're trying to isolate their resources through IaC (co-existing with other AWS account "roomates" is a story on its own 😄 ). Therefore, each team would have their own CF distro and L@Es that would affect their particular use cases.

I like the idea of using parent stack name as a seed. We're not really big into custom naming resources as we use tags (4th question) to identify which resource belongs to which team.

@robertd
Copy link
Contributor Author

robertd commented Jan 4, 2021

@njlynch Here is the working example for questions 4 and 5. https://github.com/robertd/cf-distro-cdk

Synthesizing this project will create three different stacks, and should apply Permissions Boundary to all three. However, it's only being applied to two stacks. Multiple CF distros with multiple L@E are configurable in lib/config.ts. Let me know if this makes any sense to you 😄

➜  cf-distro-cdk git:(master) ✗ cdk synth
------PERMISSION BOUNDARY APPLIED to acmefooCFStackCustomCrossRegionStringParameterReaderCustomResourceProviderRole9FD624B1-------
------PERMISSION BOUNDARY APPLIED to acmebazCFStackCustomCrossRegionStringParameterReaderCustomResourceProviderRole35E3509E-------
Successfully synthesized to /Users/robertd/code/cf-distro-cdk/cdk.out
Supply a stack id (edge-lambda-stack-us-west-2, acme-bazCFStack, acme-fooCFStack) to display its template.

I've tried to put comments throughout the app... Let me know if you have any questions.

Thanks 🙇

@njlynch
Copy link
Contributor

njlynch commented Jan 5, 2021

Ah, I suspect I know the cause behind 4 & 5. It looks like you're applying aspects to the CloudFront stack, but that won't apply aspects to other stacks in the app, including the L@E stack. Try changing your cdk.Aspects.of(stack) calls to be cdk.Aspects.of(app).

@njlynch njlynch added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. and removed needs-triage This issue or PR still needs to be triaged. labels Jan 6, 2021
@robertd
Copy link
Contributor Author

robertd commented Jan 6, 2021

Interesting @njlynch, good find. How did you figure to use app instead? I'm looking at the official docs (https://docs.aws.amazon.com/cdk/latest/guide/aspects.html) and I'm not seeing anywhere that aspects can be applied to app (just stacks or constructs).

Also, I'm still somewhat puzzled by this as I'm seeing few interesting behaviors. I'll try to explain it as best as I can.

Behavior A. Using cdk.Aspects.of(app) and overriding permissions boundary by following Aspects docs.

// located in bin/cf-distro-cdk.ts
cdk.Aspects.of(app).add(new PermissionsBoundary(`arn:aws:iam::${env.account}:policy/csr-Developer-Permissions-Boundary`));

// located in overrides/permissions-boundary.ts
  public visit(node: cdk.IConstruct): void {
    if (node instanceof iam.Role) {
      console.log(`------PERMISSION BOUNDARY APPLIED to ${node.node.uniqueId}-------`);
      const roleResource = node.node.findChild('Resource') as iam.CfnRole;
      roleResource.addPropertyOverride('PermissionsBoundary', this.permissionsBoundaryArn);
    }
  }

Results in permissions boundary override being applied only to L@E IAM resources in edge-lambda-stack-us-west-2:

➜  cf-distro-cdk git:(master) ✗ cdk synth
------PERMISSION BOUNDARY APPLIED to edgelambdastackuswest2foolambdaedge0ServiceRoleBBB87E8F-------
------PERMISSION BOUNDARY APPLIED to edgelambdastackuswest2foolambdaedge1ServiceRole5315447D-------
------PERMISSION BOUNDARY APPLIED to edgelambdastackuswest2bazlambdaedge0ServiceRoleE574DC9F-------
Successfully synthesized to /Users/robertd/code/cf/cf-distro-cdk/cdk.out
Supply a stack id (edge-lambda-stack-us-west-2, acme-bazCFStack, acme-fooCFStack) to display its template.

Behavior B. Using cdk.Aspects.of(app) and overriding permissions boundary by using @ottokruse 's workaround in #3242 (comment).

// located in bin/cf-distro-cdk.ts
cdk.Aspects.of(app).add(new PermissionsBoundary(`arn:aws:iam::${env.account}:policy/csr-Developer-Permissions-Boundary`));

// located in overrides/permissions-boundary.ts
  public visit(node: cdk.IConstruct): void {
    if (cdk.CfnResource.isCfnResource(node) && node.cfnResourceType === 'AWS::IAM::Role') {
      console.log(`------PERMISSION BOUNDARY APPLIED to ${node.node.uniqueId}-------`);
      node.addPropertyOverride('PermissionsBoundary', this.permissionsBoundaryArn);
    }
  }

Results in permission boundary override being applied to all IAM roles (both in individual CF stacks and in L@E stack):

➜  cf-distro-cdk git:(master) ✗ cdk synth
------PERMISSION BOUNDARY APPLIED to acmefooCFStackCustomCrossRegionStringParameterReaderCustomResourceProviderRole9FD624B1-------
------PERMISSION BOUNDARY APPLIED to edgelambdastackuswest2foolambdaedge0ServiceRole445AB86B-------
------PERMISSION BOUNDARY APPLIED to edgelambdastackuswest2foolambdaedge1ServiceRoleE5043A73-------
------PERMISSION BOUNDARY APPLIED to edgelambdastackuswest2bazlambdaedge0ServiceRole86B1F6C6-------
------PERMISSION BOUNDARY APPLIED to acmebazCFStackCustomCrossRegionStringParameterReaderCustomResourceProviderRole35E3509E-------
Successfully synthesized to /Users/robertd/code/cf/cf-distro-cdk/cdk.out
Supply a stack id (edge-lambda-stack-us-west-2, acme-bazCFStack, acme-fooCFStack) to display its template.

I can't really wrap my head on why I'm seeing this behavior. Why is node instanceof iam.Role not picking up all IAM Roles compared to cdk.CfnResource.isCfnResource(node) && node.cfnResourceType === 'AWS::IAM::Role', even though node instanceof iam.Role is, according to docs, the official way to apply Aspects? I wonder if this is a bug or something.

Behavior C. Tags are still not being properly applied to L@E IAM resources using cdk.Aspects.of(app).

Here is an example of acme-bazCFStack stack in cdk.out that is showing permissions boundary being applied to its L@E IAM resources, but not tags.

    "CustomCrossRegionStringParameterReaderCustomResourceProviderRole71CD6825": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Action": "sts:AssumeRole",
              "Effect": "Allow",
              "Principal": {
                "Service": "lambda.amazonaws.com"
              }
            }
          ]
        },
        "ManagedPolicyArns": [
          {
            "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
          }
        ],
        "Policies": [
          {
            "PolicyName": "Inline",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {
                          "Ref": "AWS::Partition"
                        },
                        ":ssm:us-east-1:123456789012:parameter/EdgeFunctionArn*"
                      ]
                    ]
                  },
                  "Action": [
                    "ssm:GetParameter"
                  ]
                }
              ]
            }
          }
        ],
        "PermissionsBoundary": "arn:aws:iam::123456789012:policy/csr-Developer-Permissions-Boundary"
      },
      "Metadata": {
        "aws:cdk:path": "acme-bazCFStack/Custom::CrossRegionStringParameterReaderCustomResourceProvider/Role"
      }
    },

On the other hand, on L@E IAM resources in edge-lambda-stack-us-west-2 tags are being applied properly.

"bazlambdaedge0ServiceRoleCD811D17": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Statement": [
            {
              "Action": "sts:AssumeRole",
              "Effect": "Allow",
              "Principal": {
                "Service": "lambda.amazonaws.com"
              }
            },
            {
              "Action": "sts:AssumeRole",
              "Effect": "Allow",
              "Principal": {
                "Service": "edgelambda.amazonaws.com"
              }
            }
          ],
          "Version": "2012-10-17"
        },
        "ManagedPolicyArns": [
          {
            "Fn::Join": [
              "",
              [
                "arn:",
                {
                  "Ref": "AWS::Partition"
                },
                ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
              ]
            ]
          }
        ],
        "PermissionsBoundary": "arn:aws:iam::123456789012:policy/csr-Developer-Permissions-Boundary",
        "Tags": [
          {
            "Key": "poc",
            "Value": "acme@acme.com"
          },
          {
            "Key": "program",
            "Value": "acme-enterprise"
          },
          {
            "Key": "team",
            "Value": "acme"
          }
        ]
      },

Thank you for troubleshooting this with me. Much appreciated. 🙇

@njlynch
Copy link
Contributor

njlynch commented Jan 6, 2021

How did you figure to use app instead? I'm looking at the official docs (https://docs.aws.amazon.com/cdk/latest/guide/aspects.html)

Here's the API docs: https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_core.Aspects.html#static-ofscope. Aspects.of takes an IConstruct, which means any construct can be passed in, which includes Apps, Stages, Stacks, etc.

I can't really wrap my head on why I'm seeing this behavior. Why is node instanceof iam.Role not picking up all IAM Roles compared to cdk.CfnResource.isCfnResource(node) && node.cfnResourceType === 'AWS::IAM::Role', even though node instanceof iam.Role is, according to docs, the official way to apply Aspects? I wonder if this is a bug or something.

The oddity here is actually the side-effect of an implementation detail. The role attached to the custom resource is not actually an iam.Role. This is because the IAM module depends on the core module, so the core module can't depend on (and use) the IAM module. So instead, a raw CfnResource is used to create the role:

const role = new CfnResource(this, 'Role', {
type: 'AWS::IAM::Role',
properties: {
AssumeRolePolicyDocument: {
Version: '2012-10-17',
Statement: [{ Action: 'sts:AssumeRole', Effect: 'Allow', Principal: { Service: 'lambda.amazonaws.com' } }],
},
ManagedPolicyArns: [
{ 'Fn::Sub': 'arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' },
],
Policies: policies,
},
});

@robertd
Copy link
Contributor Author

robertd commented Jan 6, 2021

Here's the API docs: https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_core.Aspects.html#static-ofscope. Aspects.of takes an IConstruct, which means any construct can be passed in, which includes Apps, Stages, Stacks, etc.

Gotcha... Thanks for clarifying that 👍

The oddity here is actually the side-effect of an implementation detail. The role attached to the custom resource is not actually an iam.Role. This is because the IAM module depends on the core module, so the core module can't depend on (and use) the IAM module. So instead, a raw CfnResource is used to create the role

Hmm sounds like a catch 22. This should definitely be documented in Aspects docs. Especially that from time to time, depending on how the resource has been created, workaround in #3242 (comment) should be used.

I assume same thing applies to Tags not being propagated to those resources created using CfnResource construct?

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. label Jan 7, 2021
@njlynch
Copy link
Contributor

njlynch commented Jan 8, 2021

This should definitely be documented in Aspects docs.

Do you have any suggestions for how the docs could be clarified? I feel as though this specific instance -- a role created in the "core" module using a "raw" CfnResource is a bit too specific to be called out in the docs. Any suggestions for how you'd want to see this phrased?

I assume same thing applies to Tags

Yes, the CfnResource used to create the custom resource role does not natively support the tags property, so it's not being tagged in the template. However, if the stack is tagged, all supported resources will have the tags propagate when you deploy. You won't see the tag in the template, but if you deploy the role, you should see the tags there. I've deployed the following, which is a slightly modified version of one of the edge function integration tests, and verified all of the roles are tagged appropriately.

/// !cdk-integ *
import * as lambda from '@aws-cdk/aws-lambda';
import * as cdk from '@aws-cdk/core';
import * as constructs from 'constructs';
import * as cloudfront from '../lib';
import { TestOrigin } from './test-origin';

const app = new cdk.App();
const stack = new cdk.Stack(app, 'integ-distribution-lambda-cross-region', { env: { region: 'eu-west-1' } });

class PermissionsBoundary implements cdk.IAspect {
  private readonly permissionsBoundaryArn: string;

  constructor(permissionBoundaryArn: string) {
    this.permissionsBoundaryArn = permissionBoundaryArn;
  }

  public visit(node: constructs.IConstruct): void {
    if (cdk.CfnResource.isCfnResource(node) && node.cfnResourceType === 'AWS::IAM::Role') {
      node.addPropertyOverride('PermissionsBoundary', this.permissionsBoundaryArn);
    }
  }
}

const lambdaFunction = new cloudfront.experimental.EdgeFunction(stack, 'Lambda', {
  code: lambda.Code.fromInline('foo'),
  handler: 'index.handler',
  runtime: lambda.Runtime.NODEJS_10_X,
});

new cloudfront.Distribution(stack, 'Dist', {
  defaultBehavior: {
    origin: new TestOrigin('www.example.com'),
    cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED,
    edgeLambdas: [{
      functionVersion: lambdaFunction.currentVersion,
      eventType: cloudfront.LambdaEdgeEventType.ORIGIN_REQUEST,
    }],
  },
});

cdk.Aspects.of(app).add(new PermissionsBoundary('arn:aws:iam::aws:policy/AdministratorAccess'));
cdk.Tags.of(app).add('testkey1', 'testvalue1');

app.synth();

@robertd
Copy link
Contributor Author

robertd commented Jan 12, 2021

@njlynch

Do you have any suggestions for how the docs could be clarified? I feel as though this specific instance -- a role created in the "core" module using a "raw" CfnResource is a bit too specific to be called out in the docs. Any suggestions for how you'd want to see this phrased?

Something along these lines...

"Note: If you use Aspects with created using raw CfnResources you will not be able to use you will have to use different approach to target these resources in your app/stack."... and perhaps we can provide some basic example.

I can definitely come up with a nice PR for aws-cloudfront docs if you want me to.

Yes, the CfnResource used to create the custom resource role does not natively support the tags property, so it's not being tagged in the template. However, if the stack is tagged, all supported resources will have the tags propagate when you deploy. You won't see the tag in the template, but if you deploy the role, you should see the tags there. I've deployed the following, which is a slightly modified version of one of the edge function integration tests, and verified all of the roles are tagged appropriately.

Hmmm.... I've just tried your code example and I'm still not seeing Tags being applied to the cross-region resources in the main stack. Btw... I had to change things a bit and use existing bucket as cloudfront origin. Am I missing something?

...
    "CustomCrossRegionStringParameterReaderCustomResourceProviderRole71CD6825": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Action": "sts:AssumeRole",
              "Effect": "Allow",
              "Principal": {
                "Service": "lambda.amazonaws.com"
              }
            }
          ]
        },
        "ManagedPolicyArns": [
          {
            "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
          }
        ],
        "Policies": [
          {
            "PolicyName": "Inline",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {
                          "Ref": "AWS::Partition"
                        },
                        ":ssm:us-east-1:",
                        {
                          "Ref": "AWS::AccountId"
                        },
                        ":parameter/EdgeFunctionArn*"
                      ]
                    ]
                  },
                  "Action": [
                    "ssm:GetParameter"
                  ]
                }
              ]
            }
          }
        ],
        "PermissionsBoundary": "arn:aws:iam::aws:policy/AdministratorAccess"
      },
      "Metadata": {
        "aws:cdk:path": "integ-distribution-lambda-cross-region/Custom::CrossRegionStringParameterReaderCustomResourceProvider/Role"
      }
    },
    "CustomCrossRegionStringParameterReaderCustomResourceProviderHandler65B5F33A": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {
            "Ref": "AssetParameters45b7ed524ce2b119dd4f2b8642ae8bfaf0df45bc6bd705072ae4ee6d1a999241S3BucketF1BC72A7"
          },
          "S3Key": {
            "Fn::Join": [
              "",
              [
                {
                  "Fn::Select": [
                    0,
                    {
                      "Fn::Split": [
                        "||",
                        {
                          "Ref": "AssetParameters45b7ed524ce2b119dd4f2b8642ae8bfaf0df45bc6bd705072ae4ee6d1a999241S3VersionKey7AD83AC7"
                        }
                      ]
                    }
                  ]
                },
                {
                  "Fn::Select": [
                    1,
                    {
                      "Fn::Split": [
                        "||",
                        {
                          "Ref": "AssetParameters45b7ed524ce2b119dd4f2b8642ae8bfaf0df45bc6bd705072ae4ee6d1a999241S3VersionKey7AD83AC7"
                        }
                      ]
                    }
                  ]
                }
              ]
            ]
          }
        },
        "Timeout": 900,
        "MemorySize": 128,
        "Handler": "__entrypoint__.handler",
        "Role": {
          "Fn::GetAtt": [
            "CustomCrossRegionStringParameterReaderCustomResourceProviderRole71CD6825",
            "Arn"
          ]
        },
        "Runtime": "nodejs12.x"
      },
      "DependsOn": [
        "CustomCrossRegionStringParameterReaderCustomResourceProviderRole71CD6825"
      ],
      "Metadata": {
        "aws:cdk:path": "integ-distribution-lambda-cross-region/Custom::CrossRegionStringParameterReaderCustomResourceProvider/Handler"
      }
    },
...

From #12323 (comment): The current implementation was targeted at "simple" cases with a single CloudFront distro (per region), which is the most common app type I've seen; as such, I picked a naming convention I thought was simplest for the "base case". However, in your case, this clearly won't work terribly well. One solution might be a bug fix to have the stack named better (perhaps using the "parent" stack name as a seed); I'm open to suggestions here on what naming might make sense. The other approach for this case is #12136, which will allow you to explicitly specify the stack name for each L@E stack (this will go out with the next release).

Are you still planning on creating "parent stack name as seed" feature/fix? I've been using the new stackId parameter... it does the job, but I was wondering if parent stack seed is still on the table.

@robertd robertd changed the title (aws-cloudfront): question regarding Lambda@Edge function/stack (aws-cloudfront): few questions regarding Lambda@Edge function/stack Jan 14, 2021
@robertd
Copy link
Contributor Author

robertd commented Jan 14, 2021

@njlynch Did you get a chance to try that integration test again? If you did... can you please post synth results here? Thanks!

@njlynch
Copy link
Contributor

njlynch commented Jan 14, 2021

@robertd - The synth results won't help, as they won't show the tags. As I said:

... if the stack is tagged, all supported resources will have the tags propagate when you deploy.

You have to actually deploy this to see the tags in action. And yes, I've just re-deployed and verified both IAM roles created were tagged correctly.

Are you still planning on creating "parent stack name as seed" feature/fix?

Yes, it's still a follow-up action for this issue. Would you be interested in taking a crack at the PR? It should be relatively straight-forward: just need to use the current node id (or node's stack's id) to replace the region here:
https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/aws-cloudfront/lib/experimental/edge-function.ts#L217

@robertd
Copy link
Contributor Author

robertd commented Jan 14, 2021

@njlynch

You have to actually deploy this to see the tags in action. And yes, I've just re-deployed and verified both IAM roles created were tagged correctly.

Hmmm... I must be doing something wrong.

image

Yes, it's still a follow-up action for this issue. Would you be interested in taking a crack at the PR? It should be relatively straight-forward: just need to use the current node id (or node's stack's id) to replace the region here:
https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/aws-cloudfront/lib/experimental/edge-function.ts#L217

I can definitely do that.

@mergify mergify bot closed this as completed in #12702 Jan 27, 2021
mergify bot pushed a commit that referenced this issue Jan 27, 2021
Closes #12323 

BREAKING CHANGE: experimental EdgeFunction stack names have changed from 'edge-lambda-stack-${region}' to 'edge-lambda-stack-${stackid}' to support multiple independent CloudFront distributions with EdgeFunctions.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@github-actions
Copy link

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-cloudfront Related to Amazon CloudFront guidance Question that needs advice or information.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants