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.
feature-request: Added 'Workspaces IP Access Control' plugin and test…
… cases (aquasecurity#451) * Added 'Workspaces IP Access Control' plugin and test cases * Accommodated PR changes to add extar checks
- Loading branch information
1 parent
ee246b2
commit 955a4e3
Showing
4 changed files
with
307 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
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,87 @@ | ||
var async = require('async'); | ||
var helpers = require('../../../helpers/aws'); | ||
|
||
module.exports = { | ||
title: 'Workspaces IP Access Control', | ||
category: 'Workspaces', | ||
description: 'Ensures enforced IP Access Control on Workspaces', | ||
more_info: 'Checking the existence of IP Access control on Workspaces and ensuring that no Workspaces are open', | ||
link: 'https://docs.aws.amazon.com/workspaces/latest/adminguide/amazon-workspaces-ip-access-control-groups.html', | ||
recommended_action: 'Enable proper IP Access Controls for all workspaces', | ||
apis: ['WorkSpaces:describeWorkspaces', 'WorkSpaces:describeWorkspaceDirectories', 'WorkSpaces:describeIpGroups', 'STS:getCallerIdentity'], | ||
|
||
run: function(cache, settings, callback) { | ||
var results = []; | ||
var source = {}; | ||
|
||
var regions = helpers.regions(settings); | ||
var acctRegion = helpers.defaultRegion(settings); | ||
var awsOrGov = helpers.defaultPartition(settings); | ||
|
||
var accountId = helpers.addSource(cache, source, ['sts', 'getCallerIdentity', acctRegion, 'data']); | ||
|
||
const enabledString = 'IP Access Control is enabled'; | ||
const enabledButAllowsWorldString = 'IP Access Control is enabled but 0.0.0.0/0 is allowed'; | ||
const disabledString = 'IP Access Control is disabled'; | ||
|
||
async.each(regions.workspaces, function(region, rcb){ | ||
var listWorkspaces = helpers.addSource(cache, source, ['workspaces', 'describeWorkspaces', region, 'data']); | ||
var listDirectories = helpers.addSource(cache, source, ['workspaces', 'describeWorkspaceDirectories', region, 'data']); | ||
var listIPGroups = helpers.addSource(cache, source, ['workspaces', 'describeIpGroups', region, 'data']); | ||
|
||
if (!listWorkspaces) { | ||
return rcb(); | ||
} | ||
|
||
if (listWorkspaces.err) { | ||
helpers.addResult( | ||
results, 3, 'Unable to query for WorkSpaces information: ' + helpers.addError(listWorkspaces), region); | ||
return rcb(); | ||
} | ||
|
||
if (!listWorkspaces.length) { | ||
helpers.addResult( | ||
results, 0, 'No Workspaces found.', region); | ||
return rcb(); | ||
} | ||
|
||
for (var workspace of listWorkspaces) { | ||
var arn = 'arn:' + awsOrGov + ':workspaces:' + region + ':' + accountId + ':workspace/' + workspace.WorkspaceId; | ||
|
||
if (!workspace.DirectoryId){ | ||
helpers.addResult(results, 2, disabledString, region, arn); | ||
continue; | ||
} | ||
|
||
var workspaceDirectory = listDirectories.find(directory => directory.DirectoryId === workspace.DirectoryId); | ||
|
||
if (workspaceDirectory && workspaceDirectory.ipGroupIds) { | ||
let openToEverything = false; | ||
for (var workspaceIPGroup of workspaceDirectory.ipGroupIds){ | ||
var ipGroup = listIPGroups.find(o => o.groupId === workspaceIPGroup); | ||
|
||
if (ipGroup && ipGroup.userRules) { | ||
if (ipGroup.userRules.find(o => o.ipRule === '0.0.0.0/0')) { | ||
openToEverything = true; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
if (openToEverything){ | ||
helpers.addResult(results, 2, enabledButAllowsWorldString, region, arn); | ||
} else { | ||
helpers.addResult(results, 0, enabledString, region, arn); | ||
} | ||
} else { | ||
helpers.addResult(results, 2, disabledString, region, arn); | ||
} | ||
} | ||
|
||
return rcb(); | ||
|
||
}, function(){ | ||
callback(null, results, source); | ||
}); | ||
} | ||
}; |
210 changes: 210 additions & 0 deletions
210
plugins/aws/workspaces/workspacesIpAccessControl.spec.js
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,210 @@ | ||
var expect = require("chai").expect; | ||
var workspacesIpAccessControl = require("./workspacesIpAccessControl.js") | ||
|
||
|
||
const errorWorkspaces = (statement) => { | ||
return {workspaces:{ | ||
describeWorkspaces: { | ||
"us-east-1":{ | ||
}, | ||
}, | ||
}, | ||
} | ||
}; | ||
|
||
const noWorkspaces = (statement) => { | ||
return {workspaces:{ | ||
describeWorkspaces: { | ||
"us-east-1":{ | ||
data: [] | ||
}, | ||
}, | ||
}, | ||
} | ||
}; | ||
|
||
const testWorkspaces = (statement) => { | ||
return {workspaces:{ | ||
describeWorkspaces: { | ||
"us-east-1":{ | ||
data: [ | ||
{ | ||
WorkspaceId: "test01", | ||
DirectoryId: "d-01", | ||
}, | ||
{ | ||
WorkspaceId: "test02", | ||
DirectoryId: "d-02", | ||
}, | ||
] | ||
}, | ||
}, | ||
describeWorkspaceDirectories: { | ||
"us-east-1":{ | ||
data:[ | ||
{ | ||
DirectoryId: "d-01", | ||
DirectoryName: "corp.amazonworkspaces.com", | ||
CustomerUserName: "Administrator", | ||
ipGroupIds: [ | ||
"ipgroup01" | ||
] | ||
}, | ||
{ | ||
DirectoryId: "d-02", | ||
DirectoryName: "corp.amazonworkspaces.com", | ||
CustomerUserName: "Administrator", | ||
ipGroupIds: [ | ||
"ipgroup02", | ||
"ipgroup03" | ||
] | ||
} | ||
] | ||
} | ||
}, | ||
describeIpGroups:{ | ||
"us-east-1":{ | ||
data: [ | ||
{ | ||
"groupId": "ipgroup01", | ||
"groupName": "testIPControlAccess" | ||
}, | ||
{ | ||
"groupId": "ipgroup02", | ||
"groupName": "testIPControlAccess" | ||
}, | ||
{ | ||
"groupId": "ipgroup03", | ||
"groupName": "testIPControlAccess", | ||
"userRules": [ | ||
{ | ||
"ipRule": "192.45.32.10", | ||
"ruleDesc": "Open for one." | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} | ||
}, | ||
} | ||
}; | ||
|
||
const testWorkspaces2 = (statement) => { | ||
return {workspaces:{ | ||
describeWorkspaces: { | ||
"us-east-1":{ | ||
data: [ | ||
{ | ||
WorkspaceId: "test01", | ||
DirectoryId: "d-01", | ||
}, | ||
{ | ||
WorkspaceId: "test02", | ||
DirectoryId: "d-02", | ||
}, | ||
] | ||
}, | ||
}, | ||
describeWorkspaceDirectories: { | ||
"us-east-1":{ | ||
data:[ | ||
{ | ||
DirectoryId: "d-01", | ||
DirectoryName: "corp.amazonworkspaces.com", | ||
CustomerUserName: "Administrator", | ||
ipGroupIds: [ | ||
"ipgroup01" | ||
] | ||
}, | ||
{ | ||
DirectoryId: "d-02", | ||
DirectoryName: "corp.amazonworkspaces.com", | ||
CustomerUserName: "Administrator", | ||
ipGroupIds: [ | ||
"ipgroup02" | ||
] | ||
} | ||
] | ||
} | ||
}, | ||
describeIpGroups:{ | ||
"us-east-1":{ | ||
data: [ | ||
{ | ||
"groupId": "ipgroup01", | ||
"groupName": "testIPControlAccess" | ||
}, | ||
{ | ||
"groupId": "ipgroup02", | ||
"groupName": "testIPControlAccess", | ||
"userRules": [ | ||
{ | ||
"ipRule": "0.0.0.0/0", | ||
"ruleDesc": "Open for all" | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} | ||
}, | ||
} | ||
}; | ||
|
||
|
||
describe("workspacesIPAccessControl", function () { | ||
describe("run", function () { | ||
it("should give a general error if it can not get workspaces", function (done) { | ||
const settings = {}; | ||
const cache = errorWorkspaces(); | ||
const callback = (err, results) => { | ||
expect(results.length).to.equal(0) | ||
}; | ||
workspacesIpAccessControl.run(cache, settings, callback); | ||
done(); | ||
}); | ||
|
||
it("should give an output of no available workspaces", function (done) { | ||
const settings = {}; | ||
const cache = noWorkspaces(); | ||
|
||
const callback = (err, results) => { | ||
expect(results.length).to.equal(1); | ||
expect(results[0].status).to.equal(0); | ||
}; | ||
|
||
workspacesIpAccessControl.run(cache, settings, callback); | ||
done(); | ||
}); | ||
|
||
it("should give IP access controls on both the workspaces", function (done) { | ||
const settings = {}; | ||
const cache = testWorkspaces(); | ||
|
||
const callback = (err, results) => { | ||
expect(results.length).to.equal(2) | ||
expect(results[0].status).to.equal(0); | ||
expect(results[1].status).to.equal(0); | ||
}; | ||
|
||
workspacesIpAccessControl.run(cache, settings, callback); | ||
done(); | ||
}) | ||
|
||
it("should give IP access control enabled on one and no IP access control on the other", function (done) { | ||
const settings = {}; | ||
const cache = testWorkspaces2(); | ||
|
||
const callback = (err, results) => { | ||
expect(results.length).to.equal(2); | ||
expect(results[0].status).to.equal(0); | ||
expect(results[1].status).to.equal(2); | ||
}; | ||
|
||
|
||
workspacesIpAccessControl.run(cache, settings, callback); | ||
done(); | ||
}) | ||
}) | ||
}) |