Slack Slash Command Integration with AWS Lambda
By: Shashwat Singh
Tags: Slack Slash Command, AWS Lambda, Serverless, Lambda, Slack

Photo by Joan Gamell on Unsplash

Introduction

Function as a Service(FaaS) is the new era of cloud development which allows us to run code without provisioning or managing any servers. AWS provides lambda functions to build Serverless applications. These applications require a trigger for execution, and once the execution is complete, they go back to sleep. We will be using Slack’s slash command to trigger the lambda function, process the request and then use delayed responses to return results.

Why i am writing this?

I worked on a project that required a check of; if a given IP was added to whitelisted IP list in firewall rules. Checking this manually was time consuming. So, I had a choice of automating this task using lambda functions and getting the results to slack. Going over many websites, I didn’t find any explanation that described complete process on how to achieve this. So thought of writing it down.

Technologies Used

AWS Lambda(Serverless function)

AWS Cloudwatch(Function logging)

AWS SNS(Call another lambda using SNS topic)

AWS API Gateway(API endpoint creation)

AWS EC2 Systems Manager(To save application api keys)

Serverless framework(Framework to create lambda functions using yaml templates)

Slack Slash commands(To call api endpoints and trigger lambda function)

Prerequisites

Have an AWS account and aws-cli configured on your machine.

Have a Slack account.

Have Serverless framework installed.

Architecture

Architecture

Above diagram illustrates the architecture and different components. Let us go through each component and data flow :

The slack’s slash command is configured to call the API gateway endpoint.

This API call acts as a trigger for the 1st lambda function.

The 1st lambda function is used for authenticating the API call, triggering the 2nd lambda function through an SNS topic and sending 200 OK response to slack. This is important as slack’s slash commands expects a response within 3 seconds or it will timeout.

The API call to the firewall and request processing takes more than 3 seconds, so we use another lambda function to take up this task, and use slack’s delayed response_url to send the response back to the slack user through the 2nd lambda function. This response_url is temporary and valid for 30 minutes.

AWS Systems Manager is used to store the api keys used for making api calls to the firewall.

AWS Cloudwatch is used for logging from both the lambda functions.

All the AWS infrastructure is created and managed using Serverless Framework.

Configuring Slash command

To configure slash command, we first need to create a slack application.

A slack app can be created by going here. Click on create an app, then provide the app name and development workspace.

Create slack app

This will create your new slack application. You will be able to see different slack app features and credentials. Go to Slash commands section and click on Create new command.

Create Slash Command

You will get this form. Command is the name of your slash command that you’ll enter to call the web hook. You can enter anything in the request URL field for now(We will change this once we have the API gateway endpoint of our lambda function). Provide a short description for your slash command and usage hint that will be shown while running the command as shown in the preview field. Fill in the details and click on Save. Your slash command is now created.

Creating and configuring lambda functions

We will use Serverless framework to create and manage lambda functions.

Create a new Serverless application.

serverless create --template aws-python3 --path ip-check

This command will create a new project named ip-check with serverless.yml and handler.py files. Update the serverless.yml file with the following code.

service : ip-check, specifies the name of serverless app.

: ip-check, specifies the name of serverless app. provider : Defines the provider, runtime, profile and environment variables.

: Defines the provider, runtime, profile and environment variables. functions : Here we define the lambda functions, its handler and triggers. The first lambda function is named auth . The events parameter will create and configure API gateway with path ip and accepting all methods. This will also configure the API endpoint as a trigger for the auth lambda function.

: Here we define the lambda functions, its handler and triggers. The first lambda function is named . The events parameter will create and configure API gateway with path and accepting all methods. This will also configure the API endpoint as a trigger for the lambda function. The second function is named as processing with SNS topic, named processing-topic as its trigger. Creation of SNS topic is done by the serverless framework.

plugins : These are serverless plugins that we need to install to provide additional features. serverless-python-requirements allows us to pass python plugins that needs to be installed using a requirements.txt file. serverless-pseudo-parameters allows us to use the AWS variables into our code, such as, #{AWS::AccountId} and # {AWS::Region} .

: These are serverless plugins that we need to install to provide additional features. allows us to pass python plugins that needs to be installed using a file. allows us to use the AWS variables into our code, such as, and # . environment : The api_id, api_key and slack_signing_secret will accessed from the AWS SSM parameter store. So, we need the keys to the parameter store.

aws ssm put-parameter\

--name "api_id"

--type "String"

--value "api-id value" aws ssm put-parameter\

--name "api_key"

--type "String"

--value "api-key value" aws ssm put-parameter\

--name "slack_signing_secret"

--type "String"

--value "slack_signing_secret value"

dockerizePip : Setting this to true will build you python packages in docker using a lambda environment, and then zip them up ready to be uploaded with the rest of your code.

Install the two plugins :

npm install serverless-python-requirements

npm install serverless-pseudo-parameters

Writing handler for auth lambda

This lambda function will authenticate if the requests are legit and coming from slack. Slack supports HMAC SHA-256 signature verification technique to authenticate the requests. We generate a hash of the string after concatenating the version number ( v0 ), the timestamp ( 1531420618 ), and the request body ( token=xyzz... ) together, with colon ( : ) as a delimiter and using the signing secret of Slack’s slash command as the hashing key. We compare this hash with the request header ‘X-Slack-Request-Timestamp’ and these should match if the request is valid. The Slack’s signing secret can be found on the slack app’s credentials section. Once the request is authenticated, it triggers the 2nd lambda function through the SNS topic and passes the response_url for delayed responses and the message.

Writing handler for processing lambda

The lambda function will get triggered by the SNS topic and get the response_url and slack message as arguments. It will call the firewall APIs and get the list of all whitelisted IPs, compare it with the input message IP address and then return if the IP is whitelisted or not.

Deploying the lambda functions

Now, the code for both the functions is complete and also serverless.yml file has been updated according to the required configuration. Deploying these functions and other configured services is very easy. You just need to run the serverless deploy command.

sls deploy -v

This command will internally create AWS Cloudformation template and create and configure the different services together. You can view the progress in the Cloudformation dashboard. Once everything is configured, it will give you the API endpoint that is created. We need to update this API endpoint to the request_URL field of our slash command that we have created at the beginning.

Congratulations, You have integrated the Slack Slash command with your custom application running on AWS Lambda 🎊

Try it out

You can go in your slack app and type /ip-check "IP Address” . This will first return “Working on your request” as the response of the first lambda function, and after processing, it will give result if the IP is whitelisted or no.

Further Reading