-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Comments
Few more things.... 😅
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 🙇 |
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:
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). |
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. 👍
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. |
@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 ➜ 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 🙇 |
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 |
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 // 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 // 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 Behavior C. Tags are still not being properly applied to L@E IAM resources using Here is an example of "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 "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. 🙇 |
Here's the API docs: https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_core.Aspects.html#static-ofscope.
The oddity here is actually the side-effect of an implementation detail. The role attached to the custom resource is not actually an aws-cdk/packages/@aws-cdk/core/lib/custom-resource-provider/custom-resource-provider.ts Lines 177 to 189 in b1996cd
|
Gotcha... Thanks for clarifying that 👍
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 |
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?
Yes, the /// !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(); |
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
Hmmm.... I've just tried your code example and I'm still not seeing ...
"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"
}
},
...
Are you still planning on creating "parent stack name as seed" feature/fix? I've been using the new |
@njlynch Did you get a chance to try that integration test again? If you did... can you please post synth results here? Thanks! |
@robertd - The synth results won't help, as they won't show the tags. As I said:
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.
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: |
Hmmm... I must be doing something wrong.
I can definitely do that. |
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*
|
❓ General Issue
The Question
Hello, @njlynch.
I have a few questions regarding the new Lambda@Edge functionality.
*-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 runcdk doctor
.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.
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):
Thanks! ✋
Environment
Other information
The text was updated successfully, but these errors were encountered: