Created
February 9, 2018 22:55
-
-
Save richadams/3f51b617dc4051563fe358d7b0d40fe2 to your computer and use it in GitHub Desktop.
PagerDuty Custom Event Transformer for handling AWS Config compliance events from SNS. Raising incidents if a resource goes non-compliant, and resolving the incident if they go compliant again (or are deleted).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Parses AWS Config events from SNS and will raise PagerDuty incidents if resources | |
// go non-compliant, resolving the incident when they return to compliant. | |
// | |
// This file is intended to be used with a PagerDuty Custom Event Transformer. | |
// https://www.pagerduty.com/docs/guides/custom-event-transformer/ | |
// | |
// Create a new Custom Event Transformer integration in PagerDuty, and subscribe it's | |
// Integration URL on the SNS Topic that you send AWS Config events to. | |
// | |
// You can see all the different notifications Config sends here: | |
// http://docs.aws.amazon.com/config/latest/developerguide/notifications-for-AWS-Config.html | |
// | |
// Note that there is currently no way to filter on the AWS side, so we have to | |
// do it here instead. All of then have the same "Type" field, so we need to look | |
// at the actual contents to determine if it's an event we care about. | |
// | |
// Compliance events will have a "newEvaluationResult" field, and resource information. | |
// If it lacks those, then it's not compliance related. | |
// You can see an example notification format here: | |
// http://docs.aws.amazon.com/config/latest/developerguide/example-config-rule-compliance-notification.html | |
// | |
// PD.fail(...) is used for any error cases. You will only see these messages if you have | |
// debug mode enabled in the event transformer, otherwise they are suppressed. | |
// Parse the rawBody into a JSON structure | |
var body = JSON.parse(PD.inputRequest.rawBody) | |
// If it's an SNS subscription confirmation, allow it through. | |
if (typeof body.SubscribeURL != "undefined") | |
{ | |
var normalized_event = { | |
incident_key: "sns-subscription", | |
event_type: PD.Trigger, | |
description: "SNS topic subscription confirmation", | |
details: body.SubscribeURL | |
}; | |
PD.emitGenericEvents([normalized_event]); | |
} | |
// Message is double JSON encoded, so we need to parse it again. | |
var message = JSON.parse(body.Message); | |
// Extract resource information, this will be our incident key and identifier. | |
var resourceType = message.resourceType; | |
var resourceId = message.resourceId; | |
var resourceKey = resourceType + "/" + resourceId; | |
// If resource information is missing, then it's not an event we care about. | |
if (typeof resourceType == "undefined") { PD.fail("resourceType missing.") } | |
if (typeof resourceId == "undefined") { PD.fail("resourceId missing.") } | |
// If we don't have any new evaluation results, then this wasn't a compliance | |
// event, and was likely another type of message. | |
if (typeof message.newEvaluationResult == "undefined") { PD.fail("newEvaluationResult missing.") } | |
// Our action is based on the compliance type of the new result. | |
switch(message.newEvaluationResult.complianceType) | |
{ | |
// Has become non-compliant, raise an incident. | |
// (We don't check oldEvaluationResult, as it could be a brand new resource without one) | |
case "NON_COMPLIANT": | |
var normalized_event = { | |
incident_key: resourceKey, | |
event_type: PD.Trigger, | |
description: "Non-compliant AWS resource: " + resourceKey, | |
details: message | |
}; | |
PD.emitGenericEvents([normalized_event]); | |
break; | |
// Has become compliant, resolve any open incident for it. | |
case "COMPLIANT": | |
var normalized_event = { | |
incident_key: resourceKey, | |
event_type: PD.Resolve, | |
description: "Compliant AWS resource: " + resourceKey, | |
details: message | |
}; | |
PD.emitGenericEvents([normalized_event]); | |
break; | |
// Resource was deleted, if there's an open incident, we should resolve it. | |
case "NOT_APPLICABLE": | |
var normalized_event = { | |
incident_key: resourceKey, | |
event_type: PD.Resolve, | |
description: "AWS resource deleted: " + resourceKey, | |
details: message | |
}; | |
PD.emitGenericEvents([normalized_event]); | |
break; | |
// If there's insufficient data, then we also do nothing. | |
case "INSUFFICIENT_DATA": | |
PD.fail("Insufficient data to determine compliance."); | |
break; | |
// Catch-all | |
default: | |
PD.fail("Unknown compliance state: " + newResult); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
On line 41 needed to be changed to the following to get this to work for me:
var message = JSON.parse(body.Message).detail;