From cafdc6bbf6e71315a0e93a36744b2b8a44a2b509 Mon Sep 17 00:00:00 2001 From: kaizen3031593 Date: Thu, 17 Mar 2022 19:29:04 -0400 Subject: [PATCH 1/7] chnages to add permission --- .../@aws-cdk/aws-lambda/lib/function-base.ts | 17 ++++- .../@aws-cdk/aws-lambda/test/function.test.ts | 72 ++++++++++++++++++- 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index b259476efad9d..832cf5262ac3d 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -1,7 +1,7 @@ import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; -import { ArnFormat, ConstructNode, IResource, Resource, Token } from '@aws-cdk/core'; +import { Annotations, ArnFormat, ConstructNode, IResource, Resource, Token } from '@aws-cdk/core'; import { AliasOptions } from './alias'; import { Architecture } from './architecture'; import { EventInvokeConfig, EventInvokeConfigOptions } from './event-invoke-config'; @@ -273,6 +273,13 @@ export abstract class FunctionBase extends Resource implements IFunction, ec2.IC * @param permission The permission to grant to this Lambda function. @see Permission for details. */ public addPermission(id: string, permission: Permission) { + this.addPermissionHelper(id, permission, false); + } + + /** + * @param qualified Whether or not the function is qualified (i.e. is an alias or a version) + */ + protected addPermissionHelper(id: string, permission: Permission, qualified?: boolean) { if (!this.canCreatePermissions) { // FIXME: @deprecated(v2) - throw an error if calling `addPermission` on a resource that doesn't support it. return; @@ -283,6 +290,10 @@ export abstract class FunctionBase extends Resource implements IFunction, ec2.IC const action = permission.action ?? 'lambda:InvokeFunction'; const scope = permission.scope ?? this; + if (['lambda:InvokeFunction', 'lambda:*'].includes(action) && !qualified) { + Annotations.of(this).addWarning('Lambda has changed their authorization strategy, which may affect resource permissions on unqualified arns. See https://github.com/aws/aws-cdk/issues/19273'); + } + new CfnPermission(scope, id, { action, principal, @@ -537,6 +548,10 @@ export abstract class QualifiedFunctionBase extends FunctionBase { ...options, }); } + + public addPermission(id: string, permission: Permission): void { + super.addPermissionHelper(id, permission, true); + } } /** diff --git a/packages/@aws-cdk/aws-lambda/test/function.test.ts b/packages/@aws-cdk/aws-lambda/test/function.test.ts index 9c01956493d8b..e7310fb32c971 100644 --- a/packages/@aws-cdk/aws-lambda/test/function.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/function.test.ts @@ -1,5 +1,5 @@ import * as path from 'path'; -import { Match, Template } from '@aws-cdk/assertions'; +import { Annotations, Match, Template } from '@aws-cdk/assertions'; import { ProfilingGroup } from '@aws-cdk/aws-codeguruprofiler'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as efs from '@aws-cdk/aws-efs'; @@ -435,6 +435,76 @@ describe('function', () => { // THEN Template.fromStack(stack).resourceCountIs('AWS::Lambda::Permission', 0); }); + + describe('annotations on different IFunctions', () => { + let stack: cdk.Stack; + let fn: lambda.Function; + let warningMessage: string; + beforeEach(() => { + warningMessage = 'Lambda has changed their authorization strategy'; + stack = new cdk.Stack(); + fn = new lambda.Function(stack, 'MyLambda', { + code: lambda.Code.fromAsset(path.join(__dirname, 'my-lambda-handler')), + handler: 'index.handler', + runtime: lambda.Runtime.PYTHON_3_6, + }); + }); + + test('function', () => { + // WHEN + fn.addPermission('MyPermission', { + principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); + + // THEN + Annotations.fromStack(stack).hasWarning('*', Match.stringLikeRegexp(warningMessage)); + }); + + test('version', () => { + // GIVEN + const version = new lambda.Version(stack, 'MyVersion', { + lambda: fn, + }); + + //WHEN + version.addPermission('MyPermission', { + principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); + + // THEN + Annotations.fromStack(stack).hasNoWarning('*', Match.stringLikeRegexp(warningMessage)); + }); + + test('alias', () => { + // GIVEN + const version = new lambda.Version(stack, 'MyVersion', { + lambda: fn, + }); + const alias = new lambda.Alias(stack, 'MyAlias', { + aliasName: 'alias', + version, + }); + + //WHEN + alias.addPermission('MyPermission', { + principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); + + // THEN + Annotations.fromStack(stack).hasNoWarning('*', Match.stringLikeRegexp(warningMessage)); + }); + + test('function without lambda:InvokeFunction', () => { + // WHEN + fn.addPermission('MyPermission', { + action: 'lambda.GetFunction', + principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); + + // THEN + Annotations.fromStack(stack).hasNoWarning('*', Match.stringLikeRegexp(warningMessage)); + }); + }); }); test('Lambda code can be read from a local directory via an asset', () => { From e6b461097a904cc623a505b58bb11f10d9bc5f53 Mon Sep 17 00:00:00 2001 From: kaizen3031593 Date: Fri, 18 Mar 2022 13:07:01 -0400 Subject: [PATCH 2/7] test latest version --- .../@aws-cdk/aws-lambda/test/function.test.ts | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/test/function.test.ts b/packages/@aws-cdk/aws-lambda/test/function.test.ts index e7310fb32c971..2762bbc932b2e 100644 --- a/packages/@aws-cdk/aws-lambda/test/function.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/function.test.ts @@ -457,7 +457,7 @@ describe('function', () => { }); // THEN - Annotations.fromStack(stack).hasWarning('*', Match.stringLikeRegexp(warningMessage)); + Annotations.fromStack(stack).hasWarning('/Default/MyLambda', Match.stringLikeRegexp(warningMessage)); }); test('version', () => { @@ -466,13 +466,13 @@ describe('function', () => { lambda: fn, }); - //WHEN + // WHEN version.addPermission('MyPermission', { principal: new iam.ServicePrincipal('lambda.amazonaws.com'), }); // THEN - Annotations.fromStack(stack).hasNoWarning('*', Match.stringLikeRegexp(warningMessage)); + Annotations.fromStack(stack).hasNoWarning('/Default/MyVersion', Match.stringLikeRegexp(warningMessage)); }); test('alias', () => { @@ -485,13 +485,29 @@ describe('function', () => { version, }); - //WHEN + // WHEN + alias.addPermission('MyPermission', { + principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); + + // THEN + Annotations.fromStack(stack).hasNoWarning('/Default/MyAlias', Match.stringLikeRegexp(warningMessage)); + }); + + test('alias on latest version', () => { + // GIVEN + const alias = new lambda.Alias(stack, 'MyAlias', { + aliasName: 'alias', + version: fn.latestVersion, + }); + + // WHEN alias.addPermission('MyPermission', { principal: new iam.ServicePrincipal('lambda.amazonaws.com'), }); // THEN - Annotations.fromStack(stack).hasNoWarning('*', Match.stringLikeRegexp(warningMessage)); + Annotations.fromStack(stack).hasNoWarning('/Default/MyAlias', Match.stringLikeRegexp(warningMessage)); }); test('function without lambda:InvokeFunction', () => { @@ -502,7 +518,7 @@ describe('function', () => { }); // THEN - Annotations.fromStack(stack).hasNoWarning('*', Match.stringLikeRegexp(warningMessage)); + Annotations.fromStack(stack).hasNoWarning('/Default/MyLambda', Match.stringLikeRegexp(warningMessage)); }); }); }); From 50bbab16137b792f317e00b4fb160eb3803028f1 Mon Sep 17 00:00:00 2001 From: kaizen3031593 Date: Fri, 18 Mar 2022 13:20:54 -0400 Subject: [PATCH 3/7] test latest version --- packages/@aws-cdk/aws-lambda/lib/function-base.ts | 6 +++++- packages/@aws-cdk/aws-lambda/test/function.test.ts | 13 ++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index 832cf5262ac3d..bf63b839243ca 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -291,7 +291,11 @@ export abstract class FunctionBase extends Resource implements IFunction, ec2.IC const scope = permission.scope ?? this; if (['lambda:InvokeFunction', 'lambda:*'].includes(action) && !qualified) { - Annotations.of(this).addWarning('Lambda has changed their authorization strategy, which may affect resource permissions on unqualified arns. See https://github.com/aws/aws-cdk/issues/19273'); + Annotations.of(this).addWarning([ + 'AWS Lambda has changed their authorization strategy, which may cause client invocations of the lambda function to fail with Access Denied errors.', + "If you are using a lambda Version or Alias, make sure to call 'grantInvoke' or 'addPermission' on the Version or Alias, not the underlying Function", + 'See: https://github.com/aws/aws-cdk/issues/19273', + ].join('\n')); } new CfnPermission(scope, id, { diff --git a/packages/@aws-cdk/aws-lambda/test/function.test.ts b/packages/@aws-cdk/aws-lambda/test/function.test.ts index 2762bbc932b2e..f57850758d881 100644 --- a/packages/@aws-cdk/aws-lambda/test/function.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/function.test.ts @@ -441,7 +441,7 @@ describe('function', () => { let fn: lambda.Function; let warningMessage: string; beforeEach(() => { - warningMessage = 'Lambda has changed their authorization strategy'; + warningMessage = 'AWS Lambda has changed their authorization strategy'; stack = new cdk.Stack(); fn = new lambda.Function(stack, 'MyLambda', { code: lambda.Code.fromAsset(path.join(__dirname, 'my-lambda-handler')), @@ -475,6 +475,17 @@ describe('function', () => { Annotations.fromStack(stack).hasNoWarning('/Default/MyVersion', Match.stringLikeRegexp(warningMessage)); }); + test('latest version', () => { + // WHEN + fn.latestVersion.addPermission('MyPermission', { + principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); + + // THEN + // cannot add permissions on latest version, so no warning necessary + Annotations.fromStack(stack).hasNoWarning('/Default/MyLambda/$LATEST', Match.stringLikeRegexp(warningMessage)); + }); + test('alias', () => { // GIVEN const version = new lambda.Version(stack, 'MyVersion', { From 7204adcca3779ec33260e3506ff9c1932cd8a15e Mon Sep 17 00:00:00 2001 From: kaizen3031593 Date: Tue, 22 Mar 2022 11:40:06 -0400 Subject: [PATCH 4/7] use template pattern for overriding base class functions --- .../@aws-cdk/aws-lambda/lib/function-base.ts | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index bf63b839243ca..ce19d10385893 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -12,6 +12,10 @@ import { CfnPermission } from './lambda.generated'; import { Permission } from './permission'; import { addAlias, flatMap } from './util'; +// keep this import separate from other imports to reduce chance for merge conflicts with v2-main +// eslint-disable-next-line no-duplicate-imports, import/order +import { Construct } from '@aws-cdk/core'; + export interface IFunction extends IResource, ec2.IConnectable, iam.IGrantable { /** @@ -268,18 +272,27 @@ export abstract class FunctionBase extends Resource implements IFunction, ec2.IC protected _invocationGrants: Record = {}; /** - * Adds a permission to the Lambda resource policy. - * @param id The id for the permission construct - * @param permission The permission to grant to this Lambda function. @see Permission for details. + * Adds a warning to function permissions that include `lambda:InvokeFunction`. + * This should apply only to permissions on Lambda functions, not versions or aliases. + * This function is overridden as a noOp for QualifiedFunctionBase. */ - public addPermission(id: string, permission: Permission) { - this.addPermissionHelper(id, permission, false); + public addWarningOnInvokeFunctionPermissions(scope: Construct, action: string) { + const affectedPermissions = ['lambda:InvokeFunction', 'lambda:*', 'lambda:Invoke*']; + if (affectedPermissions.includes(action)) { + Annotations.of(scope).addWarning([ + "AWS Lambda has changed their authorization strategy, which may cause client invocations using the 'Qualifier' parameter of the lambda function to fail with Access Denied errors.", + "If you are using a lambda Version or Alias, make sure to call 'grantInvoke' or 'addPermission' on the Version or Alias, not the underlying Function", + 'See: https://github.com/aws/aws-cdk/issues/19273', + ].join('\n')); + } } /** - * @param qualified Whether or not the function is qualified (i.e. is an alias or a version) + * Adds a permission to the Lambda resource policy. + * @param id The id for the permission construct + * @param permission The permission to grant to this Lambda function. @see Permission for details. */ - protected addPermissionHelper(id: string, permission: Permission, qualified?: boolean) { + public addPermission(id: string, permission: Permission) { if (!this.canCreatePermissions) { // FIXME: @deprecated(v2) - throw an error if calling `addPermission` on a resource that doesn't support it. return; @@ -290,13 +303,7 @@ export abstract class FunctionBase extends Resource implements IFunction, ec2.IC const action = permission.action ?? 'lambda:InvokeFunction'; const scope = permission.scope ?? this; - if (['lambda:InvokeFunction', 'lambda:*'].includes(action) && !qualified) { - Annotations.of(this).addWarning([ - 'AWS Lambda has changed their authorization strategy, which may cause client invocations of the lambda function to fail with Access Denied errors.', - "If you are using a lambda Version or Alias, make sure to call 'grantInvoke' or 'addPermission' on the Version or Alias, not the underlying Function", - 'See: https://github.com/aws/aws-cdk/issues/19273', - ].join('\n')); - } + this.addWarningOnInvokeFunctionPermissions(scope, action); new CfnPermission(scope, id, { action, @@ -553,8 +560,9 @@ export abstract class QualifiedFunctionBase extends FunctionBase { }); } - public addPermission(id: string, permission: Permission): void { - super.addPermissionHelper(id, permission, true); + public addWarningOnInvokeFunctionPermissions(_scope: Construct, _action: string): void { + // noOp + return; } } From 1b7f94b029873d194bb956ad06bce37767c9387a Mon Sep 17 00:00:00 2001 From: kaizen3031593 Date: Thu, 24 Mar 2022 19:24:56 -0400 Subject: [PATCH 5/7] only add warning when currentVersion invoked --- .../@aws-cdk/aws-lambda/lib/function-base.ts | 30 ++-- packages/@aws-cdk/aws-lambda/lib/function.ts | 4 + .../@aws-cdk/aws-lambda/test/function.test.ts | 136 +++++++++++++----- 3 files changed, 125 insertions(+), 45 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index ce19d10385893..b1306f2c3cdd9 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -265,6 +265,12 @@ export abstract class FunctionBase extends Resource implements IFunction, ec2.IC private _latestVersion?: LatestVersion; + /** + * Flag to delay adding a warning message until current version is invoked + * @internal + */ + protected _warnIfCurrentVersionCalled: boolean = false; + /** * Mapping of invocation principals to grants. Used to de-dupe `grantInvoke()` calls. * @internal @@ -276,17 +282,25 @@ export abstract class FunctionBase extends Resource implements IFunction, ec2.IC * This should apply only to permissions on Lambda functions, not versions or aliases. * This function is overridden as a noOp for QualifiedFunctionBase. */ - public addWarningOnInvokeFunctionPermissions(scope: Construct, action: string) { + public considerWarningOnInvokeFunctionPermissions(scope: Construct, action: string) { const affectedPermissions = ['lambda:InvokeFunction', 'lambda:*', 'lambda:Invoke*']; if (affectedPermissions.includes(action)) { - Annotations.of(scope).addWarning([ - "AWS Lambda has changed their authorization strategy, which may cause client invocations using the 'Qualifier' parameter of the lambda function to fail with Access Denied errors.", - "If you are using a lambda Version or Alias, make sure to call 'grantInvoke' or 'addPermission' on the Version or Alias, not the underlying Function", - 'See: https://github.com/aws/aws-cdk/issues/19273', - ].join('\n')); + if (scope.node.tryFindChild('CurrentVersion')) { + this.warnInvokeFunctionPermissions(scope); + } else { + this._warnIfCurrentVersionCalled = true; + } } } + protected warnInvokeFunctionPermissions(scope: Construct): void { + Annotations.of(scope).addWarning([ + "AWS Lambda has changed their authorization strategy, which may cause client invocations using the 'Qualifier' parameter of the lambda function to fail with Access Denied errors.", + "If you are using a lambda Version or Alias, make sure to call 'grantInvoke' or 'addPermission' on the Version or Alias, not the underlying Function", + 'See: https://github.com/aws/aws-cdk/issues/19273', + ].join('\n')); + } + /** * Adds a permission to the Lambda resource policy. * @param id The id for the permission construct @@ -303,7 +317,7 @@ export abstract class FunctionBase extends Resource implements IFunction, ec2.IC const action = permission.action ?? 'lambda:InvokeFunction'; const scope = permission.scope ?? this; - this.addWarningOnInvokeFunctionPermissions(scope, action); + this.considerWarningOnInvokeFunctionPermissions(scope, action); new CfnPermission(scope, id, { action, @@ -560,7 +574,7 @@ export abstract class QualifiedFunctionBase extends FunctionBase { }); } - public addWarningOnInvokeFunctionPermissions(_scope: Construct, _action: string): void { + public considerWarningOnInvokeFunctionPermissions(_scope: Construct, _action: string): void { // noOp return; } diff --git a/packages/@aws-cdk/aws-lambda/lib/function.ts b/packages/@aws-cdk/aws-lambda/lib/function.ts index 5bff57e1d43bc..713b0fa69f882 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function.ts @@ -399,6 +399,10 @@ export class Function extends FunctionBase { return this._currentVersion; } + if (this._warnIfCurrentVersionCalled) { + this.warnInvokeFunctionPermissions(this); + }; + this._currentVersion = new Version(this, 'CurrentVersion', { lambda: this, ...this.currentVersionOptions, diff --git a/packages/@aws-cdk/aws-lambda/test/function.test.ts b/packages/@aws-cdk/aws-lambda/test/function.test.ts index f57850758d881..5935a54c9a35d 100644 --- a/packages/@aws-cdk/aws-lambda/test/function.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/function.test.ts @@ -450,20 +450,80 @@ describe('function', () => { }); }); - test('function', () => { - // WHEN - fn.addPermission('MyPermission', { - principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + describe('permissions on functions', () => { + test('without lambda:InvokeFunction', () => { + // WHEN + fn.addPermission('MyPermission', { + action: 'lambda.GetFunction', + principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); + + // Simulate a workflow where a user has created a currentVersion with the intent to invoke it later. + fn.currentVersion; + + // THEN + Annotations.fromStack(stack).hasNoWarning('/Default/MyLambda', Match.stringLikeRegexp(warningMessage)); }); - // THEN - Annotations.fromStack(stack).hasWarning('/Default/MyLambda', Match.stringLikeRegexp(warningMessage)); + describe('with lambda:InvokeFunction', () => { + test('without invoking currentVersion', () => { + // WHEN + fn.addPermission('MyPermission', { + principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); + + // THEN + Annotations.fromStack(stack).hasNoWarning('/Default/MyLambda', Match.stringLikeRegexp(warningMessage)); + }); + + test('with currentVersion invoked first', () => { + // GIVEN + // Simulate a workflow where a user has created a currentVersion with the intent to invoke it later. + fn.currentVersion; + + // WHEN + fn.addPermission('MyPermission', { + principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); + + // THEN + Annotations.fromStack(stack).hasWarning('/Default/MyLambda', Match.stringLikeRegexp(warningMessage)); + }); + + test('with currentVersion invoked after permissions created', () => { + // WHEN + fn.addPermission('MyPermission', { + principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); + + // Simulate a workflow where a user has created a currentVersion after adding permissions to the function. + fn.currentVersion; + + // THEN + Annotations.fromStack(stack).hasWarning('/Default/MyLambda', Match.stringLikeRegexp(warningMessage)); + }); + + test('multiple currentVersion calls does not result in multiple warnings', () => { + // WHEN + fn.currentVersion; + + fn.addPermission('MyPermission', { + principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); + + fn.currentVersion; + + // THEN + const warns = Annotations.fromStack(stack).findWarning('/Default/MyLambda', Match.stringLikeRegexp(warningMessage)); + expect(warns).toHaveLength(1); + }); + }); }); - test('version', () => { + test('permission on versions', () => { // GIVEN const version = new lambda.Version(stack, 'MyVersion', { - lambda: fn, + lambda: fn.currentVersion, }); // WHEN @@ -475,7 +535,7 @@ describe('function', () => { Annotations.fromStack(stack).hasNoWarning('/Default/MyVersion', Match.stringLikeRegexp(warningMessage)); }); - test('latest version', () => { + test('permission on latest version', () => { // WHEN fn.latestVersion.addPermission('MyPermission', { principal: new iam.ServicePrincipal('lambda.amazonaws.com'), @@ -486,39 +546,41 @@ describe('function', () => { Annotations.fromStack(stack).hasNoWarning('/Default/MyLambda/$LATEST', Match.stringLikeRegexp(warningMessage)); }); - test('alias', () => { - // GIVEN - const version = new lambda.Version(stack, 'MyVersion', { - lambda: fn, - }); - const alias = new lambda.Alias(stack, 'MyAlias', { - aliasName: 'alias', - version, - }); - - // WHEN - alias.addPermission('MyPermission', { - principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + describe('permission on alias', () => { + test('of current version', () => { + // GIVEN + const version = new lambda.Version(stack, 'MyVersion', { + lambda: fn.currentVersion, + }); + const alias = new lambda.Alias(stack, 'MyAlias', { + aliasName: 'alias', + version, + }); + + // WHEN + alias.addPermission('MyPermission', { + principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); + + // THEN + Annotations.fromStack(stack).hasNoWarning('/Default/MyAlias', Match.stringLikeRegexp(warningMessage)); }); - // THEN - Annotations.fromStack(stack).hasNoWarning('/Default/MyAlias', Match.stringLikeRegexp(warningMessage)); - }); + test('of latest version', () => { + // GIVEN + const alias = new lambda.Alias(stack, 'MyAlias', { + aliasName: 'alias', + version: fn.latestVersion, + }); - test('alias on latest version', () => { - // GIVEN - const alias = new lambda.Alias(stack, 'MyAlias', { - aliasName: 'alias', - version: fn.latestVersion, - }); + // WHEN + alias.addPermission('MyPermission', { + principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); - // WHEN - alias.addPermission('MyPermission', { - principal: new iam.ServicePrincipal('lambda.amazonaws.com'), + // THEN + Annotations.fromStack(stack).hasNoWarning('/Default/MyAlias', Match.stringLikeRegexp(warningMessage)); }); - - // THEN - Annotations.fromStack(stack).hasNoWarning('/Default/MyAlias', Match.stringLikeRegexp(warningMessage)); }); test('function without lambda:InvokeFunction', () => { From 3c250f39b162901454eae186604638aef9e628ea Mon Sep 17 00:00:00 2001 From: kaizen3031593 Date: Thu, 24 Mar 2022 19:28:18 -0400 Subject: [PATCH 6/7] update documentation --- packages/@aws-cdk/aws-lambda/lib/function-base.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index b1306f2c3cdd9..438ceb95e7f4d 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -266,7 +266,7 @@ export abstract class FunctionBase extends Resource implements IFunction, ec2.IC private _latestVersion?: LatestVersion; /** - * Flag to delay adding a warning message until current version is invoked + * Flag to delay adding a warning message until current version is invoked. * @internal */ protected _warnIfCurrentVersionCalled: boolean = false; @@ -278,8 +278,11 @@ export abstract class FunctionBase extends Resource implements IFunction, ec2.IC protected _invocationGrants: Record = {}; /** - * Adds a warning to function permissions that include `lambda:InvokeFunction`. - * This should apply only to permissions on Lambda functions, not versions or aliases. + * A warning will be added to functions under the following conditions: + * - permissions that include `lambda:InvokeFunction` are added to the unqualified function. + * - function.currentVersion is invoked before or after the permission is created. + * + * This applies only to permissions on Lambda functions, not versions or aliases. * This function is overridden as a noOp for QualifiedFunctionBase. */ public considerWarningOnInvokeFunctionPermissions(scope: Construct, action: string) { From 3b03c849702aab60ab012cc1fb5322135b0c6898 Mon Sep 17 00:00:00 2001 From: kaizen3031593 Date: Thu, 24 Mar 2022 19:29:18 -0400 Subject: [PATCH 7/7] remove duplicate test --- packages/@aws-cdk/aws-lambda/test/function.test.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/test/function.test.ts b/packages/@aws-cdk/aws-lambda/test/function.test.ts index 5935a54c9a35d..2bc2ea04bbd16 100644 --- a/packages/@aws-cdk/aws-lambda/test/function.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/function.test.ts @@ -582,17 +582,6 @@ describe('function', () => { Annotations.fromStack(stack).hasNoWarning('/Default/MyAlias', Match.stringLikeRegexp(warningMessage)); }); }); - - test('function without lambda:InvokeFunction', () => { - // WHEN - fn.addPermission('MyPermission', { - action: 'lambda.GetFunction', - principal: new iam.ServicePrincipal('lambda.amazonaws.com'), - }); - - // THEN - Annotations.fromStack(stack).hasNoWarning('/Default/MyLambda', Match.stringLikeRegexp(warningMessage)); - }); }); });