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: Added collector for Alibaba cloud (aquasecurity#683)
* SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation * Added vpcEndpointAcceptance plugin and spec file * SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation * Added plugin and spec file for launch wizard security groups * Refactored code in plaintextParameters plugin and spec file * SPLOIT-113: Updated custom settings * Made PR requested changes * SPLOIT-113: Added regex to check if NoEcho is enabled * Accommodated PR changes * Fixed eslint issues * Update exports.js * Fixed eslint issues * Update index.js * Update index.js * Added cloudformation in china and gov regions * Accomodated PR changes * Updated status in result of failure * SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation * Added plugin and spec file for launch wizard security groups * Added vpcEndpointAcceptance plugin and spec file * Refactored code in plaintextParameters plugin and spec file * SPLOIT-113: Updated custom settings * Made PR requested changes * SPLOIT-113: Added regex to check if NoEcho is enabled * Accommodated PR changes * Fixed eslint issues * Update index.js * Update index.js * Accomodated PR changes * Updated status in result of failure * SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation * Added plugin and spec file for launch wizard security groups * Added vpcEndpointAcceptance plugin and spec file * Refactored code in plaintextParameters plugin and spec file * SPLOIT-113: Updated custom settings * Made PR requested changes * SPLOIT-113: Added regex to check if NoEcho is enabled * Accommodated PR changes * Fixed eslint issues * Update index.js * Update index.js * Accomodated PR changes * Updated status in result of failure * SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation * SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation * Added plugin and spec file for launch wizard security groups * Added vpcEndpointAcceptance plugin and spec file * Refactored code in plaintextParameters plugin and spec file * SPLOIT-113: Updated custom settings * Made PR requested changes * SPLOIT-113: Added regex to check if NoEcho is enabled * Accommodated PR changes * Fixed eslint issues * Update exports.js * Update index.js * Update index.js * Accomodated PR changes * Updated status in result of failure * Removed unnecesary rebase changes * Added superlinter * Added scans ci * Updated Ci file * Updated Node version in CI file * removed spech check command * Delete scan_ci.yml * Added spellcheck * Azure MySQL Enforce SSL Connection remediated * Modified index and engine files to fix azure remediation invalid token issue * Update engine.js * Added new argument for cloud * Modified index for Alibaba cloud * Added logic for Alibaba collector * Modified collector
- Loading branch information
1 parent
7bc98ad
commit 0b1e846
Showing
6 changed files
with
429 additions
and
13 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,319 @@ | ||
/********************* | ||
Collector - The collector will query Alibaba APIs for the information required | ||
to run the CloudSploit scans. This data will be returned in the callback | ||
as a JSON object. | ||
Arguments: | ||
- AlibabaConfig: If using an access key/secret, pass in the config object. Pass null if not. | ||
- settings: custom settings for the scan. Properties: | ||
- skip_regions: (Optional) List of regions to skip | ||
- api_calls: (Optional) If provided, will only query these APIs. | ||
- Example: | ||
{ | ||
"skip_regions": ["cn-hangzhou", "cn-shanghai"], | ||
"api_calls": ["ECS:DescribeInstances", "VPC:DescribeFlowLogs"] | ||
} | ||
- callback: Function to call when the collection is complete | ||
*********************/ | ||
|
||
var alicloud = require('@alicloud/pop-core'); | ||
var async = require('async'); | ||
var helpers = require(__dirname + '/../../helpers/alibaba'); | ||
|
||
var regions = helpers.regions(); | ||
|
||
var regionEndpointMap = {}; | ||
|
||
var globalServices = [ | ||
'RAM' | ||
]; | ||
|
||
var calls = { | ||
ECS: { | ||
DescribeInstances: { | ||
property: 'Instances', | ||
subProperty: 'Instance', | ||
paginate: 'NextToken', | ||
apiVersion: '2014-05-26' | ||
} | ||
}, | ||
RAM: { | ||
ListPolicies: { | ||
property: 'Policies', | ||
subProperty: 'Policy', | ||
apiVersion: '2015-05-01', | ||
paginate: 'Marker' | ||
}, | ||
ListUsers: { | ||
property: 'Users', | ||
subProperty: 'User', | ||
apiVersion: '2015-05-01', | ||
paginate: 'Marker' | ||
} | ||
}, | ||
GBDB: { | ||
DescribeDBInstances: { | ||
property: 'Items', | ||
subProperty: 'DBInstance', | ||
apiVersion: '2015-05-01', | ||
paginate: 'Pages' | ||
} | ||
}, | ||
VPC: { | ||
DescribeVpcs: { | ||
property: 'Vpcs', | ||
subProperty: 'Vpc', | ||
apiVersion: '2016-04-28', | ||
paginate: 'Pages' | ||
}, | ||
DescribeVSwitches: { | ||
property: 'VSwitches', | ||
subProperty: 'VSwitch', | ||
apiVersion: '2016-04-28', | ||
paginate: 'Pages' | ||
} | ||
}, | ||
RDS: { | ||
DescribeDBInstances: { | ||
property: 'Items', | ||
subProperty: 'DBInstance', | ||
apiVersion: '2014-08-15', | ||
paginate: 'Pages' | ||
} | ||
}, | ||
POLARDB: { | ||
DescribeDBClusters: { | ||
property: 'Items', | ||
subProperty: 'DBCluster', | ||
apiVersion: '2017-08-01', | ||
paginate: 'Pages' | ||
} | ||
} | ||
}; | ||
|
||
var postcalls = [ | ||
{ | ||
ECS: { | ||
DescribeInstanceStatus: { | ||
reliesOnService: 'ecs', | ||
reliesOnCall: 'DescribeInstances', | ||
filterKey: ['InstanceId'], | ||
filterValue: ['InstanceId'], | ||
apiVersion: '2014-05-26' | ||
} | ||
}, | ||
RAM: { | ||
GetPolicy: { | ||
reliesOnService: 'ram', | ||
reliesOnCall: 'ListPolicies', | ||
filterKey: ['PolicyName', 'PolicyType'], | ||
filterValue: ['PolicyName', 'PolicyType'], | ||
resultFilter: 'DefaultPolicyVersion', | ||
apiVersion: '2015-05-01' | ||
}, | ||
GetUser: { | ||
reliesOnService: 'ram', | ||
reliesOnCall: 'ListUsers', | ||
filterKey: ['UserName'], | ||
filterValue: ['UserName'], | ||
resultFilter: 'User', | ||
apiVersion: '2015-05-01' | ||
} | ||
} | ||
} | ||
]; | ||
|
||
var collect = function(AlibabaConfig, settings, callback) { | ||
if (settings.gather) { | ||
return callback(null, calls, postcalls); | ||
} | ||
|
||
var collection = {}; | ||
|
||
async.eachOfLimit(calls, 10, function(call, service, serviceCb) { | ||
let serviceLower = service.toLowerCase(); | ||
if (!collection[serviceLower]) collection[serviceLower] = {}; | ||
|
||
async.eachOfLimit(call, 15, function(callObj, callKey, callCb) { | ||
if (settings.api_calls && settings.api_calls.indexOf(service + ':' + callKey) === -1) return callCb(); | ||
if (!collection[serviceLower][callKey]) collection[serviceLower][callKey] = {}; | ||
|
||
let callRegions = regions[serviceLower]; | ||
let requestOption = { method: callObj.method || 'POST' }; | ||
|
||
async.eachLimit(callRegions, helpers.MAX_REGIONS_AT_A_TIME, function(region, regionCb) { | ||
if (settings.skip_regions && | ||
settings.skip_regions.indexOf(region) > -1 && | ||
globalServices.indexOf(service) === -1) return regionCb(); | ||
if (!collection[serviceLower][callKey][region]) collection[serviceLower][callKey][region] = {}; | ||
|
||
let LocalAlibabaConfig = JSON.parse(JSON.stringify(AlibabaConfig)); | ||
|
||
let endpoint = (regionEndpointMap[serviceLower] && regionEndpointMap[serviceLower].includes(region)) ? | ||
`https://${serviceLower}.${region}.aliyuncs.com` : `https://${serviceLower}.aliyuncs.com`; | ||
LocalAlibabaConfig['endpoint'] = endpoint; | ||
LocalAlibabaConfig['apiVersion'] = callObj.apiVersion; | ||
let client = new alicloud(LocalAlibabaConfig); | ||
let paginating = false; | ||
let pageNumber = 1; | ||
var clientCb = function(err, data) { | ||
if (err) collection[serviceLower][callKey][region].err = err; | ||
if (!data) return regionCb(); | ||
if (callObj.property && !data[callObj.property]) return regionCb(); | ||
if (callObj.subProperty && !data[callObj.property][callObj.subProperty]) return regionCb(); | ||
|
||
var dataToAdd = callObj.subProperty ? data[callObj.property][callObj.subProperty] : data[callObj.property]; | ||
|
||
if (paginating) { | ||
collection[serviceLower][callKey][region].data = collection[serviceLower][callKey][region].data.concat(dataToAdd); | ||
} else { | ||
collection[serviceLower][callKey][region].data = dataToAdd; | ||
} | ||
|
||
if (callObj.paginate && callObj.paginate == 'Pages' && settings.paginate) { | ||
if (data['PageNumber'] && data['PageSize'] && data['TotalCount']) { | ||
let pageSize = callObj.pageSize || parseInt(data['PageSize']); | ||
let totalCount = parseInt(data['TotalCount']); | ||
|
||
if ((pageNumber*pageSize) < totalCount) { | ||
paginating = true; | ||
pageNumber += 1; | ||
let paginateParams = { PageNumber: pageNumber, PageSize: pageSize}; | ||
return execute(null, paginateParams); | ||
} | ||
} | ||
} | ||
|
||
var nextToken = callObj.paginate; | ||
if (settings.paginate && nextToken && data[nextToken]) { | ||
paginating = true; | ||
var paginateProp = callObj.paginateReqProp ? callObj.paginateReqProp : nextToken; | ||
return execute([paginateProp, data[nextToken]]); | ||
} | ||
|
||
if (callObj.rateLimit) { | ||
setTimeout(function() { | ||
regionCb(); | ||
}, callObj.rateLimit); | ||
} else { | ||
regionCb(); | ||
} | ||
}; | ||
|
||
function execute(nextToken, paginateParams) { | ||
let localParams = JSON.parse(JSON.stringify(callObj.params || {})); | ||
localParams['RegionId'] = region; | ||
if (nextToken) localParams[nextToken[0]] = nextToken[1]; | ||
else if (paginateParams) localParams = {...localParams, ...paginateParams}; | ||
|
||
client.request(callKey, localParams, requestOption).then((result) => { | ||
clientCb(null, result); | ||
}, (err) => { | ||
clientCb(err); | ||
}); | ||
} | ||
|
||
execute(); | ||
}, function() { | ||
callCb(); | ||
}); | ||
}, function() { | ||
serviceCb(); | ||
}); | ||
}, function() { | ||
async.eachSeries(postcalls, function(postcallObj, postcallCb) { | ||
async.eachOfLimit(postcallObj, 10, function(serviceObj, service, serviceCb) { | ||
var serviceLower = service.toLowerCase(); | ||
if (!collection[serviceLower]) collection[serviceLower] = {}; | ||
|
||
async.eachOfLimit(serviceObj, 1, function(callObj, callKey, callCb) { | ||
if (settings.api_calls && settings.api_calls.indexOf(service + ':' + callKey) === -1) return callCb(); | ||
if (!collection[serviceLower][callKey]) collection[serviceLower][callKey] = {}; | ||
|
||
var requestOption = { method: callObj.method || 'POST' }; | ||
async.eachLimit(regions[serviceLower], helpers.MAX_REGIONS_AT_A_TIME, function(region, regionCb) { | ||
if (settings.skip_regions && | ||
settings.skip_regions.indexOf(region) > -1 && | ||
globalServices.indexOf(service) === -1) return regionCb(); | ||
if (!collection[serviceLower][callKey][region]) collection[serviceLower][callKey][region] = {}; | ||
|
||
if (callObj.reliesOnService && !collection[callObj.reliesOnService]) return regionCb(); | ||
|
||
if (callObj.reliesOnCall && | ||
(!collection[callObj.reliesOnService] || | ||
!collection[callObj.reliesOnService][callObj.reliesOnCall] || | ||
!collection[callObj.reliesOnService][callObj.reliesOnCall][region] || | ||
!collection[callObj.reliesOnService][callObj.reliesOnCall][region].data || | ||
!collection[callObj.reliesOnService][callObj.reliesOnCall][region].data.length)) | ||
return regionCb(); | ||
|
||
let LocalAlibabaConfig = JSON.parse(JSON.stringify(AlibabaConfig)); | ||
|
||
LocalAlibabaConfig['endpoint'] = (regionEndpointMap[serviceLower] && regionEndpointMap[serviceLower].includes(region)) ? | ||
`https://${serviceLower}.${region}.aliyuncs.com` : `https://${serviceLower}.aliyuncs.com`; | ||
LocalAlibabaConfig['apiVersion'] = callObj.apiVersion; | ||
let client = new alicloud(LocalAlibabaConfig); | ||
|
||
async.eachLimit(collection[callObj.reliesOnService][callObj.reliesOnCall][region].data, 10, function(val, valCb) { | ||
let resultKey = callObj.filterValue[0]; | ||
collection[serviceLower][callKey][region][val[resultKey]] = {}; | ||
|
||
let params = {}; | ||
if (callObj.params) params = JSON.parse(JSON.stringify(callObj.params)); | ||
|
||
for (let key in callObj.filterKey) { | ||
params[callObj.filterKey[key]] = val[callObj.filterValue[key]]; | ||
} | ||
|
||
params['RegionId'] = region; | ||
|
||
var requestCb = function(err, data) { | ||
if (err) collection[serviceLower][callKey][region][val[resultKey]].err = err; | ||
if (!data) return valCb(); | ||
|
||
collection[serviceLower][callKey][region][val[resultKey]].data = (callObj.resultFilter && data[callObj.resultFilter]) ? | ||
data[callObj.resultFilter] : data; | ||
|
||
if (callObj.rateLimit) { | ||
setTimeout(function() { | ||
valCb(); | ||
}, callObj.rateLimit); | ||
} else { | ||
valCb(); | ||
} | ||
}; | ||
|
||
var execute = function() { | ||
client.request(callKey, params, requestOption).then((result) => { | ||
requestCb(null, result); | ||
}, (err) => { | ||
requestCb(err); | ||
}); | ||
}; | ||
|
||
execute(); | ||
}, function() { | ||
if (callObj.rateLimit) { | ||
setTimeout(function() { | ||
regionCb(); | ||
}, callObj.rateLimit); | ||
} else { | ||
regionCb(); | ||
} | ||
}); | ||
}, function() { | ||
callCb(); | ||
}); | ||
}, function() { | ||
serviceCb(); | ||
}); | ||
}, function() { | ||
postcallCb(); | ||
}); | ||
}, function() { | ||
callback(null, collection); | ||
}); | ||
}); | ||
}; | ||
|
||
module.exports = collect; |
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,26 @@ | ||
'use strict'; | ||
|
||
var fs = require('fs'); | ||
var path = require('path'); | ||
var collectors = {}; | ||
|
||
var directories = fs.readdirSync(__dirname).filter(function(file) { | ||
return fs.statSync(path.join(__dirname, file)).isDirectory(); | ||
}); | ||
|
||
directories.forEach(function(directory) { | ||
collectors[directory] = {}; | ||
|
||
fs | ||
.readdirSync(__dirname + '/' + directory) | ||
.filter(function(file) { | ||
return (file.indexOf('.') !== 0); | ||
}) | ||
.forEach(function(file) { | ||
var collector = require(path.join(__dirname + '/' + directory, file)); | ||
var name = file.substring(0, file.indexOf('.js')); | ||
collectors[directory][name] = collector; | ||
}); | ||
}); | ||
|
||
module.exports = collectors; |
Empty file.
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,17 @@ | ||
var shared = require(__dirname + '/../shared.js'); | ||
var functions = require('./functions.js'); | ||
var regRegions = require('./regions.js'); | ||
|
||
var regions = function() { | ||
return regRegions; | ||
}; | ||
|
||
var helpers = { | ||
regions: regions, | ||
MAX_REGIONS_AT_A_TIME: 6 | ||
}; | ||
|
||
for (var s in shared) helpers[s] = shared[s]; | ||
for (var f in functions) helpers[f] = functions[f]; | ||
|
||
module.exports = helpers; |
Oops, something went wrong.