Skip to content

Commit 36c342e

Browse files
Release/module v1 (#1)
* feat: update mabda parameter and payload * feat: update variables * chore: update readme vars and types
1 parent 2f2d069 commit 36c342e

File tree

7 files changed

+65
-42
lines changed

7 files changed

+65
-42
lines changed

README.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ module "remediation" {
3232
aws_region = "us-east-1"
3333
account_id = "2123232323"
3434
lambda_log_group = "/aws/lambda/vulne-soldier-compliance-remediate"
35+
lambda_zip = "lambda.zip"
3536
remediation_options = {
3637
region = "us-east-1"
3738
reboot_option = "NoReboot"
@@ -56,13 +57,14 @@ provider "aws" {
5657
| `aws_region` | AWS region where the resources will be created | `string` | n/a | yes |
5758
| `account_id` | AWS account ID | `string` | n/a | yes |
5859
| `lambda_log_group` | Name of the CloudWatch Log Group for the Lambda function | `string` | n/a | yes |
60+
| `lambda_zip` | File location of the lambda zip file for remediation | `string` | `lambda.zip` | yes |
5961
| `remediation_options` | Options for the remediation document | `object` | n/a | yes |
6062
| `remediation_options.region` | The region to use | `string` | `us-east-1` | no |
6163
| `remediation_options.reboot_option` | Reboot option for patching | `string` | `NoReboot` | no |
6264
| `remediation_options.target_ec2_tag_name`| The tag name to filter EC2 instances | `string` | `AmazonECSManaged` | no |
6365
| `remediation_options.target_ec2_tag_value`| The tag value to filter EC2 instances | `string` | `true` | no |
64-
| `remediation_options.vulnerability_severities`| List of vulnerability severities to filter findings | `list(string)`| `["CRITICAL, HIGH"]` | no |
65-
| `remediation_options.override_findings_for_target_instances_ids`| List of instance IDs to override findings for target instances | `list(string)`| `[]` | no |
66+
| `remediation_options.vulnerability_severities`| Comma separated list of vulnerability severities to filter findings | `string`| `"CRITICAL, HIGH"` | no |
67+
| `remediation_options.override_findings_for_target_instances_ids`| Comma separated list of instance IDs to override findings for target instances | `string`| `""` | no |
6668

6769
## Outputs
6870

examples/basic/README.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ module "remediation" {
1919
aws_region = "us-east-1"
2020
account_id = "2324334432"
2121
lambda_log_group = "/aws/lambda/vulne-soldier-compliance-remediate"
22+
lambda_zip = "lambda.zip"
2223
remediation_options = {
2324
region = "us-east-1"
2425
reboot_option = "NoReboot"
@@ -43,13 +44,14 @@ provider "aws" {
4344
| `aws_region` | AWS region where the resources will be created | `string` | n/a | yes |
4445
| `account_id` | AWS account ID | `string` | n/a | yes |
4546
| `lambda_log_group` | Name of the CloudWatch Log Group for the Lambda function | `string` | n/a | yes |
47+
| `lambda_zip` | File location of the lambda zip file for remediation | `string` | `lambda.zip` | yes |
4648
| `remediation_options` | Options for the remediation document | `object` | n/a | yes |
4749
| `remediation_options.region` | The region to use | `string` | `us-east-1` | no |
4850
| `remediation_options.reboot_option` | Reboot option for patching | `string` | `NoReboot` | no |
4951
| `remediation_options.target_ec2_tag_name`| The tag name to filter EC2 instances | `string` | `AmazonECSManaged` | no |
5052
| `remediation_options.target_ec2_tag_value`| The tag value to filter EC2 instances | `string` | `true` | no |
51-
| `remediation_options.vulnerability_severities`| List of vulnerability severities to filter findings | `list(string)`| `["CRITICAL, HIGH"]` | no |
52-
| `remediation_options.override_findings_for_target_instances_ids`| List of instance IDs to override findings for target instances | `list(string)`| `[]` | no |
53+
| `remediation_options.vulnerability_severities`| Comma separated list of vulnerability severities to filter findings | `string`| `"CRITICAL, HIGH"` | no |
54+
| `remediation_options.override_findings_for_target_instances_ids`| Comma separated list of instance IDs to override findings for target instances | `string`| `""` | no |
5355

5456
### Outputs
5557

examples/basic/main.tf

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ module "remediation" {
44
name = "vulne-soldier-compliance-remediate"
55
environment = "dev"
66
aws_region = "us-east-1"
7-
account_id = "2132323212"
7+
account_id = "2132323212_dummmmy"
88
lambda_log_group = "/aws/lambda/vulne-soldier-compliance-remediate"
9+
lambda_zip = "../../lambda.zip"
910
remediation_options = {
1011
region = "us-east-1"
1112
reboot_option = "NoReboot"
1213
target_ec2_tag_name = "AmazonECSManaged"
1314
target_ec2_tag_value = "true"
14-
vulnerability_severities = ["CRITICAL, HIGH"]
15-
override_findings_for_target_instances_ids = []
15+
vulnerability_severities = "CRITICAL, HIGH"
16+
override_findings_for_target_instances_ids = ""
1617
}
1718
}

lambda/findings-remediate.js renamed to lambda/index.js

+24-15
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
import { logger } from './logger';
1+
const AWS = require("aws-sdk");
2+
const logger = require('./logger');
23

34
exports.handler = async (event) => {
45
const REGION = event.region || 'us-east-1';
56
const REBOOT_OPTION = event.reboot_option || "NoReboot";
67
const TARGET_EC2_TAG_NAME = event.target_ec2_tag_name;
78
const TARGET_EC2_TAG_VALUE = event.target_ec2_tag_value;
8-
const VULNERABILITY_SEVERITIES = event.vulnerability_severities
9-
&& event.vulnerability_severities.split(',').map(a => a.trim().toUpperCase());
10-
const OVERRIDE_FINDINGS_FOR_TARGET_INSTANCES_IDS = event.override_findings_for_target_instances_ids
11-
&& event.override_findings_for_target_instances_ids.split(',').map(a => a.trim());
9+
const VULNERABILITY_SEVERITIES = (event.vulnerability_severities
10+
&& event.vulnerability_severities?.split(',')?.map(a => a.trim().toUpperCase())) || [];
11+
const OVERRIDE_FINDINGS_FOR_TARGET_INSTANCES_IDS = (event.override_findings_for_target_instances_ids
12+
&& event.override_findings_for_target_instances_ids?.split(',')?.map(a => a.trim())) || [];
1213

1314
logger.info("Region is ", REGION);
1415
logger.info("Reboot option is ", REBOOT_OPTION);
@@ -18,9 +19,14 @@ exports.handler = async (event) => {
1819
logger.info("Override findings for target instances IDs are ", OVERRIDE_FINDINGS_FOR_TARGET_INSTANCES_IDS);
1920

2021
try {
21-
const ecsManagedInstanceIds = await getECSManagedInstances(REGION, TARGET_EC2_TAG_NAME, TARGET_EC2_TAG_VALUE);
22+
let ecsManagedInstanceIds = [];
23+
if (OVERRIDE_FINDINGS_FOR_TARGET_INSTANCES_IDS && OVERRIDE_FINDINGS_FOR_TARGET_INSTANCES_IDS.length > 0) {
24+
ecsManagedInstanceIds = OVERRIDE_FINDINGS_FOR_TARGET_INSTANCES_IDS;
25+
} else {
26+
ecsManagedInstanceIds = await getECSManagedInstances(REGION, TARGET_EC2_TAG_NAME, TARGET_EC2_TAG_VALUE);
27+
}
2228

23-
const { targetInstances, totalFindings } = await manageInstanceFindings(ecsManagedInstanceIds, REGION, VULNERABILITY_SEVERITIES, OVERRIDE_FINDINGS_FOR_TARGET_INSTANCES_IDS);
29+
const { targetInstances, totalFindings } = await manageInstanceFindings(ecsManagedInstanceIds, REGION, VULNERABILITY_SEVERITIES);
2430

2531
if (!targetInstances.length) {
2632
return {
@@ -31,12 +37,15 @@ exports.handler = async (event) => {
3137
}
3238

3339
const ssm = new AWS.SSM({ region: REGION });
40+
const logConfig = process.env.LAMBDA_LOG_GROUP ? {
41+
CloudWatchOutputConfig: {
42+
CloudWatchLogGroupName: process.env.LAMBDA_LOG_GROUP,
43+
CloudWatchOutputEnabled: true
44+
}
45+
} : {};
3446
const patchResult = await ssm
3547
.sendCommand({
36-
CloudWatchOutputConfig: {
37-
CloudWatchLogGroupName: process.env.LAMBDA_LOG_GROUP || '',
38-
CloudWatchOutputEnabled: true
39-
},
48+
...logConfig,
4049
Comment: 'Lambda function trigger operation for inspector finding auto-remediation',
4150
DocumentName: "AWS-RunPatchBaseline",
4251
DocumentVersion: "1",
@@ -120,7 +129,7 @@ async function getInstanceInspectorFindings(instanceId, region, severities) {
120129
return data.findings;
121130
}
122131

123-
async function manageInstanceFindings(ecsManagedInstanceIds, region, severities, overrideInstanceIds) {
132+
async function manageInstanceFindings(ecsManagedInstanceIds, region, severities) {
124133
const targetInstances = [];
125134
let totalFindings = 0;
126135

@@ -136,12 +145,12 @@ async function manageInstanceFindings(ecsManagedInstanceIds, region, severities,
136145
findings = findings.filter((finding) => !(skippingTitles.includes(finding.title)))
137146
logger.info('Total findings for instanceID ' + instanceId + ' after title check is ' + findings.length);
138147

139-
totalFindings = totalFindings += findings.length;
140-
148+
141149
const resource = findings[0].resources[0];
142-
150+
143151
// Check resource type to match expected remediation action:
144152
if (resource.type === "AWS_EC2_INSTANCE") {
153+
totalFindings = totalFindings += findings.length;
145154
targetInstances.push(instanceId);
146155
}
147156
}

lambda/logger.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ const LogLevel = {
77
};
88

99
class Logger {
10-
constructor(logLevel) {}
10+
constructor(logLevel) {
11+
this.logLevel = logLevel;
12+
}
1113

1214
error(...args) {
1315
if (this.logLevel >= LogLevel.error) {
@@ -32,5 +34,5 @@ const logLevel =
3234
INFO: LogLevel.info,
3335
DEBUG: LogLevel.debug,
3436
}[process.env.LOG_LEVEL ?? "NONE"] ?? LogLevel.none;
35-
36-
export let logger = new Logger(logLevel);
37+
38+
module.exports = new Logger(logLevel);

main.tf

+14-13
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ provider "aws" {
55
locals {
66
function_name = "${var.name}-${var.environment}"
77
ssm_document_name = "${var.name}-inspector-findings-${var.environment}"
8+
lambda_zip = var.lambda_zip
89
}
910

1011
resource "aws_ssm_document" "remediation_document" {
@@ -21,29 +22,29 @@ resource "aws_ssm_document" "remediation_document" {
2122
"description": "(Required) The region to use.",
2223
"default": "${var.remediation_options.region}"
2324
},
24-
"reboot_option": {
25+
"rebootOption": {
2526
"type": "String",
2627
"description": "(Optional) Reboot option for patching. Allowed values: NoReboot, RebootIfNeeded, AlwaysReboot",
2728
"default": "${var.remediation_options.reboot_option}"
2829
},
29-
"target_ec2_tag_name": {
30+
"targetEC2TagName": {
3031
"type": "String",
3132
"description": "The tag name to filter EC2 instances.",
3233
"default": "${var.remediation_options.target_ec2_tag_name}"
3334
},
34-
"target_ec2_tag_value": {
35+
"targetEC2TagValue": {
3536
"type": "String",
3637
"description": "The tag value to filter EC2 instances.",
3738
"default": "${var.remediation_options.target_ec2_tag_value}"
3839
},
39-
"vulnerability_severities": {
40-
"type": "StringList",
41-
"description": "(Optional) List of vulnerability severities to filter findings. Allowed values are comma separated list of : CRITICAL, HIGH, MEDIUM, LOW, INFORMATIONAL",
40+
"vulnerabilitySeverities": {
41+
"type": "String",
42+
"description": "(Optional) Comma separated list of vulnerability severities to filter findings. Allowed values are comma separated list of : CRITICAL, HIGH, MEDIUM, LOW, INFORMATIONAL",
4243
"default": "${var.remediation_options.vulnerability_severities}"
4344
},
44-
"override_findings_for_target_instances_ids": {
45-
"type": "StringList",
46-
"description": "(Optional) List of instance IDs to override findings for target instances. If not provided, all matched findings will be remediated. Values are in comma separated list of instance IDs.",
45+
"overrideFindingsForTargetInstancesIDs": {
46+
"type": "String",
47+
"description": "(Optional) Comma separated list of instance IDs to override findings for target instances. If not provided, all matched findings will be remediated. Values are in comma separated list of instance IDs.",
4748
"default": "${var.remediation_options.override_findings_for_target_instances_ids}"
4849
}
4950
},
@@ -53,7 +54,7 @@ resource "aws_ssm_document" "remediation_document" {
5354
"action": "aws:invokeLambdaFunction",
5455
"inputs": {
5556
"FunctionName": "arn:aws:lambda:${var.aws_region}:${var.account_id}:function:${local.function_name}",
56-
"Payload": "{ \"region\": \"{{ region }}\", \"reboot_option\": \"{{ reboot_option }}\", \"target_ec2_tag_name\": \"{{ target_ec2_tag_name }}\", \"target_ec2_tag_value\": \"{{ target_ec2_tag_value }}\", \"vulnerability_severities\": \"{{ vulnerability_severities }}\", \"override_findings_for_target_instances_ids\": \"{{ override_findings_for_target_instances_ids }}\" }"
57+
"Payload": "{ \"region\": \"{{ region }}\", \"reboot_option\": \"{{ rebootOption }}\", \"target_ec2_tag_name\": \"{{ targetEC2TagName }}\", \"target_ec2_tag_value\": \"{{ targetEC2TagValue }}\", \"vulnerability_severities\": \"{{ vulnerabilitySeverities }}\", \"override_findings_for_target_instances_ids\": \"{{ overrideFindingsForTargetInstancesIDs }}\" }"
5758
}
5859
}
5960
]
@@ -200,12 +201,12 @@ resource "aws_iam_role_policy" "lambda_policy" {
200201

201202

202203
resource "aws_lambda_function" "inspector_remediation" {
203-
filename = "../../lambda.zip" # You should zip your lambda_function.js before deploying
204+
filename = local.lambda_zip # You should zip your lambda_function.js before deploying
204205
function_name = local.function_name
205206
role = aws_iam_role.lambda_execution_role.arn
206-
handler = "findings-remediate.handler"
207+
handler = "index.handler"
207208
runtime = "nodejs18.x"
208-
source_code_hash = filebase64sha256("./lambda.zip")
209+
source_code_hash = filebase64sha256(local.lambda_zip)
209210

210211
timeout = 300
211212

variables.tf

+10-4
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,28 @@ variable "lambda_log_group" {
2323
type = string
2424
}
2525

26+
variable "lambda_zip" {
27+
description = "File location of the lambda zip file for remediation."
28+
type = string
29+
default = null
30+
}
31+
2632
variable "remediation_options" {
2733
description = "Options for the remediation document"
2834
type = object({
2935
region = string
3036
reboot_option = string
3137
target_ec2_tag_name = string
3238
target_ec2_tag_value = string
33-
vulnerability_severities = list(string)
34-
override_findings_for_target_instances_ids = list(string)
39+
vulnerability_severities = string
40+
override_findings_for_target_instances_ids = string
3541
})
3642
default = {
3743
region = "us-east-1"
3844
reboot_option = "NoReboot"
3945
target_ec2_tag_name = "AmazonECSManaged"
4046
target_ec2_tag_value = "true"
41-
vulnerability_severities = ["CRITICAL, HIGH"]
42-
override_findings_for_target_instances_ids = []
47+
vulnerability_severities = "CRITICAL, HIGH"
48+
override_findings_for_target_instances_ids = null
4349
}
4450
}

0 commit comments

Comments
 (0)