|
// |
|
// Sends Cloudwatch Event notifications to Slack |
|
// |
|
|
|
|
|
// |
|
// Setup: |
|
// |
|
// 1. Create a slack incoming webhook and get your token |
|
// 2. Encrypt this token with KMS and paste the CiphertextBlob at 'Replace with your KMS token' |
|
// Example: |
|
// $ aws kms encrypt --key-id 22e06448-f73c-42c4-b18f-74f91eb7bc1a --plaintext "your slack token" |
|
// { |
|
// "KeyId": "arn:aws:kms:us-west-2:xxxxxxxxxx:key/22e06448-f73c-42c4-b18f-74f91eb7bc1a", |
|
// "CiphertextBlob": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" |
|
// } |
|
// 3. Create a Lambda function and replace all the const with the required data |
|
// Function name: cloudwatch-event-to-slack |
|
// You may use the attached test data to test this function (right after you finish the next item) |
|
// 4. Give your function's role permission for the kms:Decrypt action. |
|
// Example: |
|
// { |
|
// "Version": "2012-10-17", |
|
// "Statement": [ |
|
// { |
|
// "Effect": "Allow", |
|
// "Action": [ |
|
// "kms:Decrypt" |
|
// ], |
|
// "Resource": [ |
|
// "<your KMS key ARN>" |
|
// ] |
|
// } |
|
// ] |
|
// } |
|
// |
|
// 5. Create a new CloudWatch Event Rule to send EC2 events to this lambda function |
|
// Screenshot: http://jmp.sh/uBi6dV8 |
|
// 6. You may test this by terminating and lanching an EC2 instance |
|
// |
|
|
|
|
|
const SLACK_URL = 'https://<your organization>.slack.com/services/hooks/incoming-webhook'; // Replace |
|
const SLACK_CHANNEL_NAME = "#updates-dev"; // Replace with yout own channel name |
|
const SLACK_USERNAME = "webhookbot"; |
|
const kmsEncyptedToken = 'Replace with your KMS token'; // Replace |
|
|
|
console.log('Loading function'); |
|
|
|
const AWS = require('aws-sdk'); |
|
const url = require('url'); |
|
const https = require('https'); |
|
const qs = require('querystring'); |
|
|
|
|
|
exports.handler = function(event, context) { |
|
var token = null; |
|
var slackReqOpts = null; |
|
if (token) { |
|
// Container reuse, simply process the event with the key in memory |
|
processEvent(event, context, slackReqOpts); |
|
} else { |
|
const encryptedBuf = new Buffer(kmsEncyptedToken, 'base64'); |
|
const cipherText = {CiphertextBlob: encryptedBuf}; |
|
|
|
const kms = new AWS.KMS(); |
|
kms.decrypt(cipherText, function (err, data) { |
|
if (err) { |
|
console.log("Decrypt error: " + err); |
|
context.fail(err); |
|
} else { |
|
token = data.Plaintext.toString('ascii'); |
|
const slackUrl = SLACK_URL; |
|
slackReqOpts = url.parse(slackUrl + '?token=' + token); |
|
slackReqOpts.method = 'POST'; |
|
slackReqOpts.headers = {'Content-Type': 'application/json'}; |
|
processEvent(event, context, slackReqOpts); |
|
} |
|
}); |
|
} |
|
}; |
|
|
|
var processEvent = function(event, context, slackReqOpts) { |
|
var source = event.source; |
|
var region = event.region; |
|
var detail = event.detail; |
|
var instanceId = detail['instance-id']; |
|
var state = detail.state; |
|
var text = []; |
|
text.push(source); |
|
text.push(' (' + region + ')'); |
|
text.push(': '); |
|
text.push(instanceId); |
|
text.push(' is '); |
|
text.push(state); |
|
|
|
|
|
var req = https.request(slackReqOpts, function (res) { |
|
if (res.statusCode === 200) { |
|
context.succeed('posted to slack'); |
|
} else { |
|
context.fail('status code: ' + res.statusCode); |
|
} |
|
}); |
|
|
|
req.on('error', function(e) { |
|
console.log('problem with request: ' + e.message); |
|
context.fail(e.message); |
|
}); |
|
req.write(JSON.stringify({ |
|
channel: SLACK_CHANNEL_NAME, |
|
username: SLACK_USERNAME, |
|
text: text.join(''), |
|
icon_emoji: ":ghost:" |
|
})); |
|
req.end(); |
|
} |
Ugh, had such high hopes for this, until I found out there's no AWS Lambda in us-west-1, so cloudwatch can't be configured to send to that. :-/ Sigh, further down the rabbithole...maybe I can ship via SQS...