diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index 3da6ce0db1..cefaa4e925 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -109,6 +109,7 @@ var calls = { securityContacts: { list: { url: 'https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Security/securityContacts?api-version=2017-08-01-preview', + ignoreLocation: true } }, subscriptions: { @@ -444,10 +445,10 @@ var collect = function(AzureConfig, settings, callback) { var regionsToLoop = parseCollection(subCallObj.reliesOnPath, collection); if (regionsToLoop && Object.keys(regionsToLoop).length) { // Loop through regions - async.eachOf(regionsToLoop, function(regionObj, region, regionCb) { + async.eachOfLimit(regionsToLoop, 5, function(regionObj, region, regionCb) { if (regionObj && regionObj.data && regionObj.data.length) { if (!collectionObj[region]) collectionObj[region] = {}; - async.each(regionObj.data, function(regionData, regionDataCb) { + async.eachLimit(regionObj.data, 10, function(regionData, regionDataCb) { var localReq = { url: subCallObj.url, post: subCallObj.post, @@ -523,7 +524,7 @@ var collect = function(AzureConfig, settings, callback) { async.eachOf(regionsToLoop, function(regionObj, region, regionCb) { if (!collectionObj[region]) collectionObj[region] = {}; // Loop through the resources - async.eachOf(regionObj, function(resourceObj, resourceId, resourceCb){ + async.eachOfLimit(regionObj, 5, function(resourceObj, resourceId, resourceCb){ function processResource(resourceData, resourceDataCb) { var localReq = { url: subCallObj.url, @@ -561,14 +562,14 @@ var collect = function(AzureConfig, settings, callback) { } if (Array.isArray(resourceObj)) { - async.each(resourceObj, function(resourceData, resourceDataCb) { + async.eachLimit(resourceObj, 10, function(resourceData, resourceDataCb) { processResource(resourceData, resourceDataCb); }, function(){ resourceCb(); }); } else { if (resourceObj && resourceObj.data && resourceObj.data.length) { - async.each(resourceObj.data, function(resourceData, resourceDataCb) { + async.eachLimit(resourceObj.data, 10, function(resourceData, resourceDataCb) { processResource(resourceData, resourceDataCb); }, function() { resourceCb(); diff --git a/collectors/oracle/collector.js b/collectors/oracle/collector.js index 8996ba8270..bac378b73d 100644 --- a/collectors/oracle/collector.js +++ b/collectors/oracle/collector.js @@ -20,7 +20,7 @@ var async = require('async'); var helpers = require(__dirname + '/../../helpers/oracle'); -const regionSubscriptionService = {name: 'regionSubscription', call: 'list', region: helpers.regions(false).default}; +var regionSubscriptionService; var globalServices = [ 'core' @@ -396,6 +396,10 @@ var processCall = function(OracleConfig, collection, settings, regions, call, se if (!collection[service][callKey]) collection[service][callKey] = {}; async.eachLimit(regions[service], helpers.MAX_REGIONS_AT_A_TIME, function(region, regionCb) { + if (region === 'default') { + region = OracleConfig.region ? OracleConfig.region : 'us-ashburn-1'; + } + if (settings.skip_regions && settings.skip_regions.indexOf(region) > -1 && globalServices.indexOf(service) === -1) return regionCb(); @@ -458,7 +462,6 @@ var processCall = function(OracleConfig, collection, settings, regions, call, se var getRegionSubscription = function(OracleConfig, collection, settings, calls, service, callKey, region, serviceCb) { var LocalOracleConfig = JSON.parse(JSON.stringify(OracleConfig)); - LocalOracleConfig.region = region; LocalOracleConfig.service = service; if (!collection[service]) collection[service] = {}; @@ -482,9 +485,10 @@ var getRegionSubscription = function(OracleConfig, collection, settings, calls, // Loop through all of the top-level collectors for each service var collect = function(OracleConfig, settings, callback) { var collection = {}; - + OracleConfig.region = OracleConfig.region ? OracleConfig.region : 'us-ashburn-1'; OracleConfig.maxRetries = 5; OracleConfig.retryDelayOptions = {base: 300}; + regionSubscriptionService = {name: 'regionSubscription', call: 'list', region: OracleConfig.region}; var regions = helpers.regions(settings.govcloud); diff --git a/engine.js b/engine.js index 5eb363a98d..d5d6df7ddc 100644 --- a/engine.js +++ b/engine.js @@ -2,7 +2,7 @@ var async = require('async'); var exports = require('./exports.js'); var suppress = require('./postprocess/suppress.js'); var output = require('./postprocess/output.js'); -var gslRunner = require('./helpers/gsl.js'); +var aslRunner = require('./helpers/asl.js'); /** * The main function to execute CloudSploit scans. @@ -193,11 +193,11 @@ var engine = function(cloudConfig, settings) { setTimeout(function() { pluginDone(err, maximumStatus); }, 0); }; - if (plugin.gsl) { - console.log(`INFO: Using custom GSL for plugin: ${plugin.title}`); + if (plugin.asl) { + console.log(`INFO: Using custom ASL for plugin: ${plugin.title}`); // Inject APIs and resource maps - plugin.gsl.apis = plugin.apis; - gslRunner(collection, plugin.gsl, resourceMap, postRun); + plugin.asl.apis = plugin.apis; + aslRunner(collection, plugin.asl, resourceMap, postRun); } else { plugin.run(collection, settings, postRun); } diff --git a/helpers/asl.js b/helpers/asl.js new file mode 100644 index 0000000000..d6ca853b2b --- /dev/null +++ b/helpers/asl.js @@ -0,0 +1,282 @@ +var parse = function(obj, path) { + if (typeof path == 'string') path = path.split('.'); + if (Array.isArray(path) && path.length) { + var localPath = path.shift(); + if (obj[localPath] || typeof obj[localPath] === 'boolean') { + return parse(obj[localPath], path); + } else { + return 'not set'; + } + } else { + return obj; + } +}; + +var transform = function(val, transformation) { + if (transformation == 'DATE') { + return new Date(val); + } else if (transformation == 'INTEGER') { + return parseInt(val); + } else if (transformation == 'STRING') { + return val.toString(); + } else if (transformation == 'DAYSFROM') { + // Return the number of days between the date and now + var now = new Date(); + var then = new Date(val); + var timeDiff = then.getTime() - now.getTime(); + var diff = Math.round(timeDiff / (1000 * 3600 * 24)); + return diff; + } else if (transformation == 'COUNT') { + return val.length; + } else if (transformation == 'EACH') { + return val; + } else if (transformation == 'TOLOWERCASE') { + return val.toLowerCase(); + } else { + return val; + } +}; + +function evaluateConditions(obj, conditions){ + var preVal = {}; // place to hold the result evaluated till now + for (let i in conditions){ + let condition = conditions[i]; + let value = validate(obj,condition); + + if (!condition.logical){ + // no logical operation means + // first element of the conditions + if ( i == 0){ + // first element in the condition list,so set the preVal + preVal = value; + } + // error as no logical condition and not the first element + else{ + //err + console.error('No logical operator found and this is not the first element'); + } + } + else{ + if ( i == 0){ + // first element in the condition list,and with logical operation. Error case + console.error('logical operator found in first element'); + } + else{ + // this is not first element in array and also logical op is here. use the preVal and evaluate it + if(preVal){ + //as this is not first element in array preVal should be set. + //other wise the condition is not properly formed as AND OR are binary ops + if( condition.logical === 'OR'){ + preVal.status = preVal.status || value.status; + } + else if (condition.logical === 'AND'){ + preVal.status = preVal.status && value.status; + } + else{ + // unsupported operator. + console.error('wrong logical operator mentioned'); + } + preVal.message = preVal.message.concat(', ',value.message); + } + else{ + //condition is not properly formed as AND OR are binary ops + console.error('condition is malformed'); + } + } + } + } + + return preVal; +} + +var validate = function(obj, condition) { + var result = 0; + var message = []; + var override = false; + + // Extract the values for the conditions + + if (condition.property) { + var conditionResult = 0; + condition.parsed = parse(obj, condition.property); + + // Transform the property if required + if (condition.transform) { + condition.parsed = transform(condition.parsed, condition.transform); + } + + // Compare the property with the operator + if (condition.parsed === 'not set'){ + conditionResult = 2; + message.push(`${condition.property}: not set to any value`); + } + else if (condition.op) { + if (condition.op == 'EQ') { + if (condition.parsed == condition.value) { + message.push(`${condition.property}: ${condition.parsed} matched: ${condition.value}`); + } else { + conditionResult = 2; + message.push(`${condition.property}: ${condition.parsed} did not match: ${condition.value}`); + } + } else if (condition.op == 'GT') { + if (condition.parsed > condition.value) { + message.push(`${condition.property}: count of ${condition.parsed} was greater than: ${condition.value}`); + } else { + conditionResult = 2; + message.push(`${condition.property}: count of ${condition.parsed} was not greater than: ${condition.value}`); + } + } else if (condition.op == 'NE') { + if (condition.parsed !== condition.value) { + message.push(`${condition.property}: ${condition.parsed} is not: ${condition.value}`); + } else { + conditionResult = 2; + message.push(`${condition.property}: ${condition.parsed} is: ${condition.value}`); + } + } else if (condition.op == 'MATCHES') { + var userRegex = RegExp(condition.value); + if (userRegex.test(condition.parsed)) { + message.push(`${condition.property}: ${condition.parsed} matches the regex: ${condition.value}`); + } else { + conditionResult = 2; + message.push(`${condition.property}: ${condition.parsed} does not match the regex: ${condition.value}`); + } + } else if (condition.op == 'EXISTS') { + if (condition.parsed !== 'not set') { + message.push(`${condition.property}: set to ${condition.parsed}`); + } else { + conditionResult = 2; + message.push(`${condition.property}: ${condition.parsed}`); + } + } else if (condition.op == 'ISTRUE') { + if (condition.parsed) { + message.push(`${condition.property} is true`); + } else { + conditionResult = 2; + message.push(`${condition.property} is false`); + } + } else if (condition.op == 'ISFALSE') { + if (!condition.parsed) { + message.push(`${condition.property} is false`); + } else { + conditionResult = 2; + message.push(`${condition.property} is true`); + } + } else if (condition.op == 'CONTAINS') { + if (condition.parsed.includes(condition.value)) { + message.push(`${condition.property}: ${condition.value} found in ${condition.parsed}`); + } else { + conditionResult = 2; + message.push(`${condition.value} not found in ${condition.parsed}`); + } + } + } else if (condition.transform && condition.transform == 'EACH' && condition.conditions) { + // Recurse into the same function + var subProcessed = []; + condition.parsed.forEach(function(parsed) { + subProcessed.push(validate(parsed, condition.conditions)); + }); + subProcessed.forEach(function(sub) { + if (sub.status) conditionResult = sub.status; + if (sub.message) message.push(sub.message); + }); + } + if (condition.invert) conditionResult = (conditionResult ? 0 : 2); + + if (condition.override && !conditionResult) override = true; + if (conditionResult) result = conditionResult; + } + + + if (result && override) result = 0; + + if (!message.length) { + message = ['The resource matched all required conditions']; + } + + return { + status: result, + message: message.join(', ') + }; +}; + +var asl = function(source, input, resourceMap, callback) { + if (!source || !input) return callback('No source or input provided'); + if (!input.apis || !input.apis[0]) return callback('No APIs provided for input'); + if (!input.conditions || !input.conditions.length) return callback('No conditions provided for input'); + + // Split apis into service:api + // TODO: support conditions that use different APIs + var service = input.conditions[0].service; + var api = input.conditions[0].api; + var resourcePath; + if (resourceMap && + resourceMap[service] && + resourceMap[service][api]) { + resourcePath = resourceMap[service][api]; + } + + if (!source[service]) return callback(`Source data did not contain service: ${service}`); + if (!source[service][api]) return callback(`Source data did not contain API: ${api}`); + + var results = []; + + for (var region in source[service][api]) { + var regionVal = source[service][api][region]; + if (typeof regionVal !== 'object') continue; + if (regionVal.err) { + results.push({ + status: 3, + message: regionVal.err.message || 'Error', + region: region + }); + } else if (regionVal.data) { + // It's an array, loop + regionVal.data.forEach(function(regionData) { + var validated = evaluateConditions(regionData, input.conditions); + var parsedResource = parse(regionData, resourcePath); + if (typeof parsedResource !== 'string') parsedResource = null; + + results.push({ + status: validated.status, + resource: parsedResource, + message: validated.message, + region: region + }); + }); + } else { + for (var resourceName in regionVal) { + var resourceObj = regionVal[resourceName]; + if (resourceObj.err) { + results.push({ + status: 3, + resource: resourceName, + message: resourceObj.err.message || 'Error', + region: region + }); + } else if (!resourceObj.data) { + results.push({ + status: 3, + resource: resourceName, + message: 'No data returned', + region: region + }); + } else { + var validated = evaluateConditions(resourceObj.data, input.conditions); + var parsedResource = parse(resourceObj.data, resourcePath); + if (typeof parsedResource !== 'string') parsedResource = null; + + results.push({ + status: validated.status, + resource: parsedResource ? parsedResource : resourceName, + message: validated.message, + region: region + }); + } + } + } + } + + callback(null, results, source[service][api]); +}; + +module.exports = asl; \ No newline at end of file diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index 2e93ae9453..3ff6c650f8 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -75,9 +75,7 @@ module.exports = { vpc: regions, flowlogs: regions, rds: regions, - redshift: ['us-east-1', 'us-east-2', 'us-west-2', 'us-west-1', 'ca-central-1', - 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', - 'ap-northeast-1','ap-northeast-2', 'ap-southeast-1','ap-southeast-2','ap-south-1','sa-east-1'], + redshift: regions, cloudwatch: regions, ecs: regions, resourcegroupstaggingapi: regions, diff --git a/helpers/aws/resources.js b/helpers/aws/resources.js index d09a28c771..6d5778c869 100644 --- a/helpers/aws/resources.js +++ b/helpers/aws/resources.js @@ -5,5 +5,21 @@ module.exports = { cloudfront: { listDistributions: 'ARN', getDistribution: 'Distribution.ARN' + }, + s3: { + listBuckets: 'name', + }, + sns:{ + listTopics: 'describeKey', + getTopicAttributes: 'Attributes.TopicArn' + }, + kms:{ + describeKey: 'KeyMetadata.Arn' + }, + iam:{ + generateCredentialReport: 'arn', + listServerCertificates: 'Arn', + getGroup: 'Arn', + getRole: 'Role.Arn' } }; \ No newline at end of file diff --git a/helpers/azure/auth.js b/helpers/azure/auth.js index 64c9686ad9..db4584f883 100644 --- a/helpers/azure/auth.js +++ b/helpers/azure/auth.js @@ -160,7 +160,7 @@ module.exports = { if (dv.location && dv.location.toLowerCase().replace(/ /g, '') == location.toLowerCase()) { return true; - } else if (location.toLowerCase() == 'global' && !dv.location) { + } else if (location.toLowerCase() == 'global' && (!dv.location || obj.ignoreLocation)) { return true; } return false; diff --git a/helpers/gsl.js b/helpers/gsl.js deleted file mode 100644 index 186dcd8c17..0000000000 --- a/helpers/gsl.js +++ /dev/null @@ -1,188 +0,0 @@ -var parse = function(obj, path) { - if (typeof path == 'string') path = path.split('.'); - if (Array.isArray(path) && path.length) { - var localPath = path.shift(); - if (obj[localPath]) { - return parse(obj[localPath], path); - } else { - return 'not set'; - } - } else { - return obj; - } -}; - -var transform = function(val, transformation) { - if (transformation == 'DATE') { - return new Date(val); - } else if (transformation == 'INTEGER') { - return parseInt(val); - } else if (transformation == 'STRING') { - return val.toString(); - } else if (transformation == 'DAYSFROM') { - // Return the number of days between the date and now - var now = new Date(); - var then = new Date(val); - var timeDiff = then.getTime() - now.getTime(); - var diff = Math.round(timeDiff / (1000 * 3600 * 24)); - return diff; - } else if (transformation == 'COUNT') { - return val.length; - } else if (transformation == 'EACH') { - return val; - } else { - return val; - } -}; - -var validate = function(obj, conditions) { - var result = 0; - var message = []; - var override = false; - - // Extract the values for the conditions - conditions.forEach(function(condition) { - if (condition.property) { - var conditionResult = 0; - condition.parsed = parse(obj, condition.property); - - // Transform the property if required - if (condition.transform) { - condition.parsed = transform(condition.parsed, condition.transform); - } - - // Compare the property with the operator - if (condition.op) { - if (condition.op == 'EQ') { - if (condition.parsed == condition.value) { - message.push(`${condition.property}: ${condition.parsed} matched: ${condition.value}`); - } else { - conditionResult = 2; - message.push(`${condition.property}: ${condition.parsed} did not match: ${condition.value}`); - } - } else if (condition.op == 'GT') { - if (condition.parsed > condition.value) { - message.push(`${condition.property}: count of ${condition.parsed} was greater than: ${condition.value}`); - } else { - conditionResult = 2; - message.push(`${condition.property}: count of ${condition.parsed} was not greater than: ${condition.value}`); - } - } else if (condition.op == 'NE') { - if (condition.parsed !== condition.value) { - message.push(`${condition.property}: ${condition.parsed} is not: ${condition.value}`); - } else { - conditionResult = 2; - message.push(`${condition.property}: ${condition.parsed} is: ${condition.value}`); - } - } - } else if (condition.transform && condition.transform == 'EACH' && condition.conditions) { - // Recurse into the same function - var subProcessed = []; - condition.parsed.forEach(function(parsed) { - subProcessed.push(validate(parsed, condition.conditions)); - }); - subProcessed.forEach(function(sub) { - if (sub.status) conditionResult = sub.status; - if (sub.message) message.push(sub.message); - }); - } - if (condition.invert) conditionResult = (conditionResult ? 0 : 2); - - if (condition.override && !conditionResult) override = true; - if (conditionResult) result = conditionResult; - } - }); - - if (result && override) result = 0; - - if (!message.length) { - message = ['The resource matched all required conditions']; - } - - return { - status: result, - message: message.join(', ') - }; -}; - -var gsl = function(source, input, resourceMap, callback) { - if (!source || !input) return callback('No source or input provided'); - if (!input.apis || !input.apis[0]) return callback('No APIs provided for input'); - if (!input.conditions || !input.conditions.length) return callback('No conditions provided for input'); - - // Split apis into service:api - // TODO: support conditions that use different APIs - var service = input.conditions[0].service; - var api = input.conditions[0].api; - var resourcePath; - if (resourceMap && - resourceMap[service] && - resourceMap[service][api]) { - resourcePath = resourceMap[service][api]; - } - - if (!source[service]) return callback(`Source data did not contain service: ${service}`); - if (!source[service][api]) return callback(`Source data did not contain API: ${api}`); - - var results = []; - - for (var region in source[service][api]) { - var regionVal = source[service][api][region]; - if (typeof regionVal !== 'object') continue; - if (regionVal.err) { - results.push({ - status: 3, - message: regionVal.err.message || 'Error', - region: region - }); - } else if (regionVal.data) { - // It's an array, loop - regionVal.data.forEach(function(regionData) { - var validated = validate(regionData, input.conditions); - var parsedResource = parse(regionData, resourcePath); - if (typeof parsedResource !== 'string') parsedResource = null; - - results.push({ - status: validated.status, - resource: parsedResource, - message: validated.message, - region: region - }); - }); - } else { - for (var resourceName in regionVal) { - var resourceObj = regionVal[resourceName]; - if (resourceObj.err) { - results.push({ - status: 3, - resource: resourceName, - message: resourceObj.err.message || 'Error', - region: region - }); - } else if (!resourceObj.data) { - results.push({ - status: 3, - resource: resourceName, - message: 'No data returned', - region: region - }); - } else { - var validated = validate(resourceObj.data, input.conditions); - var parsedResource = parse(resourceObj.data, resourcePath); - if (typeof parsedResource !== 'string') parsedResource = null; - - results.push({ - status: validated.status, - resource: parsedResource, - message: validated.message, - region: region - }); - } - } - } - } - - callback(null, results, source[service][api]); -}; - -module.exports = gsl; diff --git a/helpers/oracle/regions.js b/helpers/oracle/regions.js index a83e52e5b6..00bc5e705e 100644 --- a/helpers/oracle/regions.js +++ b/helpers/oracle/regions.js @@ -16,14 +16,14 @@ var regions = [ ]; module.exports = { - default: ['us-ashburn-1'], + default: ['default'], all: regions, vcn: regions, group: regions, publicIp: regions, securityList: regions, loadBalancer: regions, - user: ['us-ashburn-1'], + user: ['default'], userGroupMembership: regions, authenticationPolicy: regions, exprt: regions, @@ -45,13 +45,13 @@ module.exports = { volume: regions, volumeBackup: regions, bootVolumeAttachment: regions, - availabilityDomain: ['us-ashburn-1'], + availabilityDomain: ['default'], volumeGroup: regions, volumeGroupBackup: regions, volumeBackupPolicy: regions, volumeBackupPolicyAssignment: regions, preAuthenticatedRequest: regions, - configuration: ['us-ashburn-1'], + configuration: ['default'], dbSystem: regions, mountTarget: regions, namespace: regions diff --git a/index.js b/index.js index 7e57be6716..7ef53f670c 100755 --- a/index.js +++ b/index.js @@ -169,13 +169,12 @@ if (config.credentials.aws.credential_file) { } else if (config.credentials.oracle.credential_file) { settings.cloud = 'oracle'; cloudConfig = loadHelperFile(config.credentials.oracle.credential_file); - if (!cloudConfig || !cloudConfig.tenancyId || !cloudConfig.compartmentId || !cloudConfig.userId || !cloudConfig.keyValue) { - console.error('ERROR: Oracle credential file does not have tenancyId, compartmentId, userId, or keyValue'); + if (!cloudConfig || !cloudConfig.tenancyId || !cloudConfig.compartmentId || !cloudConfig.userId || !cloudConfig.keyValue || !cloudConfig.region) { + console.error('ERROR: Oracle credential file does not have tenancyId, compartmentId, userId, region, or keyValue'); process.exit(1); } cloudConfig.RESTversion = '/20160918'; - cloudConfig.region = 'us-ashburn-1'; } else if (config.credentials.oracle.tenancy_id) { settings.cloud = 'oracle'; checkRequiredKeys(config.credentials.oracle, ['compartment_id', 'user_id', 'key_fingerprint', 'key_value']); @@ -186,7 +185,7 @@ if (config.credentials.aws.credential_file) { userId: config.credentials.oracle.user_id, keyFingerprint: config.credentials.oracle.key_fingerprint, keyValue: config.credentials.oracle.key_value, - region: 'us-ashburn-1', + region: config.credentials.oracle.region, }; } else if (config.credentials.github.credential_file) { settings.cloud = 'github'; diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 7de7e11174..035c2d760d 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -60,7 +60,7 @@ module.exports = { if (!stackDetails.Parameters || !stackDetails.Parameters.length) { helpers.addResult(results, 0, 'Template does not contain any parameters', region, resource); - return; + continue; } for (var parameter of stackDetails.Parameters) { diff --git a/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js b/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js index 6a849aaafe..93d96c595f 100644 --- a/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js +++ b/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js @@ -20,18 +20,18 @@ module.exports = { 'for PCI. Enable CloudFront logging to log requests sent to ' + 'applications in a PCI environment.' }, - // gsl: { - // conditions: [ - // { - // service: 'cloudfront', - // api: 'getDistribution', - // property: 'Distribution.DistributionConfig.Logging.Enabled', - // transform: 'STRING', - // op: 'EQ', - // value: 'true' - // } - // ] - // }, + asl: { + conditions: [ + { + service: 'cloudfront', + api: 'getDistribution', + property: 'Distribution.DistributionConfig.Logging.Enabled', + transform: 'STRING', + op: 'EQ', + value: 'true' + } + ] + }, run: function(cache, settings, callback) { diff --git a/plugins/aws/ec2/vpcEndpointAcceptance.js b/plugins/aws/ec2/vpcEndpointAcceptance.js index 03204c4d90..367689e2aa 100644 --- a/plugins/aws/ec2/vpcEndpointAcceptance.js +++ b/plugins/aws/ec2/vpcEndpointAcceptance.js @@ -43,7 +43,7 @@ module.exports = { } describeVpcEndpointServices.data = describeVpcEndpointServices.data.filter(service => service.Owner != 'amazon'); - + if (!describeVpcEndpointServices.data.length) { helpers.addResult(results, 0, 'No user owned VPC endpoint services present', region); @@ -54,7 +54,7 @@ module.exports = { if (!service.ServiceId) continue; var resource = `arn:${defaultPartition}:ec2:${region}:${service.Owner}:vpc-endpoint-service/${service.ServiceId}`; - + if (service.AcceptanceRequired) { helpers.addResult(results, 0, `VPC endpoint service ${service.ServiceId} requires acceptance by the service owner`, @@ -77,7 +77,7 @@ module.exports = { !describeVpcEndpointServicePermissions.data.AllowedPrincipals.length) { helpers.addResult(results, 0, `VPC endpoint service ${service.ServiceId} does not require acceptance by the service owner but no allowed principals found`, - region, resource); + region, resource); } else { helpers.addResult(results, 2, `VPC endpoint service ${service.ServiceId} does not require acceptance by the service owner for allowed principals`, diff --git a/plugins/aws/ec2/vpcEndpointAcceptance.spec.js b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js index 116f1ec0b3..b6eb54ec00 100644 --- a/plugins/aws/ec2/vpcEndpointAcceptance.spec.js +++ b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js @@ -6,17 +6,17 @@ const vpcEndpointServices = [ "ServiceName": "com.amazonaws.vpce.us-east-1.vpce-svc-09d3a6a098dce6e8c", "ServiceId": "vpce-svc-09d3a6a098dce6e8c", "ServiceType": [ - { - "ServiceType": "Interface" - } + { + "ServiceType": "Interface" + } ], "AvailabilityZones": [ - "us-east-1a", - "us-east-1b" + "us-east-1a", + "us-east-1b" ], "Owner": "123456654321", "BaseEndpointDnsNames": [ - "vpce-svc-09d3a6a098dce6e8c.us-east-1.vpce.amazonaws.com" + "vpce-svc-09d3a6a098dce6e8c.us-east-1.vpce.amazonaws.com" ], "VpcEndpointPolicySupported": false, "AcceptanceRequired": true, @@ -27,18 +27,18 @@ const vpcEndpointServices = [ "ServiceName": "com.amazonaws.vpce.us-east-1.vpce-svc-09145867a106679a3", "ServiceId": "vpce-svc-09145867a106679a3", "ServiceType": [ - { - "ServiceType": "Interface" - } + { + "ServiceType": "Interface" + } ], "AvailabilityZones": [ - "us-east-1a", - "us-east-1b", - "us-east-1c" + "us-east-1a", + "us-east-1b", + "us-east-1c" ], "Owner": "123456654321", "BaseEndpointDnsNames": [ - "vpce-svc-09145867a106679a3.us-east-1.vpce.amazonaws.com" + "vpce-svc-09145867a106679a3.us-east-1.vpce.amazonaws.com" ], "VpcEndpointPolicySupported": false, "AcceptanceRequired": false, diff --git a/plugins/aws/iam/accessKeysExtra.js b/plugins/aws/iam/accessKeysExtra.js index d643166c7f..675c6241df 100644 --- a/plugins/aws/iam/accessKeysExtra.js +++ b/plugins/aws/iam/accessKeysExtra.js @@ -9,7 +9,23 @@ module.exports = { link: 'http://docs.aws.amazon.com/IAM/latest/UserGuide/ManagingCredentials.html', recommended_action: 'Remove the extra access key for the specified user.', apis: ['IAM:generateCredentialReport'], - + asl: { + conditions: [ + { + service: 'iam', + api: 'generateCredentialReport', + property: 'access_key_1_active', + op: 'ISFALSE' + }, + { + service: 'iam', + api: 'generateCredentialReport', + property: 'access_key_2_active', + op: 'ISFALSE', + logical: 'OR' + } + ] + }, run: function(cache, settings, callback) { var results = []; diff --git a/plugins/aws/iam/accessKeysLastUsed.js b/plugins/aws/iam/accessKeysLastUsed.js index b95d0c8b51..a349847e3d 100644 --- a/plugins/aws/iam/accessKeysLastUsed.js +++ b/plugins/aws/iam/accessKeysLastUsed.js @@ -28,6 +28,18 @@ module.exports = { default: 90 } }, + asl: { + conditions: [ + { + service: 'iam', + api: 'generateCredentialReport', + property: 'access_key_1_last_used_date', + transform: 'DAYSFROM', + op: 'GT', + value: 90 + } + ] + }, run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/iam/accessKeysRotated.js b/plugins/aws/iam/accessKeysRotated.js index 846b82e82c..d72395a1f1 100644 --- a/plugins/aws/iam/accessKeysRotated.js +++ b/plugins/aws/iam/accessKeysRotated.js @@ -32,6 +32,18 @@ module.exports = { default: 90 } }, + asl: { + conditions: [ + { + service: 'iam', + api: 'generateCredentialReport', + property: 'access_key_1_last_rotated', + transform: 'DAYSFROM', + op: 'GT', + value: 90 + } + ] + }, run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/iam/accessKeysRotated.spec.js b/plugins/aws/iam/accessKeysRotated.spec.js index b46865cd36..726e449d55 100644 --- a/plugins/aws/iam/accessKeysRotated.spec.js +++ b/plugins/aws/iam/accessKeysRotated.spec.js @@ -2,7 +2,7 @@ var expect = require('chai').expect; const accessKeysRotated = require('./accessKeysRotated'); var warnDate = new Date(); -warnDate.setMonth(warnDate.getMonth() - 3); +warnDate.setMonth(warnDate.getMonth() - 4); var passDate = new Date(); passDate.setMonth(passDate.getMonth() - 2); var failDate = new Date(); @@ -148,8 +148,8 @@ describe('accessKeysRotated', function () { it('should PASS if the user access key was last rotated within the pass limit', function (done) { const cache = createCache([generateCredentialReport[0], generateCredentialReport[2]]); var settings = { - access_keys_last_rotated_fail: 180, - access_keys_last_rotated_warn: 90 + access_keys_rotated_fail: 180, + access_keys_rotated_warn: 90 }; accessKeysRotated.run(cache, settings, (err, results) => { expect(results.length).to.equal(2); @@ -162,8 +162,8 @@ describe('accessKeysRotated', function () { it('should WARN if the user access key was last rotated within the warn limit', function (done) { const cache = createCache([generateCredentialReport[0], generateCredentialReport[1]]); var settings = { - access_keys_last_rotated_fail: 180, - access_keys_last_rotated_warn: 100 + access_keys_rotated_fail: 180, + access_keys_rotated_warn: 80 }; accessKeysRotated.run(cache, settings, (err, results) => { expect(results.length).to.equal(2); @@ -176,8 +176,8 @@ describe('accessKeysRotated', function () { it('should FAIL if the user access key was last rotated more than the fail limit', function (done) { const cache = createCache([generateCredentialReport[0],generateCredentialReport[0],generateCredentialReport[3]]); var settings = { - access_keys_last_rotated_fail: 180, - access_keys_last_rotated_warn: 90 + access_keys_rotated_fail: 180, + access_keys_rotated_warn: 90 }; accessKeysRotated.run(cache, settings, (err, results) => { expect(results.length).to.equal(2); diff --git a/plugins/aws/iam/canaryKeysUsed.js b/plugins/aws/iam/canaryKeysUsed.js index 6f07bec84d..1e3cb681bd 100644 --- a/plugins/aws/iam/canaryKeysUsed.js +++ b/plugins/aws/iam/canaryKeysUsed.js @@ -17,7 +17,20 @@ module.exports = { default: '' } }, - + //we need to check if (canary_user && access_key_1_last_used_date) || (canary_user && access_key_2_last_used_date) [SOP] + // canary_user && (access_key_1_last_used_date || access_key_2_last_used_date) + asl: { + conditions: [ + { + service: 'iam', + api: 'generateCredentialReport', + property: 'access_key_1_last_rotated', + transform: 'DAYSFROM', + op: 'GT', + value: 90 + } + ] + }, run: function(cache, settings, callback) { var config = { canary_user: settings.canary_user || this.settings.canary_user.default diff --git a/plugins/aws/iam/certificateExpiry.js b/plugins/aws/iam/certificateExpiry.js index 46b9eb8327..93aa0311c5 100644 --- a/plugins/aws/iam/certificateExpiry.js +++ b/plugins/aws/iam/certificateExpiry.js @@ -22,6 +22,18 @@ module.exports = { default: 30 } }, + asl: { + conditions: [ + { + service: 'iam', + api: 'listServerCertificates', + property: 'Expiration', + transform: 'DAYSFROM', + op: 'GT', + value: 90 + } + ] + }, run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/iam/emptyGroups.js b/plugins/aws/iam/emptyGroups.js index 00844bbdf5..3fc4381413 100644 --- a/plugins/aws/iam/emptyGroups.js +++ b/plugins/aws/iam/emptyGroups.js @@ -9,6 +9,18 @@ module.exports = { link: 'http://docs.aws.amazon.com/IAM/latest/UserGuide/Using_WorkingWithGroupsAndUsers.html', recommended_action: 'Remove unused groups without users', apis: ['IAM:listGroups', 'IAM:getGroup'], + asl: { + conditions: [ + { + service: 'iam', + api: 'getGroup', + property: 'Users', + transform: 'COUNT', + op: 'GT', + value: 0 + } + ] + }, run: function(cache, settings, callback) { var results = []; diff --git a/plugins/aws/iam/iamRoleLastUsed.js b/plugins/aws/iam/iamRoleLastUsed.js index 22f796bc2f..77a0374f2d 100644 --- a/plugins/aws/iam/iamRoleLastUsed.js +++ b/plugins/aws/iam/iamRoleLastUsed.js @@ -35,6 +35,18 @@ module.exports = { default: 'true' } }, + asl: { + conditions: [ + { + service: 'iam', + api: 'getRole', + property: 'Role.RoleLastUsed.LastUsedDate', + transform: 'DAYSFROM', + op: 'GT', + value: 90 + } + ] + }, run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/iam/iamUserNameRegex.js b/plugins/aws/iam/iamUserNameRegex.js index 4545732c8f..865cea3603 100644 --- a/plugins/aws/iam/iamUserNameRegex.js +++ b/plugins/aws/iam/iamUserNameRegex.js @@ -17,6 +17,18 @@ module.exports = { default: '^.*$', }, }, + asl: { + conditions: [ + { + service: 'iam', + api: 'generateCredentialReport', + property: 'user', + transform: 'STRING', + op: 'MATCHES', + value: '^.*$' + } + ] + }, run: function(cache, settings, callback) { var results = []; diff --git a/plugins/aws/iam/maxPasswordAge.js b/plugins/aws/iam/maxPasswordAge.js index e1162152ba..195f9af205 100644 --- a/plugins/aws/iam/maxPasswordAge.js +++ b/plugins/aws/iam/maxPasswordAge.js @@ -45,7 +45,18 @@ module.exports = { default: 180 } }, - + asl: { + conditions: [ + { + service: 'iam', + api: 'getAccountPasswordPolicy', + property: 'MaxPasswordAge', + transform: 'INTEGER', + op: 'GT', + value: 90 + } + ] + }, run: function(cache, settings, callback) { var config = { max_password_age_fail: settings.max_password_age_fail || this.settings.max_password_age_fail.default, diff --git a/plugins/aws/iam/minPasswordLength.js b/plugins/aws/iam/minPasswordLength.js index f4c60db430..dd90b31999 100644 --- a/plugins/aws/iam/minPasswordLength.js +++ b/plugins/aws/iam/minPasswordLength.js @@ -46,6 +46,18 @@ module.exports = { default: 14 } }, + asl: { + conditions: [ + { + service: 'iam', + api: 'getAccountPasswordPolicy', + property: 'MinimumPasswordLength', + transform: 'INTEGER', + op: 'GT', + value: 90 + } + ] + }, run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/iam/passwordExpiration.js b/plugins/aws/iam/passwordExpiration.js index 173fceedef..772e6f221e 100644 --- a/plugins/aws/iam/passwordExpiration.js +++ b/plugins/aws/iam/passwordExpiration.js @@ -26,6 +26,18 @@ module.exports = { 'password expirations enforces this policy.', cis1: '1.11 Ensure IAM password policy expires passwords within 90 days or less' }, + asl: { + conditions: [ + { + service: 'iam', + api: 'getAccountPasswordPolicy', + property: 'MaxPasswordAge', + transform: 'INTEGER', + op: 'GT', + value: 90 + } + ] + }, run: function(cache, settings, callback) { var results = []; diff --git a/plugins/aws/iam/usersMfaEnabled.js b/plugins/aws/iam/usersMfaEnabled.js index 1e9df89f8f..fdddeca8f5 100644 --- a/plugins/aws/iam/usersMfaEnabled.js +++ b/plugins/aws/iam/usersMfaEnabled.js @@ -18,6 +18,18 @@ module.exports = { cis1: '1.2 Ensure multi-factor authentication (MFA) is enabled for all ' + 'IAM users that have a console password' }, + asl: { + conditions: [ + { + service: 'iam', + api: 'generateCredentialReport', + property: 'mfa_active', + transform: 'STRING', + op: 'EQ', + value: 'true' + } + ] + }, run: function(cache, settings, callback) { var results = []; diff --git a/plugins/aws/kms/kmsScheduledDeletion.js b/plugins/aws/kms/kmsScheduledDeletion.js index 6c0f0fa0b5..5973024f22 100644 --- a/plugins/aws/kms/kmsScheduledDeletion.js +++ b/plugins/aws/kms/kmsScheduledDeletion.js @@ -9,6 +9,18 @@ module.exports = { recommended_action: 'Disable the key deletion before the scheduled deletion time.', link: 'http://docs.aws.amazon.com/kms/latest/developerguide/deleting-keys.html', apis: ['KMS:listKeys', 'KMS:describeKey'], + asl: { + conditions: [ + { + service: 'kms', + api: 'describeKey', + property: 'KeyMetadata.KeyState', + transform: 'STRING', + op: 'EQ', + value: 'PendingDeletion' + } + ] + }, run: function(cache, settings, callback) { var results = []; diff --git a/plugins/aws/s3/bucketLogging.js b/plugins/aws/s3/bucketLogging.js index a6f289b4b1..473c76bdf1 100644 --- a/plugins/aws/s3/bucketLogging.js +++ b/plugins/aws/s3/bucketLogging.js @@ -18,7 +18,18 @@ module.exports = { pci: 'PCI requires logging of all network access to environments containing ' + 'cardholder data. Enable S3 bucket access logs to log these network requests.' }, - + asl: { + conditions: [ + { + service: 's3', + api: 'getBucketLogging', + property: 'LoggingEnabled', + transform: 'STRING', + op: 'EQ', + value: 'true' + } + ] + }, run: function(cache, settings, callback) { var results = []; var source = {}; diff --git a/plugins/aws/s3/bucketVersioning.js b/plugins/aws/s3/bucketVersioning.js index e4eadecd00..a8d02cad9b 100644 --- a/plugins/aws/s3/bucketVersioning.js +++ b/plugins/aws/s3/bucketVersioning.js @@ -23,6 +23,35 @@ module.exports = { rollback: ['s3:PutBucketVersioning'] }, realtime_triggers: ['s3:CreateBucket', 's3:PutBucketVersioning'], + asl: { + conditions: [ + { + service: 's3', + api: 'getBucketVersioning', + property: 'Status', + transform: 'STRING', + op: 'EXISTS', + }, + { + service: 's3', + api: 'getBucketVersioning', + property: 'Status', + transform: 'STRING', + op: 'EQ', + value: 'Enabled', + logical: 'AND' + }, + { + service: 's3', + api: 'getBucketVersioning', + property: 'Status', + transform: 'STRING', + op: 'MATCHES', + value: '^[A-Z]{1}[a-z]+$', + logical: 'AND' + } + ] + }, run: function(cache, settings, callback) { var results = []; var source = {}; diff --git a/plugins/aws/sns/topicEncrypted.js b/plugins/aws/sns/topicEncrypted.js index e6cd7e02fc..44762ee63a 100644 --- a/plugins/aws/sns/topicEncrypted.js +++ b/plugins/aws/sns/topicEncrypted.js @@ -29,6 +29,18 @@ module.exports = { rollback: ['sns:SetTopicAttributes'] }, realtime_triggers: ['sns:CreateTopic', 'sns:SetTopicAttributes'], + asl: { + conditions: [ + { + service: 'sns', + api: 'getTopicAttributes', + property: 'Attributes.KmsMasterKeyId', + transform: 'STRING', + op: 'NE', + value: null + } + ] + }, run: function(cache, settings, callback) { var results = []; diff --git a/plugins/azure/cdnprofiles/detectInsecureCustomOrigin.js b/plugins/azure/cdnprofiles/detectInsecureCustomOrigin.js index b70f68ac24..fb3df8d631 100644 --- a/plugins/azure/cdnprofiles/detectInsecureCustomOrigin.js +++ b/plugins/azure/cdnprofiles/detectInsecureCustomOrigin.js @@ -46,7 +46,7 @@ module.exports = { if (!endpoints || endpoints.err || !endpoints.data) { helpers.addResult(results, 3, - 'Unable to query for CDN Profile endpoints: ' + helpers.addError(endpoints), profile.id); + 'Unable to query for CDN Profile endpoints: ' + helpers.addError(endpoints), location, profile.id); } else { if (!endpoints.data.length) { helpers.addResult(results, 0, diff --git a/plugins/google/storage/bucketLogging.js b/plugins/google/storage/bucketLogging.js index f6e974f9e7..451a46569c 100644 --- a/plugins/google/storage/bucketLogging.js +++ b/plugins/google/storage/bucketLogging.js @@ -34,20 +34,22 @@ module.exports = { helpers.addResult(results, 0, 'No storage buckets found', region); return rcb(); } + var bucketFound = false; buckets.data.forEach(bucket => { if (bucket.id) { - if (bucket.logging && - bucket.logging.logObjectPrefix == 'AccessLog') { + bucketFound = true; + if (bucket.logging && bucket.logging.logObjectPrefix && bucket.logging.logObjectPrefix.length) { helpers.addResult(results, 0, 'Bucket Logging Enabled', region, bucket.id); } else { helpers.addResult(results, 2, 'Bucket Logging not Enabled', region, bucket.id); } - } else { - helpers.addResult(results, 0, 'No storage buckets found', region); - return; } }); + if (!bucketFound) { + helpers.addResult(results, 0, 'No storage buckets found', region); + } + rcb(); }, function(){ // Global checking goes here diff --git a/plugins/oracle/audit/logRetentionPeriod.js b/plugins/oracle/audit/logRetentionPeriod.js index 77c6f58943..a5dd59b485 100644 --- a/plugins/oracle/audit/logRetentionPeriod.js +++ b/plugins/oracle/audit/logRetentionPeriod.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/oracle/'); module.exports = { @@ -30,43 +29,39 @@ module.exports = { }; var results = []; - var source = {}; - var regions = helpers.regions(settings.govcloud); + var source = {} + var region = helpers.objectFirstKey(cache['regionSubscription']['list']); - async.each(regions.configuration, function(region, rcb){ - if (helpers.checkRegionSubscription(cache, source, results, region)) { + if (helpers.checkRegionSubscription(cache, source, results, region)) { - var configurations = helpers.addSource(cache, source, - ['configuration', 'get', region]); + var configurations = helpers.addSource(cache, source, + ['configuration', 'get', region]); - if (!configurations) return rcb(); + if (!configurations) return callback(null, results, source); - if (configurations.err || !configurations.data) { - helpers.addResult(results, 3, - 'Unable to query for audit configurations: ' + helpers.addError(configurations), region); - return rcb(); - } + if (configurations.err || !configurations.data) { + helpers.addResult(results, 3, + 'Unable to query for audit configurations: ' + helpers.addError(configurations), region); + return callback(null, results, source); + } - if (!Object.keys(configurations.data).length) { - helpers.addResult(results, 0, 'No audit configurations found', region); - return rcb(); - } - var configuration = configurations.data; + if (!Object.keys(configurations.data).length) { + helpers.addResult(results, 0, 'No audit configurations found', region); + return callback(null, results, source); + } + var configuration = configurations.data; - if (configuration.retentionPeriodDays && - config.audit_log_retention_days && - configuration.retentionPeriodDays >= config.audit_log_retention_days) { - helpers.addResult(results, 0, - `Audit configuration period is ${configuration.retentionPeriodDays} days`, region); - } else { - helpers.addResult(results, 2, - `Audit configuration period is ${configuration.retentionPeriodDays} days`, region); - } + if (configuration.retentionPeriodDays && + config.audit_log_retention_days && + configuration.retentionPeriodDays >= config.audit_log_retention_days) { + helpers.addResult(results, 0, + `Audit configuration period is ${configuration.retentionPeriodDays} days`, region); + } else { + helpers.addResult(results, 2, + `Audit configuration period is ${configuration.retentionPeriodDays} days`, region); } - rcb(); - }, function(){ - // Global checking goes here - callback(null, results, source); - }); + } + + callback(null, results, source); } }; \ No newline at end of file diff --git a/plugins/oracle/blockstorage/blockPolicyProtection.js b/plugins/oracle/blockstorage/blockPolicyProtection.js index 0049ca0019..0b45c537c1 100644 --- a/plugins/oracle/blockstorage/blockPolicyProtection.js +++ b/plugins/oracle/blockstorage/blockPolicyProtection.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/oracle'); module.exports = { @@ -21,96 +20,92 @@ module.exports = { run: function (cache, settings, callback) { var results = []; var source = {}; - var regions = helpers.regions(settings.govcloud); var config = { policy_group_admins: settings.policy_group_admins || this.settings.policy_group_admins.default }; - async.each(regions.default, function (region, rcb) { - - var policies = helpers.addSource(cache, source, - ['policy', 'list', region]); - - if (!policies) return rcb(); - - if (policies.err || !policies.data) { - helpers.addResult(results, 3, - 'Unable to query for policies: ' + helpers.addError(policies), region); - return rcb(); - } + var region = helpers.objectFirstKey(cache['regionSubscription']['list']) + + var policies = helpers.addSource(cache, source, + ['policy', 'list', region]); + + if (!policies) return callback(null, results, source); + + if (policies.err || !policies.data) { + helpers.addResult(results, 3, + 'Unable to query for policies: ' + helpers.addError(policies), region); + return callback(null, results, source); + } + + if (!policies.data.length) { + helpers.addResult(results, 0, 'No policies found', region); + return callback(null, results, source); + } + var policyProtection = true; + var entered = false; + + policies.data.forEach(policy => { + if (policy.statements && + policy.statements.length) { + entered = true; + policy.statements.forEach(statement => { + + const statementLower = statement.toLowerCase(); + + if (statementLower.indexOf('allow') > -1 && + (statementLower.indexOf('manage') > -1 || + statementLower.indexOf('use') > -1) && + (statementLower.indexOf('request.permission') === -1 && + statementLower.indexOf('!=') === -1 && + statementLower.indexOf('_delete') === -1 && + (statementLower.indexOf('volume_') === -1 || + statementLower.indexOf('volume_backup_') === -1 || + statementLower.indexOf('volume_attachments_') === -1)) && + (statementLower.indexOf('volume') > -1 || + statementLower.indexOf('volumes-backups') > -1 || + statementLower.indexOf('volume-attachments') > -1 || + statementLower.indexOf('volume-family') > -1 || + statementLower.indexOf('all-resources') > -1)) { + + policyProtection = false; + var statementArr = statementLower.split(' '); + var statementNormalArr = statement.split(' '); + + var severity = 2; + + if (statementArr[1] === 'any-user' || statementArr[1] === 'dynamic-group') { + var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; + var compartment = statementArr[6] === 'tenancy' ? 'tenancy' : statementArr[6]; + var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[7]; + var groupType = statementArr[1]; + } else { + var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; + var compartment = statementArr[7] === 'tenancy' ? 'tenancy' : statementArr[7]; + var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[8]; + var groupType = 'The ' + statementArr[1]; + } - if (!policies.data.length) { - helpers.addResult(results, 0, 'No policies found', region); - return rcb(); - } - var policyProtection = true; - var entered = false; - - policies.data.forEach(policy => { - if (policy.statements && - policy.statements.length) { - entered = true; - policy.statements.forEach(statement => { - - const statementLower = statement.toLowerCase(); - - if (statementLower.indexOf('allow') > -1 && - (statementLower.indexOf('manage') > -1 || - statementLower.indexOf('use') > -1) && - (statementLower.indexOf('request.permission') === -1 && - statementLower.indexOf('!=') === -1 && - statementLower.indexOf('_delete') === -1 && - (statementLower.indexOf('volume_') === -1 || - statementLower.indexOf('volume_backup_') === -1 || - statementLower.indexOf('volume_attachments_') === -1)) && - (statementLower.indexOf('volume') > -1 || - statementLower.indexOf('volumes-backups') > -1 || - statementLower.indexOf('volume-attachments') > -1 || - statementLower.indexOf('volume-family') > -1 || - statementLower.indexOf('all-resources') > -1)) { - - policyProtection = false; - var statementArr = statementLower.split(' '); - var statementNormalArr = statement.split(' '); - - var severity = 2; - - if (statementArr[1] === 'any-user' || statementArr[1] === 'dynamic-group') { - var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; - var compartment = statementArr[6] === 'tenancy' ? 'tenancy' : statementArr[6]; - var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[7]; - var groupType = statementArr[1]; - } else { - var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; - var compartment = statementArr[7] === 'tenancy' ? 'tenancy' : statementArr[7]; - var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[8]; - var groupType = 'The ' + statementArr[1]; - } - - if (groupName === config.policy_group_admins.toLowerCase()) return; - if (statementArr.indexOf('request.user.name') > -1) { - groupType = 'The user'; - groupName = statementArr[statementArr.length - 1]; - severity = 1; - } - - helpers.addResult(results, severity, - `${groupType} ${groupName} has the ability to delete all block storage volumes in ${compartment} ${compartmentName}`, region, policy.id); + if (groupName === config.policy_group_admins.toLowerCase()) return; + if (statementArr.indexOf('request.user.name') > -1) { + groupType = 'The user'; + groupName = statementArr[statementArr.length - 1]; + severity = 1; } - }); + helpers.addResult(results, severity, + `${groupType} ${groupName} has the ability to delete all block storage volumes in ${compartment} ${compartmentName}`, region, policy.id); + } + }); - } - }); - if (policyProtection && entered) { - helpers.addResult(results, 0, 'All policies have block volume delete protection enabled', region); } - rcb(); - }, function () { - // Global checking goes here - callback(null, results, source); }); + + if (policyProtection && entered) { + helpers.addResult(results, 0, 'All policies have block volume delete protection enabled', region); + } + + callback(null, results, source); } }; \ No newline at end of file diff --git a/plugins/oracle/compute/instancePolicyProtection.js b/plugins/oracle/compute/instancePolicyProtection.js index a82971d6c2..e2ec28dd5b 100644 --- a/plugins/oracle/compute/instancePolicyProtection.js +++ b/plugins/oracle/compute/instancePolicyProtection.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/oracle'); module.exports = { @@ -21,88 +20,86 @@ module.exports = { run: function (cache, settings, callback) { var results = []; var source = {}; - var regions = helpers.regions(settings.govcloud); + var config = { policy_group_admins: settings.policy_group_admins || this.settings.policy_group_admins.default }; - async.each(regions.default, function (region, rcb) { - - var policies = helpers.addSource(cache, source, - ['policy', 'list', region]); - - if (!policies) return rcb(); - - if (policies.err || !policies.data) { - helpers.addResult(results, 3, - 'Unable to query for policies: ' + helpers.addError(policies), region); - return rcb(); - } + var region = helpers.objectFirstKey(cache['regionSubscription']['list']) + + var policies = helpers.addSource(cache, source, + ['policy', 'list', region]); + + if (!policies) return callback(null, results, source); + + if (policies.err || !policies.data) { + helpers.addResult(results, 3, + 'Unable to query for policies: ' + helpers.addError(policies), region); + return callback(null, results, source); + } + + if (!policies.data.length) { + helpers.addResult(results, 0, 'No policies found', region); + return callback(null, results, source); + } + var policyProtection = true; + var entered = false; + + policies.data.forEach(policy => { + if (policy.statements && + policy.statements.length) { + entered = true; + + policy.statements.forEach(statement => { + + const statementLower = statement.toLowerCase(); + + if (statementLower.indexOf('allow') > -1 && + (statementLower.indexOf('manage') > -1 || + statementLower.indexOf('use') > -1) && + (statementLower.indexOf('request.permission') === -1 && + statementLower.indexOf('!=') === -1 && + statementLower.indexOf('_delete') === -1 && + statementLower.indexOf('instance_') === -1) && + (statementLower.indexOf('instance-family') > -1 || + statementLower.indexOf('all-resources') > -1)) { + + policyProtection = false; + var statementArr = statementLower.split(' '); + var statementNormalArr = statement.split(' '); + var severity = 2; + + if (statementArr[1] === 'any-user' || statementArr[1] === 'dynamic-group') { + var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; + var compartment = statementArr[6] === 'tenancy' ? 'tenancy' : statementArr[6]; + var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[7]; + var groupType = statementArr[1]; + } else { + var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; + var compartment = statementArr[7] === 'tenancy' ? 'tenancy' : statementArr[7]; + var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[8]; + var groupType = 'The ' + statementArr[1]; + } - if (!policies.data.length) { - helpers.addResult(results, 0, 'No policies found', region); - return rcb(); - } - var policyProtection = true; - var entered = false; - - policies.data.forEach(policy => { - if (policy.statements && - policy.statements.length) { - entered = true; - - policy.statements.forEach(statement => { - - const statementLower = statement.toLowerCase(); - - if (statementLower.indexOf('allow') > -1 && - (statementLower.indexOf('manage') > -1 || - statementLower.indexOf('use') > -1) && - (statementLower.indexOf('request.permission') === -1 && - statementLower.indexOf('!=') === -1 && - statementLower.indexOf('_delete') === -1 && - statementLower.indexOf('instance_') === -1) && - (statementLower.indexOf('instance-family') > -1 || - statementLower.indexOf('all-resources') > -1)) { - - policyProtection = false; - var statementArr = statementLower.split(' '); - var statementNormalArr = statement.split(' '); - var severity = 2; - - if (statementArr[1] === 'any-user' || statementArr[1] === 'dynamic-group') { - var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; - var compartment = statementArr[6] === 'tenancy' ? 'tenancy' : statementArr[6]; - var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[7]; - var groupType = statementArr[1]; - } else { - var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; - var compartment = statementArr[7] === 'tenancy' ? 'tenancy' : statementArr[7]; - var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[8]; - var groupType = 'The ' + statementArr[1]; - } - - if (groupName === config.policy_group_admins.toLowerCase()) return; - if (statementArr.indexOf('request.user.name') > -1) { - groupType = 'The user'; - groupName = statementArr[statementArr.length - 1]; - severity = 1; - } - - helpers.addResult(results, severity, - `${groupType} ${groupName} has the ability to delete all compute instances in ${compartment} ${compartmentName}`, region, policy.id); + if (groupName === config.policy_group_admins.toLowerCase()) return; + if (statementArr.indexOf('request.user.name') > -1) { + groupType = 'The user'; + groupName = statementArr[statementArr.length - 1]; + severity = 1; } - }); - } - }); - if (policyProtection && entered) { - helpers.addResult(results, 0, 'All policies have compute instance delete protection enabled', region); + + helpers.addResult(results, severity, + `${groupType} ${groupName} has the ability to delete all compute instances in ${compartment} ${compartmentName}`, region, policy.id); + } + }); } - rcb(); - }, function () { - // Global checking goes here - callback(null, results, source); }); + + if (policyProtection && entered) { + helpers.addResult(results, 0, 'All policies have compute instance delete protection enabled', region); + } + + callback(null, results, source); } }; \ No newline at end of file diff --git a/plugins/oracle/database/dbPolicyProtection.js b/plugins/oracle/database/dbPolicyProtection.js index ac043c9a9e..0b44ea0e3f 100644 --- a/plugins/oracle/database/dbPolicyProtection.js +++ b/plugins/oracle/database/dbPolicyProtection.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/oracle'); module.exports = { @@ -21,91 +20,88 @@ module.exports = { run: function (cache, settings, callback) { var results = []; var source = {}; - var regions = helpers.regions(settings.govcloud); + var config = { policy_group_admins: settings.policy_group_admins || this.settings.policy_group_admins.default }; + + var region = helpers.objectFirstKey(cache['regionSubscription']['list']) - async.each(regions.default, function (region, rcb) { + var policies = helpers.addSource(cache, source, + ['policy', 'list', region]); - var policies = helpers.addSource(cache, source, - ['policy', 'list', region]); + if (!policies) return callback(null, results, source); - if (!policies) return rcb(); + if (policies.err || !policies.data) { + helpers.addResult(results, 3, + 'Unable to query for policies: ' + helpers.addError(policies), region); + return callback(null, results, source); + } - if (policies.err || !policies.data) { - helpers.addResult(results, 3, - 'Unable to query for policies: ' + helpers.addError(policies), region); - return rcb(); - } + if (!policies.data.length) { + helpers.addResult(results, 0, 'No policies found', region); + return callback(null, results, source); + } + var policyProtection = true; + var entered = false; - if (!policies.data.length) { - helpers.addResult(results, 0, 'No policies found', region); - return rcb(); - } - var policyProtection = true; - var entered = false; - - policies.data.forEach(policy => { - if (policy.statements && - policy.statements.length) { - entered = true; - - policy.statements.forEach(statement => { - const statementLower = statement.toLowerCase(); - - if (statementLower.indexOf('allow') > -1 && - (statementLower.indexOf('manage') > -1 || - statementLower.indexOf('use') > -1) && - (statementLower.indexOf('request.permission') === -1 && - statementLower.indexOf('!=') === -1 && - statementLower.indexOf('_delete') === -1 && - (statementLower.indexOf('db_system_') === -1 || - statementLower.indexOf('database_') === -1 || - statementLower.indexOf('db_home_') === -1)) && - (statementLower.indexOf('db-systems') > -1 || - statementLower.indexOf('databases') > -1 || - statementLower.indexOf('db-homes') > -1 || - statementLower.indexOf('all-resources') > -1)) { - - policyProtection = false; - var statementArr = statementLower.split(' '); - var statementNormalArr = statement.split(' '); - var severity = 2; - - if (statementArr[1] === 'any-user' || statementArr[1] === 'dynamic-group') { - var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; - var compartment = statementArr[6] === 'tenancy' ? 'tenancy' : statementArr[6]; - var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[7]; - var groupType = statementArr[1]; - } else { - var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; - var compartment = statementArr[7] === 'tenancy' ? 'tenancy' : statementArr[7]; - var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[8]; - var groupType = 'The ' + statementArr[1]; - } - - if (groupName === config.policy_group_admins.toLowerCase()) return; - if (statementArr.indexOf('request.user.name') > -1) { - groupType = 'The user'; - groupName = statementArr[statementArr.length - 1]; - severity = 1; - } - - helpers.addResult(results, severity, - `${groupType} ${groupName} has the ability to delete all database services in ${compartment} ${compartmentName}`, region, policy.id); + policies.data.forEach(policy => { + if (policy.statements && + policy.statements.length) { + entered = true; + + policy.statements.forEach(statement => { + const statementLower = statement.toLowerCase(); + + if (statementLower.indexOf('allow') > -1 && + (statementLower.indexOf('manage') > -1 || + statementLower.indexOf('use') > -1) && + (statementLower.indexOf('request.permission') === -1 && + statementLower.indexOf('!=') === -1 && + statementLower.indexOf('_delete') === -1 && + (statementLower.indexOf('db_system_') === -1 || + statementLower.indexOf('database_') === -1 || + statementLower.indexOf('db_home_') === -1)) && + (statementLower.indexOf('db-systems') > -1 || + statementLower.indexOf('databases') > -1 || + statementLower.indexOf('db-homes') > -1 || + statementLower.indexOf('all-resources') > -1)) { + + policyProtection = false; + var statementArr = statementLower.split(' '); + var statementNormalArr = statement.split(' '); + var severity = 2; + + if (statementArr[1] === 'any-user' || statementArr[1] === 'dynamic-group') { + var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; + var compartment = statementArr[6] === 'tenancy' ? 'tenancy' : statementArr[6]; + var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[7]; + var groupType = statementArr[1]; + } else { + var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; + var compartment = statementArr[7] === 'tenancy' ? 'tenancy' : statementArr[7]; + var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[8]; + var groupType = 'The ' + statementArr[1]; + } + + if (groupName === config.policy_group_admins.toLowerCase()) return; + if (statementArr.indexOf('request.user.name') > -1) { + groupType = 'The user'; + groupName = statementArr[statementArr.length - 1]; + severity = 1; } - }); - } - }); - if (policyProtection && entered) { - helpers.addResult(results, 0, 'All policies have database delete protection enabled', region); + helpers.addResult(results, severity, + `${groupType} ${groupName} has the ability to delete all database services in ${compartment} ${compartmentName}`, region, policy.id); + } + }); } - rcb(); - }, function () { - // Global checking goes here - callback(null, results, source); }); + + if (policyProtection && entered) { + helpers.addResult(results, 0, 'All policies have database delete protection enabled', region); + } + + callback(null, results, source); } }; \ No newline at end of file diff --git a/plugins/oracle/filestorage/nfsPolicyProtection.js b/plugins/oracle/filestorage/nfsPolicyProtection.js index 78d411fd8b..9e2052de74 100644 --- a/plugins/oracle/filestorage/nfsPolicyProtection.js +++ b/plugins/oracle/filestorage/nfsPolicyProtection.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/oracle'); module.exports = { @@ -21,93 +20,88 @@ module.exports = { run: function (cache, settings, callback) { var results = []; var source = {}; - var regions = helpers.regions(settings.govcloud); var config = { policy_group_admins: settings.policy_group_admins || this.settings.policy_group_admins.default }; - async.each(regions.default, function (region, rcb) { - - var policies = helpers.addSource(cache, source, - ['policy', 'list', region]); - - if (!policies) return rcb(); - - if (policies.err || !policies.data) { - helpers.addResult(results, 3, - 'Unable to query for policies: ' + helpers.addError(policies), region); - return rcb(); - } + var region = helpers.objectFirstKey(cache['regionSubscription']['list']) + + var policies = helpers.addSource(cache, source, + ['policy', 'list', region]); + + if (!policies) return callback(null, results, source); + + if (policies.err || !policies.data) { + helpers.addResult(results, 3, + 'Unable to query for policies: ' + helpers.addError(policies), region); + return callback(null, results, source); + } + + if (!policies.data.length) { + helpers.addResult(results, 0, 'No policies found', region); + return callback(null, results, source); + } + var policyProtection = true; + var entered = false; + + policies.data.forEach(policy => { + if (policy.statements && + policy.statements.length) { + entered = true; + policy.statements.forEach(statement => { + + const statementLower = statement.toLowerCase(); + + if (statementLower.indexOf('allow') > -1 && + (statementLower.indexOf('manage') > -1 || + statementLower.indexOf('use') > -1) && + (statementLower.indexOf('request.permission') === -1 && + statementLower.indexOf('!=') === -1 && + statementLower.indexOf('_delete') === -1 && + (statementLower.indexOf('file_system_') === -1 || + statementLower.indexOf('mount_target_') === -1 || + statementLower.indexOf('export_set_') === -1)) && + (statementLower.indexOf('file-systems') > -1 || + statementLower.indexOf('mount-targets') > -1 || + statementLower.indexOf('export-sets') > -1 || + statementLower.indexOf('all-resources') > -1)) { + + policyProtection = false; + var statementArr = statementLower.split(' '); + var statementNormalArr = statement.split(' '); + var severity = 2; + + if (statementArr[1] === 'any-user' || statementArr[1] === 'dynamic-group') { + var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; + var compartment = statementArr[6] === 'tenancy' ? 'tenancy' : statementArr[6]; + var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[7]; + var groupType = statementArr[1]; + } else { + var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; + var compartment = statementArr[7] === 'tenancy' ? 'tenancy' : statementArr[7]; + var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[8]; + var groupType = 'The ' + statementArr[1]; + } - if (!policies.data.length) { - helpers.addResult(results, 0, 'No policies found', region); - return rcb(); - } - var policyProtection = true; - var entered = false; - - policies.data.forEach(policy => { - if (policy.statements && - policy.statements.length) { - entered = true; - policy.statements.forEach(statement => { - - const statementLower = statement.toLowerCase(); - - if (statementLower.indexOf('allow') > -1 && - (statementLower.indexOf('manage') > -1 || - statementLower.indexOf('use') > -1) && - (statementLower.indexOf('request.permission') === -1 && - statementLower.indexOf('!=') === -1 && - statementLower.indexOf('_delete') === -1 && - (statementLower.indexOf('file_system_') === -1 || - statementLower.indexOf('mount_target_') === -1 || - statementLower.indexOf('export_set_') === -1)) && - (statementLower.indexOf('file-systems') > -1 || - statementLower.indexOf('mount-targets') > -1 || - statementLower.indexOf('export-sets') > -1 || - statementLower.indexOf('all-resources') > -1)) { - - policyProtection = false; - var statementArr = statementLower.split(' '); - var statementNormalArr = statement.split(' '); - var severity = 2; - - if (statementArr[1] === 'any-user' || statementArr[1] === 'dynamic-group') { - var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; - var compartment = statementArr[6] === 'tenancy' ? 'tenancy' : statementArr[6]; - var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[7]; - var groupType = statementArr[1]; - } else { - var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; - var compartment = statementArr[7] === 'tenancy' ? 'tenancy' : statementArr[7]; - var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[8]; - var groupType = 'The ' + statementArr[1]; - } - - if (groupName === config.policy_group_admins.toLowerCase()) return; - if (statementArr.indexOf('request.user.name') > -1) { - groupType = 'The user'; - groupName = statementArr[statementArr.length - 1]; - severity = 1; - } - - helpers.addResult(results, severity, - `${groupType} ${groupName} has the ability to delete all file storage services in ${compartment} ${compartmentName}`, region, policy.id); + if (groupName === config.policy_group_admins.toLowerCase()) return; + if (statementArr.indexOf('request.user.name') > -1) { + groupType = 'The user'; + groupName = statementArr[statementArr.length - 1]; + severity = 1; } - }); - } - }); - if (policyProtection && entered) { - helpers.addResult(results, 0, 'All policies have file storage delete protection enabled', region); + helpers.addResult(results, severity, + `${groupType} ${groupName} has the ability to delete all file storage services in ${compartment} ${compartmentName}`, region, policy.id); + } + }); } - - rcb(); - }, function () { - // Global checking goes here - callback(null, results, source); }); + + if (policyProtection && entered) { + helpers.addResult(results, 0, 'All policies have file storage delete protection enabled', region); + } + + callback(null, results, source); } }; \ No newline at end of file diff --git a/plugins/oracle/identity/excessivePolicies.js b/plugins/oracle/identity/excessivePolicies.js index a297bc2d4f..01900074e8 100644 --- a/plugins/oracle/identity/excessivePolicies.js +++ b/plugins/oracle/identity/excessivePolicies.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/oracle/'); module.exports = { @@ -31,7 +30,6 @@ module.exports = { run: function(cache, settings, callback) { var results = []; var source = {}; - var regions = helpers.regions(settings.govcloud); var config = { excessive_policy_fail: settings.excessive_policy_fail || this.settings.excessive_policy_fail.default, excessive_policy_warn: settings.excessive_policy_warn || this.settings.excessive_policy_warn.default @@ -39,42 +37,39 @@ module.exports = { var custom = helpers.isCustom(settings, this.settings); - async.each(regions.default, function(region, rcb){ + var region = helpers.objectFirstKey(cache['regionSubscription']['list']) - if (helpers.checkRegionSubscription(cache, source, results, region)) { + if (helpers.checkRegionSubscription(cache, source, results, region)) { - var policies = helpers.addSource(cache, source, - ['policy', 'list', region]); + var policies = helpers.addSource(cache, source, + ['policy', 'list', region]); - if (!policies) return rcb(); + if (!policies) return callback(null, results, source); - if (policies.err || !policies.data) { - helpers.addResult(results, 3, - 'Unable to query for policies: ' + helpers.addError(policies), region); - return rcb(); - } + if (policies.err || !policies.data) { + helpers.addResult(results, 3, + 'Unable to query for policies: ' + helpers.addError(policies), region); + return callback(null, results, source); + } - if (!policies.data.length) { - helpers.addResult(results, 0, 'No policies found', region); - return rcb(); - } + if (!policies.data.length) { + helpers.addResult(results, 0, 'No policies found', region); + return callback(null, results, source); + } - var policyAmt = policies.data.length; + var policyAmt = policies.data.length; - var returnMsg = ' number of policies: ' + policyAmt + ' found'; + var returnMsg = ' number of policies: ' + policyAmt + ' found'; - if (policyAmt > config.excessive_policy_fail) { - helpers.addResult(results, 2, 'Excessive' + returnMsg, region, null, custom); - } else if (policyAmt > config.excessive_policy_warn) { - helpers.addResult(results, 1, 'Large' + returnMsg, region, null, custom); - } else { - helpers.addResult(results, 0, 'Acceptable' + returnMsg, region, null, custom); - } + if (policyAmt > config.excessive_policy_fail) { + helpers.addResult(results, 2, 'Excessive' + returnMsg, region, null, custom); + } else if (policyAmt > config.excessive_policy_warn) { + helpers.addResult(results, 1, 'Large' + returnMsg, region, null, custom); + } else { + helpers.addResult(results, 0, 'Acceptable' + returnMsg, region, null, custom); } - rcb(); - }, function(){ - // Global checking goes here - callback(null, results, source); - }); + } + + callback(null, results, source); } }; \ No newline at end of file diff --git a/plugins/oracle/identity/excessivePolicyStatements.js b/plugins/oracle/identity/excessivePolicyStatements.js index ce5e984d02..de527d8427 100644 --- a/plugins/oracle/identity/excessivePolicyStatements.js +++ b/plugins/oracle/identity/excessivePolicyStatements.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/oracle/'); module.exports = { @@ -30,51 +29,48 @@ module.exports = { run: function(cache, settings, callback) { var results = []; var source = {}; - var regions = helpers.regions(settings.govcloud); var config = { excessive_policy_statement_fail: settings.excessive_policy_statement_fail || this.settings.excessive_policy_statement_fail.default, excessive_policy_statement_warn: settings.excessive_policy_statement_warn || this.settings.excessive_policy_statement_warn.default }; var custom = helpers.isCustom(settings, this.settings); + + var region = helpers.objectFirstKey(cache['regionSubscription']['list']) + - async.each(regions.default, function(region, rcb){ + if (helpers.checkRegionSubscription(cache, source, results, region)) { - if (helpers.checkRegionSubscription(cache, source, results, region)) { + var policies = helpers.addSource(cache, source, + ['policy', 'list', region]); - var policies = helpers.addSource(cache, source, - ['policy', 'list', region]); + if (!policies) return callback(null, results, source); - if (!policies) return rcb(); + if (policies.err || !policies.data) { + helpers.addResult(results, 3, + 'Unable to query for policies: ' + helpers.addError(policies), region); + return callback(null, results, source); + } - if (policies.err || !policies.data) { - helpers.addResult(results, 3, - 'Unable to query for policies: ' + helpers.addError(policies), region); - return rcb(); - } + if (!policies.data.length) { + helpers.addResult(results, 0, 'No policies found', region); + return callback(null, results, source); + } + + policies.data.forEach(policy => { + var policyAmt = policy.statements.length; + var returnMsg = ' number of policy statements: ' + policyAmt + ' found'; - if (!policies.data.length) { - helpers.addResult(results, 0, 'No policies found', region); - return rcb(); + if (policyAmt > config.excessive_policy_statement_fail) { + helpers.addResult(results, 2, 'Excessive' + returnMsg, region, policy.id, custom); + } else if (policyAmt > config.excessive_policy_statement_warn) { + helpers.addResult(results, 1, 'Large' + returnMsg, region, policy.id, custom); + } else { + helpers.addResult(results, 0, 'Acceptable' + returnMsg, region, policy.id, custom); } + }); + } - policies.data.forEach(policy => { - var policyAmt = policy.statements.length; - var returnMsg = ' number of policy statements: ' + policyAmt + ' found'; - - if (policyAmt > config.excessive_policy_statement_fail) { - helpers.addResult(results, 2, 'Excessive' + returnMsg, region, policy.id, custom); - } else if (policyAmt > config.excessive_policy_statement_warn) { - helpers.addResult(results, 1, 'Large' + returnMsg, region, policy.id, custom); - } else { - helpers.addResult(results, 0, 'Acceptable' + returnMsg, region, policy.id, custom); - } - }); - } - rcb(); - }, function(){ - // Global checking goes here - callback(null, results, source); - }); + callback(null, results, source); } }; \ No newline at end of file diff --git a/plugins/oracle/identity/minPasswordLength.js b/plugins/oracle/identity/minPasswordLength.js index 5e91eb49b4..bce5b6598b 100644 --- a/plugins/oracle/identity/minPasswordLength.js +++ b/plugins/oracle/identity/minPasswordLength.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/oracle'); module.exports = { @@ -18,15 +17,8 @@ module.exports = { run: function(cache, settings, callback) { var results = []; var source = {}; - var defaultRegion = ''; - if (cache.authenticationPolicy && - cache.authenticationPolicy.get && - Object.keys(cache.authenticationPolicy.get).length) { - defaultRegion = helpers.objectFirstKey(cache.authenticationPolicy.get); - } else { - return callback(null, results, source); - } + var defaultRegion = helpers.objectFirstKey(cache['regionSubscription']['list']); var authenticationPolicy = helpers.addSource(cache, source, ['authenticationPolicy', 'get', defaultRegion]); @@ -48,7 +40,7 @@ module.exports = { var passwordPolicy = policy.passwordPolicy; if (passwordPolicy && passwordPolicy.minimumPasswordLength) { - if (passwordPolicy.minimumPasswordLength > 14) { + if (passwordPolicy.minimumPasswordLength >= 14) { helpers.addResult(results, 0, 'Minimum password length of: ' + passwordPolicy.minimumPasswordLength + ' is suitable', 'global', authenticationPolicy.data.compartmentId); } else if (passwordPolicy && passwordPolicy.minimumPasswordLength && diff --git a/plugins/oracle/identity/passwordRequiresLowercase.js b/plugins/oracle/identity/passwordRequiresLowercase.js index b96bab47c0..47db3fb743 100644 --- a/plugins/oracle/identity/passwordRequiresLowercase.js +++ b/plugins/oracle/identity/passwordRequiresLowercase.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/oracle'); module.exports = { @@ -16,17 +15,9 @@ module.exports = { run: function(cache, settings, callback) { var results = []; var source = {}; - var defaultRegion = ''; - - if (cache.authenticationPolicy && - cache.authenticationPolicy.get && - Object.keys(cache.authenticationPolicy.get).length && - Object.keys(cache.authenticationPolicy.get).length > 0) { - defaultRegion = helpers.objectFirstKey(cache.authenticationPolicy.get); - } else { - return callback(null, results, source); - } + var defaultRegion = helpers.objectFirstKey(cache['regionSubscription']['list']); + var authenticationPolicy = helpers.addSource(cache, source, ['authenticationPolicy', 'get', defaultRegion]); diff --git a/plugins/oracle/identity/passwordRequiresNumbers.js b/plugins/oracle/identity/passwordRequiresNumbers.js index 8a2cae06a0..088ca701e4 100644 --- a/plugins/oracle/identity/passwordRequiresNumbers.js +++ b/plugins/oracle/identity/passwordRequiresNumbers.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/oracle'); module.exports = { @@ -16,16 +15,8 @@ module.exports = { run: function(cache, settings, callback) { var results = []; var source = {}; - var defaultRegion = ''; - - if (cache.authenticationPolicy && - cache.authenticationPolicy.get && - Object.keys(cache.authenticationPolicy.get).length && - Object.keys(cache.authenticationPolicy.get).length > 0) { - defaultRegion = helpers.objectFirstKey(cache.authenticationPolicy.get); - } else { - return callback(null, results, source); - } + + var defaultRegion = helpers.objectFirstKey(cache['regionSubscription']['list']); var authenticationPolicy = helpers.addSource(cache, source, ['authenticationPolicy', 'get', defaultRegion]); diff --git a/plugins/oracle/identity/passwordRequiresSymbols.js b/plugins/oracle/identity/passwordRequiresSymbols.js index fff741bd45..1b27f207c6 100644 --- a/plugins/oracle/identity/passwordRequiresSymbols.js +++ b/plugins/oracle/identity/passwordRequiresSymbols.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/oracle'); module.exports = { @@ -16,16 +15,8 @@ module.exports = { run: function(cache, settings, callback) { var results = []; var source = {}; - var defaultRegion = ''; - - if (cache.authenticationPolicy && - cache.authenticationPolicy.get && - Object.keys(cache.authenticationPolicy.get).length && - Object.keys(cache.authenticationPolicy.get).length > 0) { - defaultRegion = helpers.objectFirstKey(cache.authenticationPolicy.get); - } else { - return callback(null, results, source); - } + + var defaultRegion = helpers.objectFirstKey(cache['regionSubscription']['list']); var authenticationPolicy = helpers.addSource(cache, source, ['authenticationPolicy', 'get', defaultRegion]); diff --git a/plugins/oracle/identity/passwordRequiresUppercase.js b/plugins/oracle/identity/passwordRequiresUppercase.js index f80f14a504..4dda50834e 100644 --- a/plugins/oracle/identity/passwordRequiresUppercase.js +++ b/plugins/oracle/identity/passwordRequiresUppercase.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/oracle'); module.exports = { @@ -16,16 +15,8 @@ module.exports = { run: function(cache, settings, callback) { var results = []; var source = {}; - var defaultRegion = ''; - - if (cache.authenticationPolicy && - cache.authenticationPolicy.get && - Object.keys(cache.authenticationPolicy.get).length && - Object.keys(cache.authenticationPolicy.get).length > 0) { - defaultRegion = helpers.objectFirstKey(cache.authenticationPolicy.get); - } else { - return callback(null, results, source); - } + + var defaultRegion = helpers.objectFirstKey(cache['regionSubscription']['list']); var authenticationPolicy = helpers.addSource(cache, source, ['authenticationPolicy', 'get', defaultRegion]); diff --git a/plugins/oracle/identity/policyLeastPrivilege.js b/plugins/oracle/identity/policyLeastPrivilege.js index c88b85d044..48197d1b20 100644 --- a/plugins/oracle/identity/policyLeastPrivilege.js +++ b/plugins/oracle/identity/policyLeastPrivilege.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/oracle'); module.exports = { @@ -29,91 +28,86 @@ module.exports = { run: function (cache, settings, callback) { var results = []; var source = {}; - var regions = helpers.regions(settings.govcloud); var config = { policy_group_admins: settings.policy_group_admins || this.settings.policy_group_admins.default }; + var region = helpers.objectFirstKey(cache['regionSubscription']['list']) + + var policies = helpers.addSource(cache, source, + ['policy', 'list', region]); + + if (!policies) return callback(null, results, source); + + if (policies.err || !policies.data) { + helpers.addResult(results, 3, + 'Unable to query for policies: ' + helpers.addError(policies), region); + return callback(null, results, source); + } + + if (!policies.data.length) { + helpers.addResult(results, 0, 'No policies found', region); + return callback(null, results, source); + } + var policyProtection = true; + var entered = false; + policies.data.forEach(policy => { + if (policy.statements && + policy.statements.length) { + entered = true; + policy.statements.forEach(statement => { + + const statementLower = statement.toLowerCase(); + + if (statementLower.indexOf('allow') > -1 && + (statementLower.indexOf('manage') > -1 || + statementLower.indexOf('use') > -1) && + ((statementLower.indexOf('request.permission') === -1 && + statementLower.indexOf('!=') === -1) || + (statementLower.indexOf('request.operation') === -1 && + statementLower.indexOf('!=') === -1))) { + + policyProtection = false; + var statementArr = statementLower.split(' '); + var statementNormalArr = statement.split(' '); + var severity = 2; + + if (statementArr[1] === 'any-user' || statementArr[1] === 'dynamic-group') { + var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; + var resourceType = statementArr[4]; + var compartment = statementArr[6] === 'tenancy' ? 'tenancy' : statementArr[6]; + var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[7]; + var groupType = statementArr[1]; + var verb = statementArr[3]; + } else { + var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; + var resourceType = statementArr[5]; + var compartment = statementArr[7] === 'tenancy' ? 'tenancy' : statementArr[7]; + var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[8]; + var groupType = statementArr[1]; + var verb = statementArr[4]; + } - async.each(regions.default, function (region, rcb) { - var policies = helpers.addSource(cache, source, - ['policy', 'list', region]); - - if (!policies) return rcb(); - - if (policies.err || !policies.data) { - helpers.addResult(results, 3, - 'Unable to query for policies: ' + helpers.addError(policies), region); - return rcb(); - } - - if (!policies.data.length) { - helpers.addResult(results, 0, 'No policies found', region); - return rcb(); - } - var policyProtection = true; - var entered = false; - policies.data.forEach(policy => { - if (policy.statements && - policy.statements.length) { - entered = true; - policy.statements.forEach(statement => { - - const statementLower = statement.toLowerCase(); - - if (statementLower.indexOf('allow') > -1 && - (statementLower.indexOf('manage') > -1 || - statementLower.indexOf('use') > -1) && - ((statementLower.indexOf('request.permission') === -1 && - statementLower.indexOf('!=') === -1) || - (statementLower.indexOf('request.operation') === -1 && - statementLower.indexOf('!=') === -1))) { - - policyProtection = false; - var statementArr = statementLower.split(' '); - var statementNormalArr = statement.split(' '); - var severity = 2; - - if (statementArr[1] === 'any-user' || statementArr[1] === 'dynamic-group') { - var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; - var resourceType = statementArr[4]; - var compartment = statementArr[6] === 'tenancy' ? 'tenancy' : statementArr[6]; - var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[7]; - var groupType = statementArr[1]; - var verb = statementArr[3]; - } else { - var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; - var resourceType = statementArr[5]; - var compartment = statementArr[7] === 'tenancy' ? 'tenancy' : statementArr[7]; - var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[8]; - var groupType = statementArr[1]; - var verb = statementArr[4]; - } - - var adminsArr = config.policy_group_admins.toLowerCase().replace(' ', '').split(','); - - if (adminsArr.indexOf(groupName) > -1) return; - if (statementArr.indexOf('request.user.name') > -1) { - groupType = 'User'; - groupName = statementArr[statementArr.length - 1]; - severity = 1; - } + var adminsArr = config.policy_group_admins.toLowerCase().replace(' ', '').split(','); - helpers.addResult(results, severity, - `${groupType} ${groupName} has the ability to ${verb} ${resourceType} in ${compartment} ${compartmentName}`, region, policy.id); + if (adminsArr.indexOf(groupName) > -1) return; + if (statementArr.indexOf('request.user.name') > -1) { + groupType = 'User'; + groupName = statementArr[statementArr.length - 1]; + severity = 1; } - }); - } - }); - if (policyProtection && entered) { - helpers.addResult(results, 0, 'All policies follow least access.', region); + helpers.addResult(results, severity, + `${groupType} ${groupName} has the ability to ${verb} ${resourceType} in ${compartment} ${compartmentName}`, region, policy.id); + } + }); } - - rcb(); - }, function () { - // Global checking goes here - callback(null, results, source); }); + + if (policyProtection && entered) { + helpers.addResult(results, 0, 'All policies follow least access.', region); + } + + callback(null, results, source); } -}; +}; \ No newline at end of file diff --git a/plugins/oracle/identity/usersMfaEnabled.js b/plugins/oracle/identity/usersMfaEnabled.js index 9c51f6ccc7..8a7fc2ff9a 100644 --- a/plugins/oracle/identity/usersMfaEnabled.js +++ b/plugins/oracle/identity/usersMfaEnabled.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/oracle'); module.exports = { @@ -21,24 +20,23 @@ module.exports = { run: function (cache, settings, callback) { var results = []; var source = {}; - var regions = helpers.regions(settings.govcloud); - var noMFAUsers = []; - async.each(regions.user, function (region, rcb) { + var region = helpers.objectFirstKey(cache['regionSubscription']['list']); + var users = helpers.addSource(cache, source, ['user', 'list', region]); - if (!users) return rcb(); + if (!users) return callback(null, results, source); if (users.err || !users.data) { helpers.addResult(results, 3, 'Unable to query for user MFA status: ' + helpers.addError(users)); - return rcb(); + return callback(null, results, source); } if (users.data.length < 2) { helpers.addResult(results, 0, 'No user accounts found'); - return rcb(); + return callback(null, results, source); } users.data.forEach(user => { @@ -48,10 +46,7 @@ module.exports = { helpers.addResult(results, 2, 'The user has MFA disabled', 'global', user.id); } }); - rcb(); - }, function () { - // Global checking goes here + callback(null, results, source); - }); } }; diff --git a/plugins/oracle/objectstore/objectPolicyProtection.js b/plugins/oracle/objectstore/objectPolicyProtection.js index f636eeb8fb..64b357ebd5 100644 --- a/plugins/oracle/objectstore/objectPolicyProtection.js +++ b/plugins/oracle/objectstore/objectPolicyProtection.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/oracle'); module.exports = { @@ -25,90 +24,86 @@ module.exports = { run: function (cache, settings, callback) { var results = []; var source = {}; - var regions = helpers.regions(settings.govcloud); + var config = { policy_group_admins: settings.policy_group_admins || this.settings.policy_group_admins.default }; + + var region = helpers.objectFirstKey(cache['regionSubscription']['list']); + + var policies = helpers.addSource(cache, source, + ['policy', 'list', region]); + + if (!policies) return callback(null, results, source); + + if (policies.err || !policies.data) { + helpers.addResult(results, 3, + 'Unable to query for policies: ' + helpers.addError(policies), region); + return callback(null, results, source); + } + + if (!policies.data.length) { + helpers.addResult(results, 0, 'No policies found', region); + return callback(null, results, source); + } + var policyProtection = true; + var entered = false; + policies.data.forEach(policy => { + if (policy.statements && + policy.statements.length) { + entered = true; + policy.statements.forEach(statement => { + + const statementLower = statement.toLowerCase(); + + if (statementLower.indexOf('allow') > -1 && + (statementLower.indexOf('manage') > -1 || + statementLower.indexOf('use') > -1) && + (statementLower.indexOf('request.permission') === -1 && + statementLower.indexOf('!=') === -1 && + statementLower.indexOf('_delete') === -1 && + (statementLower.indexOf('object_') === -1 || + statementLower.indexOf('bucket_') === -1)) && + (statementLower.indexOf('objects') > -1 || + statementLower.indexOf('buckets') > -1 || + statementLower.indexOf('all-resources') > -1)) { + + policyProtection = false; + var statementArr = statementLower.split(' '); + var statementNormalArr = statement.split(' '); + var severity = 2; + + if (statementArr[1] === 'any-user' || statementArr[1] === 'dynamic-group') { + var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; + var compartment = statementArr[6] === 'tenancy' ? 'tenancy' : statementArr[6]; + var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[7]; + var groupType = statementArr[1]; + } else { + var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; + var compartment = statementArr[7] === 'tenancy' ? 'tenancy' : statementArr[7]; + var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[8]; + var groupType = 'The ' + statementArr[1]; + } - async.each(regions.default, function (region, rcb) { - - var policies = helpers.addSource(cache, source, - ['policy', 'list', region]); - - if (!policies) return rcb(); - - if (policies.err || !policies.data) { - helpers.addResult(results, 3, - 'Unable to query for policies: ' + helpers.addError(policies), region); - return rcb(); - } - - if (!policies.data.length) { - helpers.addResult(results, 0, 'No policies found', region); - return rcb(); - } - var policyProtection = true; - var entered = false; - policies.data.forEach(policy => { - if (policy.statements && - policy.statements.length) { - entered = true; - policy.statements.forEach(statement => { - - const statementLower = statement.toLowerCase(); - - if (statementLower.indexOf('allow') > -1 && - (statementLower.indexOf('manage') > -1 || - statementLower.indexOf('use') > -1) && - (statementLower.indexOf('request.permission') === -1 && - statementLower.indexOf('!=') === -1 && - statementLower.indexOf('_delete') === -1 && - (statementLower.indexOf('object_') === -1 || - statementLower.indexOf('bucket_') === -1)) && - (statementLower.indexOf('objects') > -1 || - statementLower.indexOf('buckets') > -1 || - statementLower.indexOf('all-resources') > -1)) { - - policyProtection = false; - var statementArr = statementLower.split(' '); - var statementNormalArr = statement.split(' '); - var severity = 2; - - if (statementArr[1] === 'any-user' || statementArr[1] === 'dynamic-group') { - var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; - var compartment = statementArr[6] === 'tenancy' ? 'tenancy' : statementArr[6]; - var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[7]; - var groupType = statementArr[1]; - } else { - var groupName = statementArr[2] === 'to' ? '' : statementNormalArr[2]; - var compartment = statementArr[7] === 'tenancy' ? 'tenancy' : statementArr[7]; - var compartmentName = (!statementArr[7] || statementArr[7] === 'tenancy') ? '' : statementNormalArr[8]; - var groupType = 'The ' + statementArr[1]; - } - - if (groupName === config.policy_group_admins.toLowerCase()) return; - if (statementArr.indexOf('request.user.name') > -1) { - groupType = 'The user'; - groupName = statementArr[statementArr.length - 1]; - severity = 1; - } - - helpers.addResult(results, severity, - `${groupType} ${groupName} has the ability to delete all object store services in ${compartment} ${compartmentName}`, region, policy.id); + if (groupName === config.policy_group_admins.toLowerCase()) return; + if (statementArr.indexOf('request.user.name') > -1) { + groupType = 'The user'; + groupName = statementArr[statementArr.length - 1]; + severity = 1; } - }); - } - }); - if (policyProtection && entered) { - helpers.addResult(results, 0, 'All policies have object store delete protection enabled', region); + helpers.addResult(results, severity, + `${groupType} ${groupName} has the ability to delete all object store services in ${compartment} ${compartmentName}`, region, policy.id); + } + }); } - - rcb(); - }, function () { - // Global checking goes here - callback(null, results, source); }); + + if (policyProtection && entered) { + helpers.addResult(results, 0, 'All policies have object store delete protection enabled', region); + } + + callback(null, results, source); } }; \ No newline at end of file