Invoke AWS Step Function from AWS Lambda using the Serverless Framework
In one of my last articles I showed how to chain Lambda Functions which means to invoke one Lambda Function from another one. This time I want to show you how you can invoke a Step Function from a Lambda Function using the Serverless Framework.
A use case for this kind of a setup is if you for example have a Step Function which should be invoked after receiving a request through an AWS API Gateway and want to let’s say validate the requests.
TL;DR
Here you can find a GitHub repository if you want a quick start.
Prerequisites
Follow the instructions in this article to prepare everything and and set up a Step Function which will be called from a dedicated “Proxy” Lambda Function.
Additionally install the aws-sdk module which we will need for actually invoking our Step Function
npm install --save aws-sdk
Create Lambda Function
Now we are good to go, so lets create a new project using the Serverless Framework and define our Step Machine
Prepare Environment
The Serverless Framework allows to define access rights inside the serverless.yml. We need to grant the permission for starting Step Functions as followed
provider:
name: aws
runtime: nodejs6.10
region: us-east-1
iamRoleStatements:
- Effect: Allow
Action:
- states:StartExecution
Resource: "*"
Reference to the Step Function
Now the interesting part. We are going to define an output resource named StateMachine and assign a reference to our Step Function. Later we set this resource as a value for an environment variable of the “Proxy” Lambda.
resources:
Outputs:
StateMachine:
Description: The ARN of the provisioning state machine
Value:
Ref: Hellostepfunc1
NOTE: Even though the name of the Step Function begins with a lower letter we have to reference it here using a capital letter, don’t ask me why.
Define “Proxy” Lambda
Let’s finally define our “Proxy” Lambda, which invokes the Step Function
var aws = require('aws-sdk')
module.exports.proxy = (event, context, callback) => {
var params = {
stateMachineArn: process.env.statemachine_arn,
input: JSON.stringify({})
}
var stepfunctions = new aws.StepFunctions()
stepfunctions.startExecution(params, function (err, data) {
if (err) {
console.log('err while executing step function')
} else {
console.log('started execution of step function')
}
})
}
Note that we have to set the ARN of the Step Function in order to invoke it. In the last step we introduced a resource which holds this ARN. In the next step we will see how to actually use it.
Define handler
The last step is to connect our functions to the respective Lambda Function handlers in the serverless.yml. Note that this time we also specify a environment variable. Here we use the resource we created to assigns the value of the resource to the environment variable called statemachine_arn. With this technique you can reference Step Functions. Quite easy, right?
functions:
...
proxy:
handler: handler.proxy
environment:
statemachine_arn: ${self:resources.Outputs.StateMachine.Value}
Deploy Functions
At this point we could deploy our Lambda and Step Functions
serverless deploy -v
You should see verbose output and If everything went fine you can see your Functions in the respective AWS console view. Just be sure to select the right region.
Note: Referencing a Step Function this way seems not to work when using the serverless-offline plugin, at least for me it didn’t.
Invoke Lambda Function
Now you can invoke the Lambda and you should see an output which says that the Step Function execution started
serverless invoke -f proxy -l
Well that’s it, have fun playing around with AWS Lambda and Step Functions. I would love to hear any feedback.
Cheers
Noah