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.
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
var http = require ('https'); var querystring = require ('querystring'); exports.handler = function(event, context) { console.log(event); var message = JSON.parse(event.Message); var color = 'warning'; switch(message.NewStateValue) { case "OK": color = 'good'; break; case "ALARM": color = 'danger'; break; } var payloadStr = JSON.stringify({ "username": "Cloudwatch", "attachments": [ { "title": message.AlarmName, "fallback": message.NewStateReason, "text": message.NewStateReason, "fields": [ { "title": "Region", "value": message.Region, "short": true }, { "title": "State", "value": message.NewStateValue, "short": true } ], "color": color } ], "icon_emoji": ":cloudwatch:" }); var postData = querystring.stringify({ "payload": payloadStr }); var options = { hostname: 'hooks.slack.com', port: 443, path: '/services/<your_unique_web_hook_url>', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': postData.length } }; var req = http.request(options, function(res) { res.on("data", function(chunk) { console.log(chunk); context.done(null, 'done!'); }); }).on('error', function(e) { context.done('error', e); }); req.write(postData); req.end(); }; |
Now we can create our API with the API Gateway from within the AWS console.
Setup a POST method and choose the Lambda function we setup earlier then click Save.
Now you are ready to deploy your API, click Deploy API and create a stage, I have used the default suggestion of prod.
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.