Skip to content

Commit

Permalink
fix(lambda): Validate Lambda "functionName" parameter (#17970)
Browse files Browse the repository at this point in the history
Closes #13264

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
Dzhuneyt committed Feb 17, 2022
1 parent 7e6c70e commit a416a2d
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
11 changes: 10 additions & 1 deletion packages/@aws-cdk/aws-lambda/lib/function.ts
Expand Up @@ -6,7 +6,7 @@ import * as kms from '@aws-cdk/aws-kms';
import * as logs from '@aws-cdk/aws-logs';
import * as sns from '@aws-cdk/aws-sns';
import * as sqs from '@aws-cdk/aws-sqs';
import { Annotations, ArnFormat, CfnResource, Duration, Fn, Lazy, Names, Stack } from '@aws-cdk/core';
import { Annotations, ArnFormat, CfnResource, Duration, Fn, Lazy, Names, Stack, Token } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { Architecture } from './architecture';
import { Code, CodeConfig } from './code';
Expand Down Expand Up @@ -627,6 +627,15 @@ export class Function extends FunctionBase {
physicalName: props.functionName,
});

if (props.functionName && !Token.isUnresolved(props.functionName)) {
if (props.functionName.length > 64) {
throw new Error(`Function name can not be longer than 64 characters but has ${props.functionName.length} characters.`);
}
if (!/^[a-zA-Z0-9-_]+$/.test(props.functionName)) {
throw new Error(`Function name ${props.functionName} can contain only letters, numbers, hyphens, or underscores with no spaces.`);
}
}

const managedPolicies = new Array<iam.IManagedPolicy>();

// the arn is in the form of - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Expand Down
40 changes: 40 additions & 0 deletions packages/@aws-cdk/aws-lambda/test/function.test.ts
Expand Up @@ -12,6 +12,7 @@ import * as sns from '@aws-cdk/aws-sns';
import * as sqs from '@aws-cdk/aws-sqs';
import { testDeprecated } from '@aws-cdk/cdk-build-tools';
import * as cdk from '@aws-cdk/core';
import { Intrinsic, Token } from '@aws-cdk/core';
import * as constructs from 'constructs';
import * as _ from 'lodash';
import * as lambda from '../lib';
Expand Down Expand Up @@ -2404,6 +2405,45 @@ describe('function', () => {
});
expect(fn.architecture?.name).toEqual('arm64');
});

test('Error when function name is longer than 64 chars', () => {
const stack = new cdk.Stack();
expect(() => new lambda.Function(stack, 'MyFunction', {
code: lambda.Code.fromInline('foo'),
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
functionName: 'a'.repeat(65),
})).toThrow(/Function name can not be longer than 64 characters/);
});

test('Error when function name contains invalid characters', () => {
const stack = new cdk.Stack();
[' ', '\n', '\r', '[', ']', '<', '>', '$'].forEach(invalidChar => {
expect(() => {
new lambda.Function(stack, `foo${invalidChar}`, {
code: new lambda.InlineCode('foo'),
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_14_X,
functionName: `foo${invalidChar}`,
});
}).toThrow(/can contain only letters, numbers, hyphens, or underscores with no spaces./);
});
});

test('No error when function name is Tokenized and Unresolved', () => {
const stack = new cdk.Stack();
expect(() => {
const realFunctionName = 'a'.repeat(141);
const tokenizedFunctionName = Token.asString(new Intrinsic(realFunctionName));

new lambda.Function(stack, 'foo', {
code: new lambda.InlineCode('foo'),
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_14_X,
functionName: tokenizedFunctionName,
});
}).not.toThrow();
});
});

function newTestLambda(scope: constructs.Construct) {
Expand Down

0 comments on commit a416a2d

Please sign in to comment.