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.
Google Compute Engine OS Login 2FA Enabled (aquasecurity#878)
Co-authored-by: dipsubha06 <[email protected]>
- Loading branch information
1 parent
d4c890c
commit 7b4fb9f
Showing
3 changed files
with
198 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,85 @@ | ||
var async = require('async'); | ||
var helpers = require('../../../helpers/google'); | ||
|
||
module.exports = { | ||
title: 'OS Login 2FA Enabled', | ||
category: 'Compute', | ||
description: 'Ensure that Virtual Machines instances have OS logic feature enabled and configured with Two-Factor Authentication.', | ||
more_info: 'Enable OS login Two-Factor Authentication (2FA) to add an additional security layer to your VM instances. The risk of your VM instances getting attcked is reduced significantly if 2FA is enabled.', | ||
link: 'https://cloud.google.com/compute/docs/oslogin/setup-two-factor-authentication', | ||
recommended_action: 'Set enable-oslogin-2fa to true in custom metadata for the instance.', | ||
apis: ['instances:compute:list', 'projects:get'], | ||
compliance: { | ||
pci: 'PCI recommends implementing additional security features for ' + | ||
'any required service. This includes using secured technologies ' + | ||
'such as SSH.' | ||
}, | ||
|
||
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 zones = regions.zones; | ||
var noInstances = []; | ||
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 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); | ||
let isEnabled = false; | ||
|
||
if (instance.metadata && instance.metadata.items && instance.metadata.items.length) { | ||
|
||
if (instance.metadata.items.find(item => (item.key && item.key.toLowerCase() === 'enable-oslogin-2fa' && | ||
item.value && item.value.toLowerCase() === 'true'))) { | ||
isEnabled = true; | ||
} | ||
} | ||
|
||
if (isEnabled) { | ||
helpers.addResult(results, 0, | ||
'OS Login 2FA is enabled for the the instance', region, resource); | ||
} else { | ||
helpers.addResult(results, 2, | ||
'OS Login 2FA is not enabled for the the instance', 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,112 @@ | ||
var expect = require('chai').expect; | ||
var plugin = require('./osLogin2FAEnabled'); | ||
|
||
const createCache = (instanceData, error) => { | ||
return { | ||
instances: { | ||
compute: { | ||
list: { | ||
'us-central1-a': { | ||
data: instanceData, | ||
err: error | ||
} | ||
} | ||
} | ||
}, | ||
projects: { | ||
get: { | ||
'global': { | ||
data: 'testproj' | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
|
||
describe('osLogin2FAEnabled', 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 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([]); | ||
|
||
plugin.run(cache, {}, callback); | ||
}); | ||
|
||
it('should fail when OS Login 2FA is not enabled', 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('OS Login 2FA is not enabled for the the instance'); | ||
expect(results[0].region).to.equal('us-central1'); | ||
done() | ||
}; | ||
|
||
const cache = createCache( | ||
[ | ||
{ | ||
id: "17198672", | ||
name: "testing-instance", | ||
zone: "https://www.googleapis.com/compute/v1/projects/test-dev/zones/us-central1-a", | ||
metadata: { items: [] } | ||
} | ||
] | ||
); | ||
|
||
plugin.run(cache, {}, callback); | ||
}) | ||
|
||
it('should pass when OS Login 2FA is enabled', 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('OS Login 2FA is enabled for the the instance'); | ||
expect(results[0].region).to.equal('us-central1'); | ||
done() | ||
}; | ||
|
||
const cache = createCache( | ||
[ | ||
{ | ||
id: "321087009587", | ||
name: "testing-instance2", | ||
zone: "https://www.googleapis.com/compute/v1/projects/test-dev/zones/us-central1-a", | ||
metadata: { | ||
items: [ | ||
{ key: 'enable-oslogin', value: 'TRUE' }, | ||
{ key: 'enable-oslogin-2fa', value: 'TRUE' } | ||
] | ||
} | ||
} | ||
] | ||
); | ||
|
||
plugin.run(cache, {}, callback); | ||
}) | ||
|
||
}) | ||
}) |