forked from aquasecurity/cloudsploit
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SAAS-2470: Google Compute Engine Instance Preemptibility Disabled (aq…
…uasecurity#873) * Google Compute Engine Instance Preemptibility Disabled * renamed files Co-authored-by: AkhtarAmir <[email protected]>
- Loading branch information
1 parent
0e2a5d1
commit e566913
Showing
3 changed files
with
209 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
var async = require('async'); | ||
var helpers = require('../../../helpers/google'); | ||
|
||
module.exports = { | ||
title: 'Instance Preemptibility Disabled', | ||
category: 'Compute', | ||
description: 'Ensure that preemptible Virtual Machine instances do not exist.', | ||
more_info: 'Preemptible instances are excess Compute Engine capacity, so their availability varies with usage. Compute Engine can terminate preemptible instances if it requires access to these resources for other tasks.', | ||
link: 'https://cloud.google.com/compute/docs/instances/preemptible', | ||
recommended_action: 'Ensure that your Google Compute Engine VM instances are not preemptible.', | ||
apis: ['instances:compute:list', 'projects:get'], | ||
|
||
run: function(cache, settings, callback) { | ||
var results = []; | ||
var source = {}; | ||
var regions = helpers.regions(); | ||
|
||
let projects = helpers.addSource(cache, source, | ||
['projects','get', 'global']); | ||
|
||
if (!projects || projects.err || !projects.data || !projects.data.length) { | ||
helpers.addResult(results, 3, | ||
'Unable to query for projects: ' + helpers.addError(projects), 'global', null, null, (projects) ? projects.err : null); | ||
return callback(null, results, source); | ||
} | ||
|
||
var project = projects.data[0].name; | ||
async.each(regions.instances.compute, (region, rcb) => { | ||
var noInstances = []; | ||
var zones = regions.zones; | ||
async.each(zones[region], function(zone, zcb) { | ||
var instances = helpers.addSource(cache, source, | ||
['instances', 'compute','list', zone ]); | ||
|
||
if (!instances) return zcb(); | ||
|
||
if (instances.err || !instances.data) { | ||
helpers.addResult(results, 3, 'Unable to query compute instances', region, null, null, instances.err); | ||
return zcb(); | ||
} | ||
|
||
if (!instances.data.length) { | ||
noInstances.push(zone); | ||
return zcb(); | ||
} | ||
|
||
instances.data.forEach(instance => { | ||
let resource = helpers.createResourceName('instances', instance.name, project, 'zone', zone); | ||
if (instance.scheduling && instance.scheduling.preemptible) { | ||
helpers.addResult(results, 2, | ||
'VM Instance is preemptible', region, resource); | ||
} else { | ||
helpers.addResult(results, 0, | ||
'VM Instance is not preemptible', region, resource); | ||
} | ||
}); | ||
zcb(); | ||
}, function() { | ||
if (noInstances.length) { | ||
helpers.addResult(results, 0, `No instances found in following zones: ${noInstances.join(', ')}`, region); | ||
} | ||
rcb(); | ||
}); | ||
}, function() { | ||
callback(null, results, source); | ||
}); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
var assert = require('assert'); | ||
var expect = require('chai').expect; | ||
var plugin = require('./instancePreemptibility'); | ||
|
||
const createCache = (instanceData, error) => { | ||
return { | ||
instances: { | ||
compute: { | ||
list: { | ||
'us-central1-a': { | ||
data: instanceData, | ||
err: error | ||
} | ||
} | ||
} | ||
}, | ||
projects: { | ||
get: { | ||
'global': { | ||
data: 'tets-proj' | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
|
||
describe('instancePreemptibility', function () { | ||
describe('run', function () { | ||
|
||
it('should give unknown if an instance error occurs', function (done) { | ||
const callback = (err, results) => { | ||
expect(results.length).to.be.above(0); | ||
expect(results[0].status).to.equal(3); | ||
expect(results[0].message).to.include('Unable to query compute instances'); | ||
expect(results[0].region).to.equal('us-central1'); | ||
done() | ||
}; | ||
|
||
const cache = createCache( | ||
[], | ||
['error'] | ||
); | ||
|
||
plugin.run(cache, {}, callback); | ||
}); | ||
|
||
it('should pass no VM Instances', function (done) { | ||
const callback = (err, results) => { | ||
expect(results.length).to.be.above(0); | ||
expect(results[0].status).to.equal(0); | ||
expect(results[0].message).to.include('No instances found'); | ||
expect(results[0].region).to.equal('us-central1'); | ||
done() | ||
}; | ||
|
||
const cache = createCache( | ||
[], | ||
null | ||
); | ||
|
||
plugin.run(cache, {}, callback); | ||
}); | ||
|
||
it('should fail if VM instance is preemptible', function (done) { | ||
const callback = (err, results) => { | ||
expect(results.length).to.be.above(0); | ||
expect(results[0].status).to.equal(2); | ||
expect(results[0].message).to.include('VM Instance is preemptible'); | ||
expect(results[0].region).to.equal('us-central1'); | ||
done() | ||
}; | ||
|
||
const cache = createCache( | ||
[ | ||
{ | ||
"kind": "compute#instance", | ||
"id": "53523", | ||
"creationTimestamp": "2019-10-04T13:44:44.117-07:00", | ||
"name": "instance-3", | ||
"description": "", | ||
"tags": { | ||
"fingerprint": "42WmSpB8rSM=" | ||
}, | ||
"machineType": "https://www.googleapis.com/compute/v1/projects/rosy-booth-253119/zones/us-central1-a/machineTypes/n1-standard-1", | ||
"status": "RUNNING", | ||
"zone": "https://www.googleapis.com/compute/v1/projects/rosy-booth-253119/zones/us-central1-a", | ||
"canIpForward": true, | ||
"selfLink": "https://www.googleapis.com/compute/v1/projects/rosy-booth-253119/zones/us-central1-a/instances/instance-3", | ||
"scheduling": { | ||
"onHostMaintenance": "MIGRATE", | ||
"automaticRestart": false, | ||
"preemptible": true | ||
} | ||
} | ||
], | ||
null | ||
); | ||
|
||
plugin.run(cache, {}, callback); | ||
}) | ||
|
||
it('should pass if VM instance is not preemptible', function (done) { | ||
const callback = (err, results) => { | ||
expect(results.length).to.be.above(0); | ||
expect(results[0].status).to.equal(0); | ||
expect(results[0].message).to.equal('VM Instance is not preemptible'); | ||
expect(results[0].region).to.equal('us-central1'); | ||
done() | ||
}; | ||
|
||
const cache = createCache( | ||
[ | ||
{ | ||
"kind": "compute#instance", | ||
"id": "45444", | ||
"creationTimestamp": "2019-09-25T14:05:30.014-07:00", | ||
"name": "instance-2", | ||
"description": "", | ||
"tags": { | ||
"fingerprint": "42WmSpB8rSM=" | ||
}, | ||
"machineType": "https://www.googleapis.com/compute/v1/projects/rosy-booth-253119/zones/us-central1-a/machineTypes/g1-small", | ||
"status": "RUNNING", | ||
"zone": "https://www.googleapis.com/compute/v1/projects/rosy-booth-253119/zones/us-central1-a", | ||
"canIpForward": false, | ||
"selfLink": "https://www.googleapis.com/compute/v1/projects/rosy-booth-253119/zones/us-central1-a/instances/instance-2", | ||
"scheduling": { | ||
"onHostMaintenance": "MIGRATE", | ||
"automaticRestart": true, | ||
"preemptible": false | ||
} | ||
} | ||
] | ||
); | ||
|
||
plugin.run(cache, {}, callback); | ||
}) | ||
|
||
}) | ||
}); |