Skip to content
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

Feature/ec2 plugin mark launch wizard security groups #1

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
});
}
}
}