Skip to content

Commit

Permalink
Merge pull request #2 from cevoaustralia/guardduty-archived-findings
Browse files Browse the repository at this point in the history
Added support for alerting on Archiving GuardDuty alerts.
  • Loading branch information
stevemac007 authored Jun 2, 2024
2 parents d4dba40 + 49bf580 commit 5a65798
Show file tree
Hide file tree
Showing 13 changed files with 517 additions and 39 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,4 @@ REGIONS ?= \
publish: $(usesReleaseZip) $(REGIONS)
$(REGIONS):
aws $(awsProfile) s3 cp "./cloudformation.yaml" "s3://$(BUCKET_PREFIX)-$@" --acl public-read
aws $(awsProfile) s3 cp "$(RELEASE_ZIP)" "s3://$(BUCKET_PREFIX)-$@" --acl public-read
aws $(awsProfile) s3 cp "$(RELEASE_ZIP)" "s3://$(BUCKET_PREFIX)-$@" --acl public-read
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
},
"dependencies": {
"lodash": "^4.17.21",
"aws-sdk": "^2.463.0",
"test": "^3.3.0"
},
"devDependencies": {
"aws-sdk": "^2.463.0",
"eslint": "^5.16.0",
"eslint-plugin-import": "^2.17.3",
"eslint-plugin-lodash": "^2.7.0",
Expand Down
9 changes: 9 additions & 0 deletions src/eventdef.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,15 @@ class EventDef {
return this.getArn().product;
}

/**
* Get detail type from current record.
*
* @returns {string|undefined} The detail-type field
*/
getDetailType() {
return _.get(this.message, "detail-type");
}

/**
* Get SNS subject from current record.
*
Expand Down
4 changes: 3 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ const _ = require("lodash")
"codedeploySns",
"codepipeline",
"codepipeline-approval",
"guardduty",
"guardduty-apicall",
"guardduty-findings",
"guardduty-kuberuntime",
"securityhub",
"inspector",
"rds",
Expand Down
66 changes: 66 additions & 0 deletions src/parsers/guardduty-apicall.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// AWS GuardDuty event parser
//
exports.matches = event =>
event.getSource() === "guardduty" && event.getDetailType() === "AWS API Call via CloudTrail";

exports.parse = event => {
const detail = event.get("detail");

const createdAt = new Date(_.get(detail, "time"));
const fields = [];

const eventName = _.get(detail, "eventName");
const actionedBy = _.get(detail, "userIdentity.principalId");
const accountId = _.get(detail, "recipientAccountId");
const region = _.get(detail, "awsRegion");

let title = "Findings Archived";
let description = `Findings Archived by ${actionedBy}`;
let color = event.COLORS.ok;

if (eventName === "UnarchiveFindings") {
title = "Findings Unarchived";
description = `Findings Unarchived by ${actionedBy}`;
color = event.COLORS.warning;
}

fields.push({
title: "Account",
value: accountId,
short: true
});

fields.push({
title: "Region",
value: region,
short: true
});

fields.push({
title: "Actioned by",
value: actionedBy,
short: false
});

const findings = _.get(detail, "requestParameters.findingIds");

for (const finding of findings) {
fields.push({
title: "Finding ID",
value: finding,
short: false
});
}


return event.attachmentWithDefaults({
author_name: "Amazon GuardDuty",
fallback: `${title} ${description}`,
color: color,
title: title,
fields: fields,
mrkdwn_in: ["title", "text"],
ts: createdAt,
});
};
38 changes: 16 additions & 22 deletions src/parsers/guardduty.js → src/parsers/guardduty-findings.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,27 @@
// AWS GuardDuty event parser
//
exports.matches = event =>
event.getSource() === "guardduty"
|| _.get(event.message, "detail.service.serviceName") === "guardduty";
event.getSource() === "guardduty" && event.getDetailType() === "GuardDuty Finding";

exports.parse = event => {
const detail = event.get("detail");

//const id = _.get(detail, "id");
const title = _.get(detail, "title");
const description = _.get(detail, "description");
const createdAt = new Date(_.get(detail, "time"));
const severity = _.get(detail, "severity");
const accountId = _.get(detail, "accountId");
const region = _.get(detail, "region");
let color = event.COLORS.neutral; //low severity below 4
const fields = [];

//const id = _.get(detail, "id");
const severity = _.get(detail, "severity");
//const partition = _.get(event, "partition");
//const arn = _.get(event, "arn");
const type = _.get(detail, "type");

const threatName = _.get(detail, "service.additionalInfo.threatName");
const threatListName = _.get(detail, "service.additionalInfo.threatListName");
const fields = [];

fields.push({
title: "Description",
Expand Down Expand Up @@ -130,7 +131,7 @@ exports.parse = event => {

const connectionDirection = _.get(detectedAction, "connectionDirection");
const protocol = _.get(detectedAction, "protocol");
const blocked = _.get(detectedAction, "blocked");
// const blocked = _.get(detectedAction, "blocked");

const ipAddressV4 = _.get(detectedAction, "remoteIpDetails.ipAddressV4");
const isp = _.get(detectedAction, "remoteIpDetails.organization.isp");
Expand All @@ -139,12 +140,12 @@ exports.parse = event => {
const country = _.get(detectedAction, "remoteIpDetails.country.countryName");
const city = _.get(detectedAction, "remoteIpDetails.city.cityName");

const remotePort = _.get(detectedAction, "remotePortDetails.port");
const remotePortName = _.get(detectedAction, "remotePortDetails.portName");
// const remotePort = _.get(detectedAction, "remotePortDetails.port");
// const remotePortName = _.get(detectedAction, "remotePortDetails.portName");

const localIpAddress = _.get(detectedAction, "localIpDetails.ipAddressV4");
const localPort = _.get(detectedAction, "localPortDetails.port");
const localPortName = _.get(detectedAction, "localPortDetails.portName");
// const localPortName = _.get(detectedAction, "localPortDetails.portName");


fields.push({
Expand All @@ -164,12 +165,6 @@ exports.parse = event => {
value: `${country} - ${city}`,
short: true
});
//
// fields.push({
// title: "Remote Details",
// value: `${remotePort} (${remotePortName})`,
// short: true
// });
}
else if (actionType === "KUBERNETES_API_CALL") {

Expand Down Expand Up @@ -310,7 +305,7 @@ exports.parse = event => {

const name = _.get(cluster, "name");
const arn = _.get(cluster, "arn");
const createdAt = _.get(cluster, "createdAt");
// const createdAt = _.get(cluster, "createdAt");
const vpcId = _.get(cluster, "vpcId");
const status = _.get(cluster, "status");

Expand All @@ -326,14 +321,14 @@ exports.parse = event => {
short: true
});

const kubernetesDetails = _.get(detail, "resource.kubernetesDetails")
const workloadDetails = _.get(kubernetesDetails, "kubernetesWorkloadDetails")
const kubernetesDetails = _.get(detail, "resource.kubernetesDetails");
const workloadDetails = _.get(kubernetesDetails, "kubernetesWorkloadDetails");
fields.push({
title: "Workload",
value: workloadDetails,
short: true
});
const userDetails = _.get(kubernetesDetails, "kubernetesUserDetails")
const userDetails = _.get(kubernetesDetails, "kubernetesUserDetails");

const username= _.get(userDetails, "username");
const uid = _.get(userDetails, "uid");
Expand All @@ -352,7 +347,7 @@ exports.parse = event => {
short: true
});

const tags = _.get(cluster , "tags");
const tags = _.get(cluster, "tags");

for (let i = 0; i < tags.length; i++) {
const key = tags[i].key;
Expand All @@ -375,11 +370,10 @@ exports.parse = event => {
});
}

let color = event.COLORS.neutral; //low severity below 4
if (severity > 4) { //medium seveirty between 4 and 7
color = event.COLORS.warning;
}
if (severity > 7) { //high sevirity above 7
if (severity > 7) { //high sevirity above 7
color = event.COLORS.critical;
}

Expand Down
128 changes: 128 additions & 0 deletions src/parsers/guardduty-kuberuntime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//
// AWS GuardDuty event parser
//
exports.matches = event =>
event.getSource() === "guardduty" && _.startsWith(event.getDetailType(), "GuardDuty Runtime Protection");

exports.parse = event => {
const detail = event.get("detail");

const title = event.getDetailType();
const description = "";
const fields = [];
const createdAt = new Date(_.get(event, "message.time"));
const accountId = _.get(event, "message.account");
const region = _.get(event, "message.region");

let color = event.COLORS.ok;
if (_.includes(event.getDetailType(), "Unhealthy")) {
color = event.COLORS.critical;
}

const resource = _.get(detail, "resourceDetails");

// const previousStatus = _.get(detail, "previousStatus");
// const currentStatus = _.get(detail, "currentStatus");
const issue = _.get(detail, "issue");

fields.push({
title: "Account",
value: accountId,
short: true
});

fields.push({
title: "Region",
value: region,
short: true
});

const resourceType = _.get(resource, "resourceType");

fields.push({
title: "Resource Type",
value: resourceType,
short: true
});

if (resourceType === "EKS") {
const eksCluster = _.get(resource, "eksClusterDetails");

fields.push({
title: "Cluster",
value: _.get(eksCluster, "clusterName"),
short: true
});

const addonVersion = _.get(eksCluster, "addonDetails.addonVersion");
const addonStatus = _.get(eksCluster, "addonDetails.addonStatus");

fields.push({
title: "AddOn",
value: `${addonVersion} - ${addonStatus}`,
short: true
});
}
else if (resourceType === "EC2") {
const ec2Instance = _.get(resource, "ec2InstanceDetails");
const instanceId = _.get(ec2Instance, "instanceId");
const instanceType = _.get(ec2Instance, "instanceType");
const clusterArn = _.get(ec2Instance, "clusterArn");
const agentVersion= _.get(ec2Instance, "agentDetails.version");
const managementType= _.get(ec2Instance, "managementType");

fields.push({
title: "Instance",
value: instanceId,
short: true
});
fields.push({
title: "Instance Type",
value: instanceType,
short: true
});
fields.push({
title: "ClusterArn",
value: clusterArn,
short: false
});
fields.push({
title: "Agent Version",
value: agentVersion,
short: true
});
fields.push({
title: "Management Type",
value: managementType,
short: true
});
}
else {
console.log(`Unknown GuardDuty resourceType '${resourceType}'`);

fields.push({
title: `Unknown Resource Type (${resourceType})`,
value: JSON.stringify(resource, null, 2),
short: false
});
}


if (issue) {
fields.push({
title: "Issue",
value: issue,
short: false
});
}

return event.attachmentWithDefaults({
author_name: "Amazon GuardDuty",
fallback: `${title} ${description}`,
color: color,
title: title,
fields: fields,
mrkdwn_in: ["title", "text"],
ts: createdAt,
});
};
10 changes: 5 additions & 5 deletions src/parsers/securityhub.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@ exports.parse = event => {
const finding = _.get(detail, "findings")[0];
console.log(`Finding ${JSON.stringify(finding, null, 2)}`);

const id = _.get(finding, "Id");
const generatorId = _.get(finding, "GeneratorId");
// const id = _.get(finding, "Id");
// const generatorId = _.get(finding, "GeneratorId");
const title = _.get(finding, "Title");
const description = _.get(finding, "Description");
const createdAt = new Date(_.get(finding, "CreatedAt"));
const updatedAt = new Date(_.get(finding, "UpdatedAt"));
// const updatedAt = new Date(_.get(finding, "UpdatedAt"));
const firstSeen = new Date(_.get(finding, "FirstObservedAt"));
const lastSeen = new Date(_.get(finding, "LastObservedAt"));
const complianceStatus = _.get(finding, "Compliance.Status");
// const complianceStatus = _.get(finding, "Compliance.Status");
const severity = _.get(finding, "Severity.Normalized");
const severityLabel = _.get(finding, "Severity.Label");
const criticality = _.get(finding, "Criticality");
// const criticality = _.get(finding, "Criticality");

const accountId = _.get(finding, "AwsAccountId");
const resources = _.get(finding, "Resources");
Expand Down
Loading

0 comments on commit 5a65798

Please sign in to comment.