AWS Cloudwatch to Slack via API Gateway and Lambda

Slack has many integrations with third party tools and apps, unfortunately as of this time there is no direct integration with AWS SNS which CloudWatch uses to send its alerts.

In order to get CloudWatch alerts sending to Slack it is necessary to use an intermediary service, examples include Zapier, Heroku (Example 1, Example 2) or more recently AWS Lambda (Example 1, Example 2).

Using Lambda is the most attractive option as it is very easy to set it up and means you don’t need to maintain another account with a different service. The only draw back with using Lambda is that its only available in a few select regions. If you use AWS regions outside of the 4 that currently support Lambda then you cannot send alerts to Slack directly via Lambda.

Hopefully Lambda will eventually be able to be used in all AWS regions but until that time there is another way to leverage the power of Lambda to get CloudWatch alerts posting into Slack channels – using the AWS API Gateway.

Lets get started by creating a new incoming web hook within Slack. Once that is done we can create our Lambda function to process the SNS alerts.

Choose one of the available regions for Lambda skip the blueprint section and choose a name for your function. Make sure Node.js is selected as the runtime. You can accept the defaults for the rest of the fields.

Screen Shot 2015-08-20 at 11.06.46 pm

Paste the following code into the code box replacing <your_unique_web_hook_url> on line 49 with the web hook URL you have created in Slack and save the Lambda function.

Now we can create our API with the API Gateway from within the AWS console.

Screen Shot 2015-08-20 at 10.48.23 pm

Setup a POST method and choose the Lambda function we setup earlier then click Save.

Screen Shot 2015-08-20 at 10.52.31 pm

 

Now you are ready to deploy your API, click Deploy API and create a stage, I have used the default suggestion of prod.

Screen Shot 2015-08-20 at 11.22.53 pm

 

Copy the invoke URL and create a new SNS topic called “Slack”. Create a subscription setting the protocol to HTTPS and then paste in your API URL from above.

The final step is to request a confirmation for your new subscription and then check the logs for your Lambda function to get the subscription confirmation link. You need to confirm the subscription with this link.

Now you are done and you should have CloudWatch alerts flowing through to your Slack channel.

Screen Shot 2015-08-20 at 11.30.42 pm

 

Deploying client side applications to S3 with Grunt

If you are developing static client side applications then S3 is the perfect place to host them – it is cheap and massively scalable especially if you use CloudFront.

Using Grunt and grunt-aws-s3 also makes it incredibly easy to deploy these apps.

I’m going to assume you already have nodejs and Grunt installed and ready to go, so lets start by adding the grunt-aws-s3 plugin:

Once that is installed you can enable it inside your Gruntfile by adding the following:

Now you need to create an S3 bucket to deploy to and an IAM user and policy to give Grunt permission to deploy to it.

When you create the new IAM user you should generate new keys, place the access key, secret key and your S3 bucket region into a file named deploy-keys.json (Make sure you place this file in your .gitignore – you should never commit API keys) in the same directory as your Gruntfile and in the following format:

Attach the following IAM policy to your newly created user where is the name of the S3 bucket you have created:

You can now add the following to your grunt.initConfig to setup the deploy task:

Refer to the grunt-aws-s3 documentation for further configuration options, you may also like to change the files cwd to a sub folder such as /dist or /www if you have Grunt running a build step into a sub directory.

You can now deploy your application to S3 by running the following:

Most likely you will want to run a few other grunt tasks before deploying like linting or building so you should register a task like so:

Now you have a deploy task which will run jshint and build your project before deploying it to S3 (obviously you will need to have registered tasks for jshint and build for this to work) :

This task can now be run whenever you need to push a new version of your application live.

A final tip – If you are using jshint or any other linter with your project and have it set to enforce camel case variable names you may find that it does not like the “aws_s3” key used inside the grunt.initConfig block – this is easy to fix by adding the following to your Gruntfile:

You can now go through the rest of your Gruntfile and replace all references to “aws_s3” with “s3Deploy” and you will receive no more linting errors.