-
Notifications
You must be signed in to change notification settings - Fork 53
Add Auto-remediation for check EKS-001 #67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,41 @@ | ||||||||
| 'use strict' | ||||||||
| const AWS = require('aws-sdk') | ||||||||
| /** | ||||||||
| * Lambda function enforce EKS Endpoint not to be public | ||||||||
| * | ||||||||
| */ | ||||||||
| module.exports.handler = (event, context, callback) => { | ||||||||
| console.log('EKS Publicly Accessible Cluster Endpoints - Received event:', JSON.stringify(event, null, 2)) | ||||||||
| if (!event || !event.resource || !event.region) { | ||||||||
| return handleError('Invalid event') | ||||||||
| } | ||||||||
|
|
||||||||
| const clustername=event.resource.split('/')[1]; | ||||||||
|
|
||||||||
| let params = { | ||||||||
| name: clustername, | ||||||||
| resourcesVpcConfig: { | ||||||||
| endpointPrivateAccess: true , | ||||||||
| endpointPublicAccess: false, | ||||||||
| } | ||||||||
| }; | ||||||||
|
|
||||||||
| let eks = new AWS.EKS({region: event.region}) | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
|
||||||||
| eks.updateClusterConfig(params, function(err, data) { | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggest to use asynchronous flow instead of using callbacks. |
||||||||
| if (err) console.log(err, err.stack); // an error occurred | ||||||||
| else console.log(data); // successful response | ||||||||
|
Comment on lines
+26
to
+27
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These
Suggested change
|
||||||||
|
|
||||||||
| if (err) { | ||||||||
| console.log('Error', err) | ||||||||
| return handleError(err.message ? err.message : 'Failed to modify cluster configuration') | ||||||||
| } | ||||||||
| return callback(null, 'Successfully processed event') | ||||||||
|
|
||||||||
| }); | ||||||||
|
|
||||||||
| function handleError (message) { | ||||||||
| message = message || 'Failed to process request.' | ||||||||
| return callback(new Error(message)) | ||||||||
| } | ||||||||
| } | ||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -2,17 +2,29 @@ | |||||
|
|
||||||
| const CONFIG = require('./config') | ||||||
| const AWS = require('aws-sdk') | ||||||
| let delayedExecution; | ||||||
| let delay; | ||||||
| let queueURL; | ||||||
| let type; | ||||||
|
|
||||||
| module.exports.handler = (event, context, callback) => { | ||||||
| console.log('Received event: ', JSON.stringify(event, null, 2)) | ||||||
| console.log('Config settings: ', JSON.stringify(CONFIG, null, 2)) | ||||||
| //console.log('Config settings: ', JSON.stringify(CONFIG, null, 2)) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove unused code
Suggested change
|
||||||
|
|
||||||
| if (!event || !event.Records[0] || !event.Records[0].Sns || !event.Records[0].Sns.Message) { | ||||||
| if ((!event || !event.Records[0] || !event.Records[0].Sns || !event.Records[0].Sns.Message) && !event.Records[0].body) { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can use
Suggested change
|
||||||
| callback(new Error('No event specified')) | ||||||
| return | ||||||
| } | ||||||
|
|
||||||
| let message = JSON.parse(event.Records[0].Sns.Message) | ||||||
| let message; | ||||||
| if(event.Records[0].body){ | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is confuse because line 14 will return an error if |
||||||
| let sqsBody = JSON.parse(event.Records[0].body); | ||||||
| message = JSON.parse(sqsBody.Records[0].Sns.Message) | ||||||
| type=sqsBody.Records[0].Sns.Type | ||||||
| } | ||||||
| else{ | ||||||
| message = JSON.parse(event.Records[0].Sns.Message) | ||||||
| type = event.Records[0].Sns.Type | ||||||
| } | ||||||
| let AutoRemediate = 'AutoRemediate' + message.ruleId | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use
Suggested change
ref: https://medium.com/better-programming/javascript-how-backticks-work-de269e0fb8ba |
||||||
|
|
||||||
| if (!CONFIG[`${AutoRemediate}`]) { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
@@ -27,22 +39,54 @@ module.exports.handler = (event, context, callback) => { | |||||
| return | ||||||
| } | ||||||
|
|
||||||
| let FunctionName = | ||||||
| if (!CONFIG[`${AutoRemediate}`]['delayedExecution']) { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| console.log('Delayed execution disabled', AutoRemediate) | ||||||
| delayedExecution=false | ||||||
| } | ||||||
| else{ | ||||||
| delayedExecution=true; | ||||||
| console.log('Delayed execution enabled', AutoRemediate) | ||||||
| delay=CONFIG[`${AutoRemediate}`]['delay'] | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| queueURL='https://sqs.us-west-2.amazonaws.com/747218156759/CloudConformityAutoRemediate' | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We shouldn't leave the aws account in. We can use environment variable for queue url . |
||||||
|
|
||||||
| } | ||||||
|
|
||||||
| //Event is configured as Delayed notification and this is the first time we're seeing the SNS message... | ||||||
| if (delayedExecution && type!="DelayedNotification") { | ||||||
| console.log("Delayed execution, sending event to SQS with Delay...") | ||||||
| event.Records[0].Sns.Type="DelayedNotification" //Change Type of message and put it on SQS with delay... | ||||||
| var sqs = new AWS.SQS(); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| var params = { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| MessageBody: JSON.stringify(event, null, 2), | ||||||
| QueueUrl: queueURL, | ||||||
| DelaySeconds: delay, | ||||||
| } | ||||||
| sqs.sendMessage(params, function(err, data) { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ♻️ consider to use asyn instead of callback |
||||||
| if (err) console.log(err, err.stack); // an error occurred | ||||||
| else console.log(data); // successful response | ||||||
| }); | ||||||
| } | ||||||
| else{ | ||||||
|
|
||||||
| //Compose the function name based on its own name... | ||||||
| let FunctionName = | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| process.env['AWS_LAMBDA_FUNCTION_NAME'] | ||||||
| .substring(0, process.env['AWS_LAMBDA_FUNCTION_NAME'].lastIndexOf('-') + 1) + | ||||||
| AutoRemediate | ||||||
|
|
||||||
| console.log(`Invoking ${FunctionName} ...`) | ||||||
| console.log(`Invoking ${FunctionName} ...`) | ||||||
|
|
||||||
| let Lambda = new AWS.Lambda({region: process.env['AWS_REGION'], apiVersion: '2015-03-31'}) | ||||||
| let Lambda = new AWS.Lambda({region: process.env['AWS_REGION'], apiVersion: '2015-03-31'}) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| Lambda.invoke({ FunctionName: `${FunctionName}`, Payload: JSON.stringify(message, null, 2) }, function (error, data) { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| if (error) { | ||||||
| console.log(`Error occurred while invoking ${FunctionName}`) | ||||||
| console.log(error) | ||||||
| callback(error) | ||||||
| } else { | ||||||
| callback(null, `Successfully invoked ${FunctionName} with result ${data}`) | ||||||
| } | ||||||
| }) | ||||||
| } | ||||||
|
|
||||||
| Lambda.invoke({ FunctionName: `${FunctionName}`, Payload: JSON.stringify(message, null, 2) }, function (error, data) { | ||||||
| if (error) { | ||||||
| console.log(`Error occurred while invoking ${FunctionName}`) | ||||||
| console.log(error) | ||||||
| callback(error) | ||||||
| } else { | ||||||
| callback(null, `Successfully invoked ${FunctionName} with result ${data}`) | ||||||
| } | ||||||
| }) | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ service: auto-remediate | |
|
|
||
| provider: | ||
| name: aws | ||
| versionFunctions: false | ||
| runtime: nodejs12.x | ||
| stage: v1 | ||
| region: ${opt:region, 'us-east-1'} | ||
|
|
@@ -635,6 +636,19 @@ functions: | |
| - functions/AutoRemediateEC2-045.js | ||
| role: AutoRemediateEC2045Role | ||
|
|
||
| AutoRemediateEKS-001: | ||
| handler: functions/AutoRemediateEKS-001.handler | ||
| timeout: 120 | ||
| memorySize: 128 | ||
| tags: | ||
| Name: Auto Remediate EKS-001 | ||
| Owner: CloudConformity | ||
| Role: Auto Remediate | ||
| Environment: Ops | ||
| package: | ||
| include: | ||
| - functions/AutoRemediateEKS-001.js | ||
| role: AutoRemediateEKS001Role | ||
| AutoRemediateEC2-038: | ||
| handler: functions/AutoRemediateEC2-038.handler | ||
| timeout: 120 | ||
|
|
@@ -708,6 +722,12 @@ resources: | |
|
|
||
| Resources: | ||
|
|
||
| AutoRemediateQUEUE: | ||
| Type: AWS::SQS::Queue | ||
| Properties: | ||
| MessageRetentionPeriod: 7200 #2 Hours | ||
| QueueName: CloudConformityAutoRemediate | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The SQS queue must be encrypted at rest. Please configure KMS KeyId in the queue property |
||
| AutoRemediateEC2002Role: | ||
| Type: AWS::IAM::Role | ||
| Properties: | ||
|
|
@@ -1568,6 +1588,14 @@ resources: | |
| - Ref: 'AWS::Region' | ||
| - Ref: 'AWS::AccountId' | ||
| - 'log-group:/aws/lambda/*:*:*' | ||
| - Effect: Allow | ||
| Action: | ||
| - sqs:SendMessage | ||
| - sqs:ReceiveMessage | ||
| - sqs:DeleteMessage | ||
| - sqs:GetQueueAttributes | ||
| Resource: | ||
| Fn::GetAtt: [ AutoRemediateQUEUE, Arn ] | ||
| - Effect: Allow | ||
| Action: | ||
| - lambda:InvokeFunction | ||
|
|
@@ -2044,6 +2072,41 @@ resources: | |
| - ec2:RevokeSecurityGroupIngress | ||
| Resource: "*" | ||
|
|
||
| AutoRemediateEKS001Role: | ||
| Type: AWS::IAM::Role | ||
| Properties: | ||
| RoleName: AutoRemediateEKS-001Role | ||
| AssumeRolePolicyDocument: | ||
| Version: '2012-10-17' | ||
| Statement: | ||
| - Effect: Allow | ||
| Principal: | ||
| Service: | ||
| - lambda.amazonaws.com | ||
| Action: | ||
| - sts:AssumeRole | ||
| Policies: | ||
| - PolicyName: AutoRemediateEKS001RolePolicy | ||
| PolicyDocument: | ||
| Statement: | ||
| - Effect: Allow | ||
| Action: | ||
| - logs:CreateLogGroup | ||
| - logs:CreateLogStream | ||
| - logs:PutLogEvents | ||
| Resource: | ||
| - 'Fn::Join': | ||
| - ':' | ||
| - | ||
| - 'arn:aws:logs' | ||
| - Ref: 'AWS::Region' | ||
| - Ref: 'AWS::AccountId' | ||
| - 'log-group:/aws/lambda/*:*:*' | ||
| - Effect: Allow | ||
| Action: | ||
| - eks:UpdateClusterConfig | ||
| Resource: "*" | ||
|
|
||
| AutoRemediateRS023Role: | ||
| Type: AWS::IAM::Role | ||
| Properties: | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,11 @@ | ||||||
| let event = { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| 'resource': 'EKS-TEST', | ||||||
| 'region': 'us-east-1' | ||||||
| } | ||||||
|
|
||||||
| let AutoRemediate = require('../functions/AutoRemediateEKS-001') | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| AutoRemediate.handler(event, {}, function (err, data) { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add valid unit tests here. |
||||||
| console.log(err) | ||||||
| console.log('data', JSON.stringify(data, null, 2)) | ||||||
| }) | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.