Skip to content

Commit

Permalink
Merge pull request #1 from AkhtarAmir/feature/ec2-plugin-mark-launch-…
Browse files Browse the repository at this point in the history
…wizard-security-groups

Feature/ec2 plugin mark launch wizard security groups
  • Loading branch information
AkhtarAmir authored Aug 14, 2020
2 parents 2122ade + de52e8a commit f3b72f6
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 16 deletions.
4 changes: 3 additions & 1 deletion exports.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ module.exports = {
'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'),

'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'),
'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'),
'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'),
'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'),
'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'),
Expand Down Expand Up @@ -71,8 +72,9 @@ module.exports = {
'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'),
'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'),
'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'),
'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'),
'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'),
'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'),
'vpcEndpointAcceptance' : require(__dirname + '/plugins/aws/ec2/vpcEndpointAcceptance'),
'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'),
'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'),

Expand Down
2 changes: 1 addition & 1 deletion plugins/aws/ec2/ec2MetadataOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module.exports = {
title: 'Insecure EC2 Metadata Options',
category: 'EC2',
description: 'Ensures EC2 instance metadata is updated to require HttpTokens or disable HttpEndpoint',
more_info: 'The new EC2 metadata service prevents SSRF attack escalations from accessing the senstive instance metadata endpoints.',
more_info: 'The new EC2 metadata service prevents SSRF attack escalations from accessing the sensitive instance metadata endpoints.',
link: 'https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html#configuring-instance-metadata-service',
recommended_action: 'Update instance metadata options to use IMDSv2',
apis: ['EC2:describeInstances'],
Expand Down
55 changes: 55 additions & 0 deletions plugins/aws/ec2/launchWizardSecurityGroups.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
var async = require('async');
var helpers = require('../../../helpers/aws');

module.exports = {
title: 'EC2 LaunchWizard Security Groups',
category: 'EC2',
description: 'Ensures security groups created by the EC2 launch wizard are not used',
more_info: 'The EC2 launch wizard frequently creates insecure security groups that are exposed publicly. These groups should not be used and custom security groups should be created instead.',
link: 'https://docs.aws.amazon.com/launchwizard/latest/userguide/launch-wizard-sap-security-groups.html',
recommended_action: 'Delete the launch wizard security group and replace it with a custom security group.',
apis: ['EC2:describeSecurityGroups'],

run: function(cache, settings, callback) {
var results = [];
var source = {};
var regions = helpers.regions(settings);

async.each(regions.ec2, function(region, rcb){
var describeSecurityGroups = helpers.addSource(cache, source,
['ec2', 'describeSecurityGroups', region]);

if (!describeSecurityGroups) return rcb();

if (describeSecurityGroups.err || !describeSecurityGroups.data) {
helpers.addResult(results, 3,
'Unable to query for security groups: ' + helpers.addError(describeSecurityGroups), region);
return rcb();
}

if (!describeSecurityGroups.data.length) {
helpers.addResult(results, 0, 'No security groups present', region);
return rcb();
}

for (var s in describeSecurityGroups.data) {
var sg = describeSecurityGroups.data[s];
var resource = sg.GroupId;

if (sg.GroupName.toLowerCase().startsWith('launch-wizard')) {
helpers.addResult(results, 2,
'Security Group ' + sg.GroupName + ' was launched using EC2 launch wizard',
region, resource);
} else {
helpers.addResult(results, 0,
'Security Group ' + sg.GroupName + ' was not launched using EC2 launch wizard',
region, resource);
}
}

rcb();
}, function(){
callback(null, results, source);
});
}
};
153 changes: 153 additions & 0 deletions plugins/aws/ec2/launchWizardSecurityGroups.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
var expect = require('chai').expect;
const launchWizardSecurityGroups = require('./launchWizardSecurityGroups');

const securityGroups = [
{
"Description": "launch-wizard-1 created 2020-08-10T14:28:09.271+05:00",
"GroupName": "launch-wizard-1",
"IpPermissions": [
{
"FromPort": 22,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "0.0.0.0/0"
}
],
"Ipv6Ranges": [],
"PrefixListIds": [],
"ToPort": 22,
"UserIdGroupPairs": []
}
],
"OwnerId": "560213429563",
"GroupId": "sg-0ff1642cae23c309a",
"IpPermissionsEgress": [
{
"IpProtocol": "-1",
"IpRanges": [
{
"CidrIp": "0.0.0.0/0"
}
],
"Ipv6Ranges": [],
"PrefixListIds": [],
"UserIdGroupPairs": []
}
],
"Tags": [],
"VpcId": "vpc-99de2fe4"
},
{
"Description": "Allows SSh access to developer",
"GroupName": "spec-test-sg",
"IpPermissions": [],
"OwnerId": "560213429563",
"GroupId": "sg-0b5f2771716acfee4",
"IpPermissionsEgress": [
{
"FromPort": 22,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "0.0.0.0/0"
}
],
"Ipv6Ranges": [
{
"CidrIpv6": "::/0"
}
],
"PrefixListIds": [],
"ToPort": 22,
"UserIdGroupPairs": []
}
],
"Tags": [],
"VpcId": "vpc-99de2fe4"
}
];

