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

hotfix/vmAvailabilitySetLimit: Fixed bug and added test case #696

Merged
merged 20 commits into from
Jul 30, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
0adfc2d
hotfix/vmAvailabilitySetLimit: Fixed bug and added test case
ali-imran7 May 10, 2021
f9d4e70
hotfix/vmAvailabilitySetLimit: Fixed bug and added test case
ali-imran7 May 10, 2021
902b368
Merge branch 'master' of https://github.com/aquasecurity/cloudsploit …
ali-imran7 Jun 1, 2021
2ee7782
Merge branch 'master' of https://github.com/ali-imran7/cloudsploit in…
AkhtarAmir Jun 1, 2021
7f55510
Merge branch 'hotfix/vmAvailabilitySetLimit' of https://github.com/al…
AkhtarAmir Jun 1, 2021
4e4027c
feature/AKD-132: Added Azure 'Premium SSD Disabled' plugin and test c…
ali-imran7 Jun 1, 2021
7989905
feature/AKD-189: Added Azure 'Always On Enabled' Plugin and test case…
ali-imran7 Jun 1, 2021
260ab2d
feature/managedNatGateways: Added Azure 'Managed NAT Gateway In Use' …
ali-imran7 Jun 1, 2021
a9fb406
feature/AKD-188: Added Azure 'Remote Debugging Disabled' Plugin and t…
ali-imran7 Jun 1, 2021
7e96693
feature/noGatewayConnections: Added Azure 'No Network Gateways Connec…
ali-imran7 Jun 1, 2021
aaf0aea
feature/gatewaysInUse: Added Azure 'Network Gateways Usage' Plugin an…
ali-imran7 Jun 1, 2021
5579c63
feature/AKD-149: Added Azure 'Disk Volumes BYOK Encryption Enabled' p…
ali-imran7 Jun 1, 2021
e51939f
feature/AKD-144: Added Azure 'Scale Sets Health Monitoring Enabled' p…
ali-imran7 Jun 1, 2021
44d7067
feature/AKD-143: Added Azure 'Virtual Machine Boot Diagnostics Enable…
ali-imran7 Jun 1, 2021
50f8efa
feature/AKD-141: Added Azure 'Virtual Machine Performance Diagnostics…
ali-imran7 Jun 1, 2021
85b0e66
feature/AKD-142: Added 'Azure Active Directory (AD) Authentication En…
ali-imran7 Jun 1, 2021
1eaec15
spec/virtualMachines: Added test cases for virtual machine plugins (#…
ali-imran7 Jun 1, 2021
29ba543
fix/approvedVmImage : Fixed spell errors (#666)
ali-imran7 Jun 1, 2021
c05c34e
feature/AKD-147: Added Azure 'Old VM Disk Snapshots' plugin and test …
ali-imran7 Jun 1, 2021
8c94f19
Merge branch 'master' of https://github.com/aquasecurity/cloudsploit …
ali-imran7 Jun 3, 2021
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
7 changes: 7 additions & 0 deletions collectors/azure/collector.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,13 @@ var calls = {
};

var postcalls = {
availabilitySets:{
listByResourceGroup: {
reliesOnPath: 'resourceGroups.list',
properties: ['id'],
url: 'https://management.azure.com/{id}/providers/Microsoft.Compute/availabilitySets?api-version=2020-12-01'
}
},
advancedThreatProtection: {
get: {
reliesOnPath: 'databaseAccounts.list',
Expand Down
2 changes: 1 addition & 1 deletion plugins/azure/sqlserver/autoFailoverGroupsEnabled.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ module.exports = {
if (!failoverGroups || failoverGroups.err || !failoverGroups.data) {
helpers.addResult(results, 3,
'Unable to query for auto-failover groups: ' + helpers.addError(failoverGroups), location, server.id);
continue;
continue;
}

if (failoverGroups.data.length) {
Expand Down
77 changes: 47 additions & 30 deletions plugins/azure/virtualmachines/vmAvailabilitySetLimit.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = {
more_info: 'Azure limits availability sets to certain numbers of resources. Exceeding those limits could prevent resources from launching.',
link: 'https://docs.microsoft.com/en-us/azure/virtual-machines/windows/overview',
recommended_action: 'Contact Azure support to increase the number of instances available',
apis: ['resourceGroups:list', 'availabilitySets:listBySubscription'],
apis: ['resourceGroups:list', 'availabilitySets:listByResourceGroup'],
settings: {
instance_limit_percentage_fail: {
name: 'Instance Limit Percentage Fail',
Expand Down Expand Up @@ -36,49 +36,66 @@ module.exports = {
var source = {};
var locations = helpers.locations(settings.govcloud);

async.each(locations.availabilitySets, function(location, rcb){
async.each(locations.resourceGroups, function(location, rcb){
var resourceGroups = helpers.addSource(cache, source,
['resourceGroups', 'list', location]);
giorod3 marked this conversation as resolved.
Show resolved Hide resolved

var availabilitySets = helpers.addSource(cache, source,
['availabilitySets', 'listBySubscription', location]);
if (!resourceGroups) return rcb();

if (!availabilitySets) return rcb();

if (availabilitySets.err || !availabilitySets.data) {
if (resourceGroups.err || !resourceGroups.data) {
helpers.addResult(results, 3,
'Unable to query Availability Sets: ' + helpers.addError(availabilitySets), location);
'Unable to query Resource Groups: ' + helpers.addError(resourceGroups), location);
return rcb();
}

if (!availabilitySets.data.length) {
helpers.addResult(results, 0, 'No existing Availability Sets', location);
if (!resourceGroups.data.length) {
helpers.addResult(results, 0, 'No existing Resource Groups', location);
return rcb();
}

var limits = {
'max-instances': 200
};
async.each(resourceGroups.data, function(resourceGroup, scb){
var availabilitySets = helpers.addSource(cache, source,
['availabilitySets', 'listByResourceGroup', location, resourceGroup.id]);

availabilitySets.data.forEach(availabilitySet => {
if (availabilitySet.virtualMachines) {
var vmInstances = availabilitySet.virtualMachines.length;
} else {
return;
if (!availabilitySets || availabilitySets.err || !availabilitySets.data) {
helpers.addResult(results, 3,
'Unable to query Availability Sets: ' + helpers.addError(availabilitySets), location);
return scb();
}

var percentage = Math.ceil((vmInstances / limits['max-instances']) * 100);
var returnMsg = 'Availability Set contains ' + vmInstances + ' of ' +
limits['max-instances'] + ' (' + percentage + '%) available instances';

if (percentage >= config.instance_limit_percentage_fail) {
helpers.addResult(results, 2, returnMsg, location, availabilitySet.id);
} else if (percentage >= config.instance_limit_percentage_warn) {
helpers.addResult(results, 1, returnMsg, location, availabilitySet.id);
} else {
helpers.addResult(results, 0, returnMsg, location, availabilitySet.id);
if (!availabilitySets.data.length) {
helpers.addResult(results, 0, 'No existing Availability Sets', location);
return scb();
}
});

rcb();
var limits = {
'max-instances': 200
};

availabilitySets.data.forEach(availabilitySet => {
if (availabilitySet.virtualMachines) {
var vmInstances = availabilitySet.virtualMachines.length;
} else {
return;
}

var percentage = Math.ceil((vmInstances / limits['max-instances']) * 100);
var returnMsg = 'Availability Set contains ' + vmInstances + ' of ' +
limits['max-instances'] + ' (' + percentage + '%) available instances';

if (percentage >= config.instance_limit_percentage_fail) {
helpers.addResult(results, 2, returnMsg, location, availabilitySet.id);
} else if (percentage >= config.instance_limit_percentage_warn) {
helpers.addResult(results, 1, returnMsg, location, availabilitySet.id);
} else {
helpers.addResult(results, 0, returnMsg, location, availabilitySet.id);
}
});

scb();
}, function(){
rcb();
});
}, function(){
callback(null, results, source);
});
Expand Down
147 changes: 147 additions & 0 deletions plugins/azure/virtualmachines/vmAvailabilitySetLimit.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
var expect = require('chai').expect;
var vmAvailabilitySetLimit = require('./vmAvailabilitySetLimit');

const resourceGroups = [
{
'id': '/subscriptions/123/resourceGroups/aqua-resource-group',
'name': 'aqua-resource-group',
'type': 'Microsoft.Resources/resourceGroups',
'location': 'eastus',
'tags': {},
'properties': {
'provisioningState': 'Succeeded'
}
}
];

const availabilitySets = [
{
'name': 'test-set',
'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Compute/availabilitySets/test-set',
'type': 'Microsoft.Compute/availabilitySets',
'location': 'eastus',
'tags': {},
'platformUpdateDomainCount': 5,
'platformFaultDomainCount': 2,
'virtualMachines': [
{
'id': '/subscriptions/123/resourceGroups/AQUA-RESOURCE-GROUP/providers/Microsoft.Compute/virtualMachines/test-vm-1'
}
],
'sku': {
'name': 'Aligned'
}
}
];

const createCache = (resourceGroups, availabilitySets) => {
let group = {};
let set = {};
if (resourceGroups) {
group['data'] = resourceGroups;
if (resourceGroups.length && availabilitySets) {
set[resourceGroups[0].id] = {
data: availabilitySets
};
}
}
return {
resourceGroups: {
list: {
'eastus': group
}
},
availabilitySets: {
listByResourceGroup: {
'eastus': set
}
}
};
};

describe('vmAvailabilitySetLimit', function() {
describe('run', function() {
it('should give passing result if No existing resource groups', function(done) {
const cache = createCache([]);
vmAvailabilitySetLimit.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(0);
expect(results[0].message).to.include('No existing Resource Groups');
expect(results[0].region).to.equal('eastus');
done();
});
});

it('should give unknown result if unable to query for resource groups', function(done) {
const cache = createCache();
vmAvailabilitySetLimit.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(3);
expect(results[0].message).to.include('Unable to query Resource Groups');
expect(results[0].region).to.equal('eastus');
done();
});
});

it('should give passing result if No existing Availability Sets', function(done) {
const cache = createCache([resourceGroups[0]], []);
vmAvailabilitySetLimit.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(0);
expect(results[0].message).to.include('No existing Availability Sets');
expect(results[0].region).to.equal('eastus');
done();
});
});

it('should give unknown result if unable to query for availability sets', function(done) {
const cache = createCache([resourceGroups[0]]);
vmAvailabilitySetLimit.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(3);
expect(results[0].message).to.include('Unable to query Availability Sets');
expect(results[0].region).to.equal('eastus');
done();
});
});

it('should give passing result if vm instances percentage are below the limits', function(done) {
const cache = createCache([resourceGroups[0]], [availabilitySets[0]]);
vmAvailabilitySetLimit.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(0);
expect(results[0].message).to.include('Availability Set contains 1 of 200 (1%) available instances');
expect(results[0].region).to.equal('eastus');
done();
});
});

it('should give failing results if number of vm instances has reached the fail limit', function(done) {
const cache = createCache([resourceGroups[0]], [availabilitySets[0]]);
const settings = {
instance_limit_percentage_fail: 1
};
vmAvailabilitySetLimit.run(cache, settings, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(2);
expect(results[0].message).to.include('Availability Set contains 1 of 200 (1%) available instances');
expect(results[0].region).to.equal('eastus');
done();
});
});

it('should give warn result if number of vm instances has reached the warn limit', function(done) {
const cache = createCache([resourceGroups[0]], [availabilitySets[0]]);
const settings = {
instance_limit_percentage_warn: 1
};
vmAvailabilitySetLimit.run(cache, settings, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(1);
expect(results[0].message).to.include('Availability Set contains 1 of 200 (1%) available instances');
expect(results[0].region).to.equal('eastus');
done();
});
});
});
});