Skip to content

Commit

Permalink
merging master into open-source
Browse files Browse the repository at this point in the history
  • Loading branch information
giorodaqua committed Nov 25, 2020
1 parent 1ba1ada commit 0b70c1b
Show file tree
Hide file tree
Showing 71 changed files with 1,571 additions and 259 deletions.
7 changes: 6 additions & 1 deletion collectors/aws/collector.js
Expand Up @@ -370,7 +370,12 @@ var calls = {
EMR: {
listClusters: {
property: 'Clusters',
paginate: 'Marker'
paginate: 'Marker',
params: {
ClusterStates: [
'RUNNING'
]
}
}
},
ES: {
Expand Down
7 changes: 7 additions & 0 deletions collectors/azure/collector.js
Expand Up @@ -216,6 +216,13 @@ var postcalls = {
url: 'https://management.azure.com/{id}/blobServices/default/containers?api-version=2019-06-01'
}
},
blobServices: {
list: {
reliesOnPath: 'storageAccounts.list',
properties: ['id'],
url: 'https://management.azure.com/{id}/blobServices?api-version=2019-06-01'
}
},
fileShares: {
list: {
reliesOnPath: 'storageAccounts.list',
Expand Down
2 changes: 1 addition & 1 deletion docs/notes.md
Expand Up @@ -26,7 +26,7 @@ To create a cross-account role:
```

## CloudSploit Supplemental Policy
Allows read only accesss to services not included in the SecurityAudit AWS Managed policy but that are also tested by the CSPM scans.
Allows read only access to services not included in the SecurityAudit AWS Managed policy but that are also tested by the CSPM scans.

```$xslt
{
Expand Down
2 changes: 1 addition & 1 deletion docs/writing-remediation.md
Expand Up @@ -26,7 +26,7 @@ permissions: {
},
realtime_triggers: ['s3:CreateBucket'],
```
##### Description of the fileds mentioned above:
##### Description of the fields mentioned above:
* ```remediation_description```(string): A short description on what action will be performed to remediate the vulnerability.
* ```remediation_min_version```(string): Timestamp when this remediation is available in `YYYYMMDDhhmm` format.
* ```apis_remediate```(string): These are the api calls to collect the data needed for remediation.
Expand Down
2 changes: 1 addition & 1 deletion engine.js
Expand Up @@ -157,7 +157,7 @@ var engine = function(cloudConfig, settings) {
// Write out the result (to console or elsewhere)
outputHandler.writeResult(results[r], plugin, key, complianceMsg);

// Add this to our tracking fo the worst status to calculate
// Add this to our tracking for the worst status to calculate
// the exit code
maximumStatus = Math.max(maximumStatus, results[r].status);
// Remediation
Expand Down
1 change: 1 addition & 0 deletions exports.js
Expand Up @@ -66,6 +66,7 @@ module.exports = {
'openFTP' : require(__dirname + '/plugins/aws/ec2/openFTP.js'),
'openHadoopNameNode' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNode.js'),
'openHadoopNameNodeWebUI' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNodeWebUI.js'),
'openOracleAutoDataWarehouse' : require(__dirname + '/plugins/aws/ec2/openOracleAutoDataWarehouse.js'),
'openKibana' : require(__dirname + '/plugins/aws/ec2/openKibana.js'),
'openMySQL' : require(__dirname + '/plugins/aws/ec2/openMySQL.js'),
'openOracle' : require(__dirname + '/plugins/aws/ec2/openOracle.js'),
Expand Down
9 changes: 9 additions & 0 deletions exports.spec.js
Expand Up @@ -94,6 +94,15 @@ describe('exports', function () {

expect(lTest.remediation_min_version, `Test: ${test} remediation_min_version parameter is not a string`).to.be.a('string');
expect(lTest.remediation_min_version.length, `Test: ${test} remediation_min_version parameter length is not 12`).to.equal(12);

if (lTest.remediation_inputs) {
expect(lTest.remediation_inputs, `Test: ${test} remediation_inputs is not an object`).to.be.an('object');
Object.keys(lTest.remediation_inputs).forEach(function(rInput){
expect(lTest.remediation_inputs[rInput].name, `Test: ${test} remediation_inputs.${rInput}.name is not a string`).to.be.a('string');
expect(lTest.remediation_inputs[rInput].description, `Test: ${test} remediation_inputs.${rInput}.description is not a string`).to.be.a('string');
expect(lTest.remediation_inputs[rInput].regex, `Test: ${test} remediation_inputs.${rInput}.regex is not a string`).to.be.a('string');
});
}
}

if (lTest.rollback) {
Expand Down
2 changes: 2 additions & 0 deletions helpers/aws/functions.js
Expand Up @@ -177,6 +177,8 @@ function normalizePolicyDocument(doc) {
}

function globalPrincipal(principal) {
if (!principal) return false;

if (typeof principal === 'string' && principal === '*') {
return true;
}
Expand Down
3 changes: 2 additions & 1 deletion helpers/aws/index.js
Expand Up @@ -13,7 +13,8 @@ var regions = function(settings) {
var helpers = {
regions: regions,
MAX_REGIONS_AT_A_TIME: 6,
CLOUDSPLOIT_EVENTS_BUCKET: 'cloudsploit-engine-trails'
CLOUDSPLOIT_EVENTS_BUCKET: 'cloudsploit-engine-trails',
CLOUDSPLOIT_EVENTS_SNS: 'aqua-cspm-sns-'
};

for (var s in shared) helpers[s] = shared[s];
Expand Down
29 changes: 23 additions & 6 deletions helpers/azure/functions.js
Expand Up @@ -95,12 +95,29 @@ function findOpenPorts(ngs, protocols, service, location, results) {
if (strings.indexOf(string) === -1) strings.push(string);
found = true;
}
} else if (securityRule.properties['destinationPortRanges'] &&
securityRule.properties['destinationPortRanges'].toString().indexOf(port) > -1) {
var string = `Security Rule "` + securityRule['name'] + `": ` + (protocol === '*' ? `All protocols` : protocol.toUpperCase()) +
` port ` + ports + ` open to ` + sourceFilter;
if (strings.indexOf(string) === -1) strings.push(string);
found = true;
} else if (securityRule.properties['destinationPortRanges']) {
if (securityRule.properties['destinationPortRanges'].toString().indexOf(port) > -1) {
var string = `Security Rule "` + securityRule['name'] + `": ` + (protocol === '*' ? `All protocols` : protocol.toUpperCase()) +
` port ` + ports + ` open to ` + sourceFilter;
if (strings.indexOf(string) === -1) strings.push(string);
found = true;
} else {
for (let portRange of securityRule.properties['destinationPortRanges']){
if (portRange.toString().indexOf("-") > -1) {
portRange = portRange.split("-");
let startPort = portRange[0];
let endPort = portRange[1];
if (parseInt(startPort) <= port && parseInt(endPort) >= port){
var string = `Security Rule "` + securityRule['name'] + `": ` + (protocol === '*' ? `All protocols` : protocol.toUpperCase()) +
` port ` + ports + ` open to ` + sourceFilter;
strings.push(string);
if (strings.indexOf(string) === -1) strings.push(string);
found = true;
break;
}
}
}
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions helpers/azure/locations.js
Expand Up @@ -60,6 +60,7 @@ module.exports = {
logProfiles: ['global'],
profiles: ['global'],
managementLocks: ['global'],
blobServices: locations,
networkWatchers: locations,
managedClusters: locations,
virtualMachineScaleSets: locations,
Expand Down
11 changes: 6 additions & 5 deletions helpers/oracle/index.js
Expand Up @@ -5,7 +5,6 @@ var govLocations = require('./regions_gov.js');

var async = require('async');
var sshpk = require('sshpk');
var assert = require('assert-plus');

// REST Oracle
var oci = require( '../../other_modules/oci' );
Expand Down Expand Up @@ -51,8 +50,9 @@ function OracleExecutor(OracleConfig) {
}
try {
OracleConfig.privateKey = sshpk.parsePrivateKey(OracleConfig.keyValue, 'pem');
assert.ok(sshpk.PrivateKey.isPrivateKey(OracleConfig.privateKey, [1, 2]),
'options.key must be a sshpk.PrivateKey');
if (!sshpk.PrivateKey.isPrivateKey(OracleConfig.privateKey, [1, 2])) {
throw 'options.key must be a sshpk.PrivateKey';
}
(!OracleConfig.RESTversion ? OracleConfig.RESTversion = '/20160918' : false );
} catch (e) {
console.log('Could not read the Oracle Private Key.');
Expand Down Expand Up @@ -102,8 +102,9 @@ function OracleExecutor(OracleConfig) {

try {
OracleConfig.privateKey = sshpk.parsePrivateKey(OracleConfig.keyValue, 'pem');
assert.ok(sshpk.PrivateKey.isPrivateKey(OracleConfig.privateKey, [1, 2]),
'options.key must be a sshpk.PrivateKey');
if (!sshpk.PrivateKey.isPrivateKey(OracleConfig.privateKey, [1, 2])) {
throw 'options.key must be a sshpk.PrivateKey';
}
(!OracleConfig.RESTversion ? OracleConfig.RESTversion = '/20160918' : false );

} catch (e) {
Expand Down
111 changes: 110 additions & 1 deletion plugins/aws/athena/workgroupEncrypted.js
Expand Up @@ -9,7 +9,32 @@ module.exports = {
link: 'https://docs.aws.amazon.com/athena/latest/ug/encryption.html',
recommended_action: 'Enable encryption at rest for all Athena workgroups.',
apis: ['Athena:listWorkGroups', 'Athena:getWorkGroup', 'STS:getCallerIdentity'],

remediation_description: 'Encryption for the affected workgroups will be enabled.',
remediation_min_version: '202011182332',
apis_remediate: ['Athena:listWorkGroups', 'Athena:getWorkGroup', 'STS:getCallerIdentity'],
actions: {
remediate: ['Athena:updateWorkGroup'],
rollback: ['Athena:updateWorkGroup']
},
permissions: {
remediate: ['athena:UpdateWorkGroup'],
rollback: ['athena:UpdateWorkGroup']
},
realtime_triggers: ['athena:CreateWorkGroup', 'athena:UpdateWorkGroup'],
remediation_inputs: {
encryptionOption: {
name: '(Mandatory) Encryption method',
description: 'SSE_S3 | SSE_KMS | CSE_KMS',
regex: '^(SSE_S3|SSE_KMS|CSE_KMS)$',
required: true
},
kmsKeyIdforWg: {
name: '(Optional)KMS Key ID',
description: 'The KMS Key ID used for encryption if encryption option is SSE_KMS or CSE_KMS',
regex: '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$',
required: false
}
},
run: function(cache, settings, callback) {
var results = [];
var source = {};
Expand Down Expand Up @@ -70,5 +95,89 @@ module.exports = {
}, function(){
callback(null, results, source);
});
},

remediate: function(config, cache, settings, resource, callback) {
var putCall = this.actions.remediate;
var pluginName = 'workgroupEncrypted';
var wgNameArr = resource.split(':');
var wgName = wgNameArr[wgNameArr.length - 1].split('/');
wgName = wgName[wgName.length - 1];
// find the location of the Kinesis wg needing to be remediated
var wgLocation = wgNameArr[3];
if (!wgLocation) {
return callback('Unable to get wg location');
}
// add the location of the Kinesis wg to the config
config.region = wgLocation;
var params = {};
// create the params necessary for the remediation
if (settings.input && settings.input.encryptionOption){
if (settings.input.encryptionOption === 'SSE_KMS' ||
settings.input.encryptionOption === 'CSE_KMS') {
if (settings.input.kmsKeyIdforWg){
params = {
WorkGroup: wgName,
ConfigurationUpdates: {
ResultConfigurationUpdates: {
EncryptionConfiguration: {
EncryptionOption: settings.input.encryptionOption,
KmsKey: settings.input.kmsKeyIdforWg
}
}
}
};
} else {
return callback(`Key is mandatory for workgroup update with ${settings.input.encryptionOption}`);
}

} else if (settings.input.encryptionOption === 'SSE_S3'){
params = {
WorkGroup: wgName,
ConfigurationUpdates: {
ResultConfigurationUpdates: {
EncryptionConfiguration: {
EncryptionOption: settings.input.encryptionOption,
}
}
}
};
}

} else {
return callback('EncryptionOption is mandatory for workgroup update');
}

var remediation_file = settings.remediation_file;

remediation_file['pre_remediate']['actions'][pluginName][resource] = {
'Encryption': 'Disabled',
'Workgroup Name': wgName
};

// passes the config, put call, and params to the remediate helper function
helpers.remediatePlugin(config, putCall[0], params, function(err) {
if (err) {
remediation_file['remediate']['actions'][pluginName]['error'] = err;
return callback(err);
}

let action = params;
action.action = putCall;

remediation_file['post_remediate']['actions'][pluginName][resource] = action;
remediation_file['remediate']['actions'][pluginName][resource] = {
'Action': 'ENCRYPTED',
'Workgroup Name': wgName
};
settings.remediation_file = remediation_file;
return callback(null, action);
});
},

rollback: function(config, cache, settings, resource, callback) {
console.log('Rollback support for this plugin has not yet been implemented');
console.log(config, cache, settings, resource);
callback();
}
};
70 changes: 70 additions & 0 deletions plugins/aws/cloudtrail/cloudtrailEncryption.js
Expand Up @@ -12,6 +12,26 @@ module.exports = {
compliance: {
cis2: '2.7 Ensure CloudTrail logs are encrypted at rest using KMS CMKs'
},
remediation_description: 'Encryption for the affected Cloud trails will be enabled.',
remediation_min_version: '202010302230',
apis_remediate: ['CloudTrail:describeTrails'],
remediation_inputs: {
kmsKeyIdforCt: {
name: '(Mandatory) KMS Key ID',
description: 'The KMS Key ID used for encryption',
regex: '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$',
required: true
}
},
actions: {
remediate: ['CloudTrail:updateTrail'],
rollback: ['CloudTrail:updateTrail']
},
permissions: {
remediate: ['cloudtrail:UpdateTrail'],
rollback: ['cloudtrail:UpdateTrail']
},
realtime_triggers: ['cloudtrail:CreateTrail', 'cloudtrail:UpdateTrail'],

run: function(cache, settings, callback) {
var results = [];
Expand Down Expand Up @@ -50,5 +70,55 @@ module.exports = {
}, function(){
callback(null, results, source);
});
},
remediate: function(config, cache, settings, resource, callback) {
var putCall = this.actions.remediate;
var pluginName = 'cloudtrailEncryption';
var ctNameArr = resource.split(':');
var ctName = ctNameArr[ctNameArr.length - 1].split('/');
// find the location of the ct needing to be remediated

var ctLocation = ctNameArr[3];
var err;
// add the location of the ct to the config
config.region = ctLocation;
var params = {};

// create the params necessary for the remediation
if (settings.input &&
settings.input.kmsKeyIdforCt) {
params = {
'Name': resource,
'KmsKeyId': settings.input.kmsKeyIdforCt,
};
} else {
err = 'KmsKeyId is mandatory to enable encryption';
return callback(err, null);
}

var remediation_file = settings.remediation_file;
remediation_file['pre_remediate']['actions'][pluginName][resource] = {
'Encryption': 'Disabled',
'CloudTrail': resource
};
// passes the config, put call, and params to the remediate helper function
helpers.remediatePlugin(config, putCall[0], params, function(err) {
if (err) {
remediation_file['remediate']['actions'][pluginName]['error'] = err;
return callback(err, null);
}

let action = params;
action.action = putCall;

remediation_file['post_remediate']['actions'][pluginName][resource] = action;
remediation_file['remediate']['actions'][pluginName][resource] = {
'Action': 'ENCRYPTED',
'CloudTrail': ctName
};

settings.remediation_file = remediation_file;
return callback(null, action);
});
}
};

0 comments on commit 0b70c1b

Please sign in to comment.