const createCache = (securityGroups) => {
return {
ec2: {
describeSecurityGroups: {
'us-east-1': {
data: securityGroups
},
},
},
};
};

const createErrorCache = () => {
return {
ec2: {
describeSecurityGroups: {
'us-east-1': {
err: {
message: 'error describing security groups'
},
},
},
},
};
};

const createNullCache = () => {
return {
ec2: {
describeSecurityGroups: {
'us-east-1': null,
},
},
};
};

describe('launchWizardSecurityGroups', function () {
describe('run', function () {
it('should PASS if security groups was not created using EC2 launch wizard', function (done) {
const cache = createCache([securityGroups[1]]);
launchWizardSecurityGroups.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(0);
done();
});
});

it('should FAIL if security groups was created using EC2 launch wizard', function (done) {
const cache = createCache([securityGroups[0]]);
launchWizardSecurityGroups.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(2);
done();
});
});

it('should PASS if no security groups are detected', function (done) {
const cache = createCache([]);
launchWizardSecurityGroups.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(0);
done();
});
});

it('should UNKNOWN if there was an error describing security groups', function (done) {
const cache = createErrorCache();
launchWizardSecurityGroups.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(3);
done();
});
});

it('should not return any results if unable to query for security groups', function (done) {
const cache = createNullCache();
launchWizardSecurityGroups.run(cache, {}, (err, results) => {
expect(results.length).to.equal(0);
done();
});
});
});
});
9 changes: 0 additions & 9 deletions plugins/aws/ec2/vpcEndpointAcceptance.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,6 @@ describe('vpcEndpointAcceptance', function () {
});
});

it('should PASS if no VPC endpoint services are detected', function (done) {
const cache = createCache([]);
vpcEndpointAcceptance.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(0);
done();
});
});

it('should UNKNOWN if there was an error querying for VPC endpoint services', function (done) {
const cache = createErrorCache();
vpcEndpointAcceptance.run(cache, {}, (err, results) => {
Expand Down
10 changes: 5 additions & 5 deletions plugins/google/vpcnetwork/defaultVpcInUse.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ module.exports = {
if (network.name == 'default') {
defVPC = true;
vpcUrl = network.selfLink;
}
}
});
if (!defVPC) {
helpers.addResult(results, 0, 'No default VPC found', 'global');
Expand All @@ -52,9 +52,9 @@ module.exports = {

async.each(regions.zones, function(location, icb){
location.forEach(loc => {
let instances = helpers.addSource(
cache, source, ['instances', 'list', loc]);
let instances = helpers.addSource(cache, source,
['instances', 'compute','list', loc]);

if (!instances || instances.err || !instances.data) {
} else if (instances.data.length) {
instances.data.forEach(instance => {
Expand Down Expand Up @@ -83,4 +83,4 @@ module.exports = {
callback(null, results, source);
});
}
}
}

0 comments on commit f3b72f6

Please sign in to comment.