Skip to content

Commit c7e7eaf

Browse files
edvaldoszyzirkelc
andauthored
feat: support Arguments for Lambda when query language is JSONata (#645)
* fix: correctly resolve lambda function name from Arguments or Parameters * test: use itParam to test both JSONPath and JSONata scenarios * fix: lambda permissions for jsonata --------- Co-authored-by: zirkelc <[email protected]>
1 parent 6e9847b commit c7e7eaf

File tree

2 files changed

+123
-36
lines changed

2 files changed

+123
-36
lines changed

lib/deploy/stepFunctions/compileIamRole.js

+10-8
Original file line numberDiff line numberDiff line change
@@ -360,9 +360,18 @@ function getRedshiftDataPermissions(action, state) {
360360
}
361361

362362
function getLambdaPermissions(state) {
363+
if (isJsonPathParameter(state, 'FunctionName') || isJsonataArgument(state, 'FunctionName')) {
364+
const allowedFunctions = getParameterOrArgument(state, 'AllowedFunctions');
365+
return [{
366+
action: 'lambda:InvokeFunction',
367+
resource: allowedFunctions || '*',
368+
}];
369+
}
370+
363371
// function name can be name-only, name-only with alias, full arn or partial arn
364372
// https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_RequestParameters
365-
const functionName = state.Parameters.FunctionName;
373+
const functionName = getParameterOrArgument(state, 'FunctionName');
374+
366375
if (_.isString(functionName)) {
367376
const segments = functionName.split(':');
368377

@@ -429,13 +438,6 @@ function getLambdaPermissions(state) {
429438
}];
430439
}
431440

432-
if (state.Parameters['FunctionName.$']) {
433-
return [{
434-
action: 'lambda:InvokeFunction',
435-
resource: state.Parameters.AllowedFunctions ? state.Parameters.AllowedFunctions : '*',
436-
}];
437-
}
438-
439441
// hope for the best...
440442
return [{
441443
action: 'lambda:InvokeFunction',

lib/deploy/stepFunctions/compileIamRole.test.js

+113-28
Original file line numberDiff line numberDiff line change
@@ -3587,7 +3587,49 @@ describe('#compileIamRole', () => {
35873587
]);
35883588
});
35893589

3590-
it('should support variable FunctionName', () => {
3590+
itParam('should resolve FunctionName: ${value}', ['JSONPath', 'JSONata'], (queryLanguage) => {
3591+
serverless.service.stepFunctions = {
3592+
stateMachines: {
3593+
myStateMachine1: {
3594+
id: 'StateMachine1',
3595+
definition: {
3596+
StartAt: 'A',
3597+
States: {
3598+
A: {
3599+
Type: 'Task',
3600+
Resource: 'arn:aws:states:::lambda:invoke',
3601+
...getParamsOrArgs(
3602+
queryLanguage,
3603+
{
3604+
FunctionName: 'arn:aws:lambda:us-west-2:1234567890:function:foo',
3605+
'Payload.$': '$.Payload',
3606+
},
3607+
{
3608+
FunctionName: 'arn:aws:lambda:us-west-2:1234567890:function:foo',
3609+
Payload: '{% $states.input.Payload %}',
3610+
},
3611+
),
3612+
End: true,
3613+
},
3614+
},
3615+
},
3616+
},
3617+
},
3618+
};
3619+
3620+
serverlessStepFunctions.compileIamRole();
3621+
const statements = serverlessStepFunctions.serverless.service
3622+
.provider.compiledCloudFormationTemplate.Resources.StateMachine1Role
3623+
.Properties.Policies[0].PolicyDocument.Statement;
3624+
const lambdaPermissions = statements.filter(s => _.isEqual(s.Action, ['lambda:InvokeFunction']));
3625+
expect(lambdaPermissions).to.have.lengthOf(1);
3626+
expect(lambdaPermissions[0].Resource).to.deep.equal([
3627+
'arn:aws:lambda:us-west-2:1234567890:function:foo',
3628+
'arn:aws:lambda:us-west-2:1234567890:function:foo:*',
3629+
]);
3630+
});
3631+
3632+
itParam('should support variable FunctionName: ${value}', ['JSONPath', 'JSONata'], (queryLanguage) => {
35913633
serverless.service.stepFunctions = {
35923634
stateMachines: {
35933635
myStateMachine1: {
@@ -3598,26 +3640,47 @@ describe('#compileIamRole', () => {
35983640
A: {
35993641
Type: 'Task',
36003642
Resource: 'arn:aws:states:::lambda:invoke.waitForTaskToken',
3601-
Parameters: {
3602-
'FunctionName.$': '$.functionName',
3603-
Payload: {
3604-
'model.$': '$.new_model',
3605-
'token.$': '$$.Task.Token',
3643+
...getParamsOrArgs(
3644+
queryLanguage,
3645+
{
3646+
'FunctionName.$': '$.functionName',
3647+
Payload: {
3648+
'model.$': '$.new_model',
3649+
'token.$': '$$.Task.Token',
3650+
},
36063651
},
3607-
},
3652+
{
3653+
FunctionName: '{% $states.input.functionName %}',
3654+
Payload: {
3655+
model: '{% $states.input.new_model %}',
3656+
token: '{% $states.context.Task.Token %}',
3657+
},
3658+
},
3659+
),
36083660
Next: 'B',
36093661
},
36103662
B: {
36113663
Type: 'Task',
36123664
Resource: 'arn:aws:states:::lambda:invoke.waitForTaskToken',
3613-
Parameters: {
3614-
'FunctionName.$': '$.functionName',
3615-
AllowedFunctions: '*limited*',
3616-
Payload: {
3617-
'model.$': '$.new_model',
3618-
'token.$': '$$.Task.Token',
3665+
...getParamsOrArgs(
3666+
queryLanguage,
3667+
{
3668+
'FunctionName.$': '$.functionName',
3669+
AllowedFunctions: '*limited*',
3670+
Payload: {
3671+
'model.$': '$.new_model',
3672+
'token.$': '$$.Task.Token',
3673+
},
36193674
},
3620-
},
3675+
{
3676+
FunctionName: '{% $states.input.functionName %}',
3677+
AllowedFunctions: '*limited*',
3678+
Payload: {
3679+
model: '{% $states.input.new_model %}',
3680+
token: '{% $states.context.Task.Token %}',
3681+
},
3682+
},
3683+
),
36213684
End: true,
36223685
},
36233686
},
@@ -3643,27 +3706,49 @@ describe('#compileIamRole', () => {
36433706
A: {
36443707
Type: 'Task',
36453708
Resource: 'arn:aws:states:::lambda:invoke.waitForTaskToken',
3646-
Parameters: {
3647-
'FunctionName.$': '$.functionName',
3648-
AllowedFunctions: 'arn:aws:lambda:us-west-2:1234567890:function:foo',
3649-
Payload: {
3650-
'model.$': '$.new_model',
3651-
'token.$': '$$.Task.Token',
3709+
...getParamsOrArgs(
3710+
queryLanguage,
3711+
{
3712+
'FunctionName.$': '$.functionName',
3713+
AllowedFunctions: 'arn:aws:lambda:us-west-2:1234567890:function:foo',
3714+
Payload: {
3715+
'model.$': '$.new_model',
3716+
'token.$': '$$.Task.Token',
3717+
},
36523718
},
3653-
},
3719+
{
3720+
FunctionName: '{% $states.input.functionName %}',
3721+
AllowedFunctions: 'arn:aws:lambda:us-west-2:1234567890:function:foo',
3722+
Payload: {
3723+
model: '{% $states.input.new_model %}',
3724+
token: '{% $states.context.Task.Token %}',
3725+
},
3726+
},
3727+
),
36543728
Next: 'B',
36553729
},
36563730
B: {
36573731
Type: 'Task',
36583732
Resource: 'arn:aws:states:::lambda:invoke.waitForTaskToken',
3659-
Parameters: {
3660-
'FunctionName.$': '$.functionName',
3661-
AllowedFunctions: '*limited*',
3662-
Payload: {
3663-
'model.$': '$.new_model',
3664-
'token.$': '$$.Task.Token',
3733+
...getParamsOrArgs(
3734+
queryLanguage,
3735+
{
3736+
'FunctionName.$': '$.functionName',
3737+
AllowedFunctions: '*limited*',
3738+
Payload: {
3739+
'model.$': '$.new_model',
3740+
'token.$': '$$.Task.Token',
3741+
},
36653742
},
3666-
},
3743+
{
3744+
FunctionName: '{% $states.input.functionName %}',
3745+
AllowedFunctions: '*limited*',
3746+
Payload: {
3747+
model: '{% $states.input.new_model %}',
3748+
token: '{% $states.context.Task.Token %}',
3749+
},
3750+
},
3751+
),
36673752
End: true,
36683753
},
36693754
},

0 commit comments

Comments
 (0)