From 6c05b1da714bf721f5ac762ac227bc1dc5b9a44b Mon Sep 17 00:00:00 2001 From: fatimaaqua Date: Mon, 31 Aug 2026 09:56:58 +0000 Subject: [PATCH 1/3] syncing the saas with opensource --- collectors/aws/accessanalyzer/listFindings.js | 6 +- .../aws/accessanalyzer/listFindingsV2.js | 6 +- .../aws/apigateway/getClientCertificate.js | 4 +- collectors/aws/apigateway/getIntegration.js | 4 +- .../aws/appmesh/describeVirtualGateway.js | 4 +- .../describeLaunchConfigurations.js | 4 +- .../describeNotificationConfigurations.js | 4 +- collectors/aws/cloudfront/getDistribution.js | 4 +- collectors/aws/cloudtrail/listTags.js | 4 +- .../aws/cloudwatch/getEc2MetricStatistics.js | 4 +- .../aws/cloudwatch/getEcMetricStatistics.js | 4 +- .../aws/cloudwatch/getEsMetricStatistics.js | 4 +- .../aws/cloudwatch/getRdsMetricStatistics.js | 4 +- .../getRdsReadIOPSMetricStatistics.js | 4 +- .../getRdsWriteIOPSMetricStatistics.js | 4 +- .../cloudwatch/getredshiftMetricStatistics.js | 4 +- .../getRepositoryPermissionsPolicy.js | 28 +++ collectors/aws/codebuild/batchGetBuilds.js | 37 +++ collectors/aws/codebuild/batchGetProjects.js | 4 +- collectors/aws/collector.js | 58 +++-- collectors/aws/collector_multipart.js | 4 +- .../instanceAttachmentStorageConfigs.js | 4 +- ...listInstanceCallRecordingStorageConfigs.js | 4 +- ...istInstanceChatTranscriptStorageConfigs.js | 4 +- ...istInstanceExportedReportStorageConfigs.js | 4 +- .../listInstanceMediaStreamStorageConfigs.js | 4 +- .../aws/dynamodb/describeContinuousBackups.js | 4 +- collectors/aws/dynamodb/describeTable.js | 4 +- collectors/aws/dynamodb/listBackups.js | 4 +- collectors/aws/ec2/describeAddresses.js | 69 ++++++ .../aws/ec2/describeSnapshotAttribute.js | 4 +- collectors/aws/ec2/describeSnapshots.js | 8 +- collectors/aws/ec2/describeSubnets.js | 4 +- collectors/aws/ecs/describeCluster.js | 4 +- .../aws/ecs/describeContainerInstances.js | 4 +- collectors/aws/ecs/describeServices.js | 4 +- collectors/aws/ecs/describeTasks.js | 4 +- collectors/aws/ecs/listContainerInstances.js | 4 +- collectors/aws/ecs/listServices.js | 4 +- collectors/aws/ecs/listTasks.js | 4 +- collectors/aws/eks/describeCluster.js | 4 +- collectors/aws/eks/describeNodegroups.js | 4 +- collectors/aws/eks/listNodegroups.js | 4 +- .../elasticache/describeCacheSubnetGroups.js | 4 +- .../describeConfigurationSettings.js | 4 +- collectors/aws/elb/describeInstanceHealth.js | 4 +- .../aws/elb/describeLoadBalancerAttributes.js | 4 +- .../aws/elb/describeLoadBalancerPolicies.js | 4 +- collectors/aws/elb/describeTags.js | 4 +- collectors/aws/elbv2/describeListeners.js | 4 +- .../elbv2/describeLoadBalancerAttributes.js | 4 +- collectors/aws/elbv2/describeTags.js | 4 +- collectors/aws/elbv2/describeTargetGroups.js | 4 +- .../aws/emr/describeSecurityConfiguration.js | 4 +- .../aws/firehose/describeDeliveryStream.js | 4 +- .../describePublishingDestination.js | 4 +- collectors/aws/guardduty/getDetector.js | 4 +- collectors/aws/guardduty/getFindings.js | 4 +- collectors/aws/guardduty/getMasterAccount.js | 4 +- collectors/aws/guardduty/listFindings.js | 4 +- .../guardduty/listPublishingDestinations.js | 4 +- .../aws/iam/generateCredentialReport.js | 2 +- collectors/aws/iam/getGroupPolicy.js | 4 +- collectors/aws/iam/getInstanceProfile.js | 4 +- collectors/aws/iam/getPolicyVersion.js | 4 +- collectors/aws/iam/getRole.js | 4 +- collectors/aws/iam/getRolePolicy.js | 4 +- collectors/aws/iam/getUserPolicy.js | 4 +- collectors/aws/iam/listRoles.js | 4 +- collectors/aws/kinesis/describeStream.js | 4 +- collectors/aws/kms/getKeyPolicy.js | 4 +- collectors/aws/kms/listGrants.js | 6 +- .../aws/lexmodelsv2/describeBotAlias.js | 4 +- collectors/aws/lookoutvision/describeModel.js | 4 +- collectors/aws/managedblockchain/getMember.js | 4 +- collectors/aws/mwaa/getEnvironment.js | 4 +- .../getEncryptionSecurityPolicy.js | 4 +- .../getNetworkSecurityPolicy.js | 4 +- .../listEncryptionSecurityPolicies.js | 4 +- .../listNetworkSecurityPolicies.js | 4 +- collectors/aws/rds/describeDBParameters.js | 6 +- collectors/aws/s3/getBucketAcl.js | 4 +- collectors/aws/s3/getBucketEncryption.js | 4 +- .../aws/s3/getBucketLifecycleConfiguration.js | 4 +- collectors/aws/s3/getBucketLocation.js | 4 +- collectors/aws/s3/getBucketLogging.js | 4 +- collectors/aws/s3/getBucketPolicy.js | 4 +- collectors/aws/s3/getBucketPolicyStatus.js | 4 +- collectors/aws/s3/getBucketTagging.js | 4 +- collectors/aws/s3/getBucketVersioning.js | 4 +- collectors/aws/s3/getBucketWebsite.js | 4 +- .../aws/s3/getObjectLockConfiguration.js | 4 +- collectors/aws/s3/getPublicAccessBlock.js | 4 +- collectors/aws/s3/index.js | 14 +- .../aws/s3control/getPublicAccessBlock.js | 4 +- collectors/aws/securityhub/getFindings.js | 4 +- .../aws/ses/getIdentityDkimAttributes.js | 4 +- collectors/aws/sqs/getQueueAttributes.js | 4 +- .../aws/ssm/describeDocumentPermission.js | 48 ++++ collectors/aws/ssm/describeParameters.js | 4 +- .../storagegateway/describeNFSFileShares.js | 43 ++++ .../storagegateway/describeSMBFileShares.js | 43 ++++ .../aws/storagegateway/listFileShares.js | 45 ++++ .../describeTrustedAdvisorCheckResult.js | 4 +- .../aws/wafregional/listResourcesForWebACL.js | 4 +- collectors/aws/wafv2/getWebACL.js | 4 +- .../aws/wafv2/getWebACLForCognitoUserPool.js | 4 +- .../aws/wafv2/listResourcesForWebACL.js | 4 +- engine.spec.js | 2 + exports.spec.js | 2 + helpers/aws/api.js | 216 ++++++++++++++++- helpers/aws/api_multipart.js | 219 +++++++++++++++++- helpers/aws/functions.js | 133 ++++++++++- helpers/aws/regions.js | 19 +- helpers/aws/regions_china.js | 11 +- helpers/aws/regions_gov.js | 11 +- helpers/aws/regions_gov_fedramp_east_1.js | 11 +- helpers/aws/regions_gov_fedramp_west_1.js | 11 +- helpers/aws/resources.js | 71 +++++- helpers/azure/api.js | 18 +- helpers/azure/functions.js | 2 +- helpers/google/index.js | 9 +- helpers/oracle/regions.js | 16 +- .../cloudformationAdminPriviliges.js | 47 ++-- plugins/aws/ec2/appTierInstanceIamRole.js | 2 +- .../aws/ec2/vpcPeeringLeastAccessRoutes.js | 4 +- plugins/aws/ec2/webTierInstanceIamRole.js | 2 +- .../aws/ecr/ecrRepositoryTagImmutability.js | 8 +- .../ecr/ecrRepositoryTagImmutability.spec.js | 50 ++++ plugins/aws/eks/eksKubernetesVersion.js | 5 +- plugins/aws/eks/eksKubernetesVersion.spec.js | 2 +- plugins/aws/iam/accessKeysLastUsed.spec.js | 2 +- plugins/aws/iam/iamPoliciesPresent.js | 12 + plugins/aws/iam/iamRolePolicies.js | 77 +++++- plugins/aws/iam/iamUserAdmins.js | 122 +++++++++- plugins/aws/iam/iamUserUnauthorizedToEdit.js | 77 +++++- plugins/aws/iam/iamUserWithoutPermissions.js | 41 +++- plugins/aws/iam/rolePolicyUnusedServices.js | 104 ++++++++- .../imageRecipeVolumeEncrypted.js | 14 +- plugins/aws/lambda/lambdaAdminPrivileges.js | 86 +++---- .../aws/lambda/lambdaEnhancedMonitoring.js | 11 +- .../lambda/lambdaEnhancedMonitoring.spec.js | 38 +++ .../aws/mwaa/environmentAdminPrivileges.js | 34 ++- .../cosmosdb/cosmosPublicAccessDisabled.js | 1 - plugins/azure/keyvaults/keyVaultKeyExpiry.js | 8 + .../azure/keyvaults/keyVaultKeyExpiry.spec.js | 13 ++ .../keyvaults/keyVaultKeyExpiryNonRbac.js | 8 + .../keyVaultKeyExpiryNonRbac.spec.js | 13 ++ .../azure/keyvaults/keyVaultSecretExpiry.js | 8 + .../keyvaults/keyVaultSecretExpiry.spec.js | 13 ++ .../keyvaults/keyVaultSecretExpiryNonRbac.js | 8 + .../keyVaultSecretExpiryNonRbac.spec.js | 13 ++ .../azure/monitor/logProfileArchiveData.js | 70 ++---- .../monitor/logProfileArchiveData.spec.js | 158 +++++-------- plugins/azure/monitor/monitorResourceSku.js | 5 +- .../azure/monitor/monitorResourceSku.spec.js | 15 ++ plugins/azure/openai/accountCMKEncrypted.js | 10 +- .../azure/openai/accountCMKEncrypted.spec.js | 9 +- .../azure/openai/accountDiagnosticLogging.js | 3 + .../openai/accountDiagnosticLogging.spec.js | 8 +- plugins/azure/openai/accountHasTags.js | 4 + plugins/azure/openai/accountHasTags.spec.js | 2 + .../azure/openai/accountManagedIdentity.js | 4 + .../openai/accountManagedIdentity.spec.js | 2 + .../openai/accountPublicAccessDisabled.js | 2 + .../accountPublicAccessDisabled.spec.js | 4 + .../queueservice/queueServiceAllAccessAcl.js | 8 + .../queueServiceAllAccessAcl.spec.js | 14 +- .../storageAccountPublicNetworkAccess.js | 4 + .../tableservice/tableServiceAllAccessAcl.js | 8 + .../tableServiceAllAccessAcl.spec.js | 14 +- 171 files changed, 2167 insertions(+), 542 deletions(-) create mode 100644 collectors/aws/codeartifact/getRepositoryPermissionsPolicy.js create mode 100644 collectors/aws/codebuild/batchGetBuilds.js create mode 100644 collectors/aws/ec2/describeAddresses.js create mode 100644 collectors/aws/ssm/describeDocumentPermission.js create mode 100644 collectors/aws/storagegateway/describeNFSFileShares.js create mode 100644 collectors/aws/storagegateway/describeSMBFileShares.js create mode 100644 collectors/aws/storagegateway/listFileShares.js diff --git a/collectors/aws/accessanalyzer/listFindings.js b/collectors/aws/accessanalyzer/listFindings.js index 10c9cb933b..965bb7cb98 100644 --- a/collectors/aws/accessanalyzer/listFindings.js +++ b/collectors/aws/accessanalyzer/listFindings.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var accessanalyzer = new AWS.AccessAnalyzer(AWSConfig); async.eachLimit(collection.accessanalyzer.listAnalyzers[AWSConfig.region].data, 15, function(analyzer, cb) { collection.accessanalyzer.listFindings[AWSConfig.region][analyzer.arn] = {}; @@ -36,9 +36,9 @@ module.exports = function(AWSConfig, collection, retries, callback) { var localParams = JSON.parse(JSON.stringify(params || {})); if (nextToken) localParams['nextToken'] = nextToken; if (nextToken) { - helpers.makeCustomCollectorCall(accessanalyzer, 'listFindings', localParams, retries, null, null, null, paginateCb); + helpers.makeCustomCollectorCall(accessanalyzer, 'listFindings', localParams, retries, null, null, null, settings, scanAWSConfig, AWSConfig, paginateCb); } else { - helpers.makeCustomCollectorCall(accessanalyzer, 'listFindings', params, retries, null, null, null, paginateCb); + helpers.makeCustomCollectorCall(accessanalyzer, 'listFindings', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, paginateCb); } } diff --git a/collectors/aws/accessanalyzer/listFindingsV2.js b/collectors/aws/accessanalyzer/listFindingsV2.js index 3f9240b56e..aa409117a8 100644 --- a/collectors/aws/accessanalyzer/listFindingsV2.js +++ b/collectors/aws/accessanalyzer/listFindingsV2.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var accessanalyzer = new AWS.AccessAnalyzer(AWSConfig); async.eachLimit(collection.accessanalyzer.listAnalyzers[AWSConfig.region].data, 15, function(analyzer, cb) { collection.accessanalyzer.listFindingsV2[AWSConfig.region][analyzer.arn] = {}; @@ -36,9 +36,9 @@ module.exports = function(AWSConfig, collection, retries, callback) { var localParams = JSON.parse(JSON.stringify(params || {})); if (nextToken) localParams['nextToken'] = nextToken; if (nextToken) { - helpers.makeCustomCollectorCall(accessanalyzer, 'listFindingsV2', localParams, retries, null, null, null, paginateCb); + helpers.makeCustomCollectorCall(accessanalyzer, 'listFindingsV2', localParams, retries, null, null, null, settings, scanAWSConfig, AWSConfig, paginateCb); } else { - helpers.makeCustomCollectorCall(accessanalyzer, 'listFindingsV2', params, retries, null, null, null, paginateCb); + helpers.makeCustomCollectorCall(accessanalyzer, 'listFindingsV2', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, paginateCb); } } diff --git a/collectors/aws/apigateway/getClientCertificate.js b/collectors/aws/apigateway/getClientCertificate.js index 7c68bcfb22..c5065213de 100644 --- a/collectors/aws/apigateway/getClientCertificate.js +++ b/collectors/aws/apigateway/getClientCertificate.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var apigateway = new AWS.APIGateway(AWSConfig); async.eachLimit(collection.apigateway.getRestApis[AWSConfig.region].data, 5, function(api, cb){ @@ -21,7 +21,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { clientCertificateId: stage.clientCertificateId }; - helpers.makeCustomCollectorCall(apigateway, 'getClientCertificate', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(apigateway, 'getClientCertificate', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.apigateway.getClientCertificate[AWSConfig.region][stage.clientCertificateId].err = err; return pCb(); diff --git a/collectors/aws/apigateway/getIntegration.js b/collectors/aws/apigateway/getIntegration.js index 9a4ce5ca39..efe48f8c4a 100644 --- a/collectors/aws/apigateway/getIntegration.js +++ b/collectors/aws/apigateway/getIntegration.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var apigateway = new AWS.APIGateway(AWSConfig); async.eachLimit(collection.apigateway.getRestApis[AWSConfig.region].data, 5, function(api, cb){ @@ -29,7 +29,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { restApiId : api.id, }; - helpers.makeCustomCollectorCall(apigateway, 'getIntegration', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(apigateway, 'getIntegration', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.apigateway.getIntegration[AWSConfig.region][api.id][resource.id][methodKey].err = err; return mCb(); diff --git a/collectors/aws/appmesh/describeVirtualGateway.js b/collectors/aws/appmesh/describeVirtualGateway.js index e6a55fd82c..77c64c3b53 100644 --- a/collectors/aws/appmesh/describeVirtualGateway.js +++ b/collectors/aws/appmesh/describeVirtualGateway.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var appmesh = new AWS.AppMesh(AWSConfig); if (!collection.appmesh || @@ -24,7 +24,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { async.eachLimit(collection.appmesh.listVirtualGateways[AWSConfig.region][mesh.meshName].data.virtualGateways, 3, function(gateway, pCb){ collection.appmesh.describeVirtualGateway[AWSConfig.region][gateway.virtualGatewayName] = {}; - helpers.makeCustomCollectorCall(appmesh, 'describeVirtualGateway', {virtualGatewayName: gateway.virtualGatewayName,meshName: mesh.meshName}, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(appmesh, 'describeVirtualGateway', {virtualGatewayName: gateway.virtualGatewayName,meshName: mesh.meshName}, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.appmesh.describeVirtualGateway[AWSConfig.region][gateway.virtualGatewayName].err = err; } diff --git a/collectors/aws/autoscaling/describeLaunchConfigurations.js b/collectors/aws/autoscaling/describeLaunchConfigurations.js index eb47515c0b..3beaab906c 100644 --- a/collectors/aws/autoscaling/describeLaunchConfigurations.js +++ b/collectors/aws/autoscaling/describeLaunchConfigurations.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var autoscaling = new AWS.AutoScaling(AWSConfig); async.eachLimit(collection.autoscaling.describeAutoScalingGroups[AWSConfig.region].data, 15, function(asg, cb){ @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'LaunchConfigurationNames': [asg.LaunchConfigurationName] }; - helpers.makeCustomCollectorCall(autoscaling, 'describeLaunchConfigurations', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(autoscaling, 'describeLaunchConfigurations', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.autoscaling.describeLaunchConfigurations[AWSConfig.region][asg.AutoScalingGroupARN].err = err; } diff --git a/collectors/aws/autoscaling/describeNotificationConfigurations.js b/collectors/aws/autoscaling/describeNotificationConfigurations.js index 34e4adcb6d..534b4ad6cc 100644 --- a/collectors/aws/autoscaling/describeNotificationConfigurations.js +++ b/collectors/aws/autoscaling/describeNotificationConfigurations.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var autoscaling = new AWS.AutoScaling(AWSConfig); async.eachLimit(collection.autoscaling.describeAutoScalingGroups[AWSConfig.region].data, 15, function(asg, cb){ @@ -10,7 +10,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'AutoScalingGroupNames':[asg.AutoScalingGroupName] }; - helpers.makeCustomCollectorCall(autoscaling, 'describeNotificationConfigurations', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(autoscaling, 'describeNotificationConfigurations', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { collection.autoscaling.describeNotificationConfigurations[AWSConfig.region][asg.AutoScalingGroupARN] = {}; if (err || !data) { collection.autoscaling.describeNotificationConfigurations[AWSConfig.region][asg.AutoScalingGroupARN].err = err; diff --git a/collectors/aws/cloudfront/getDistribution.js b/collectors/aws/cloudfront/getDistribution.js index f0f979c067..4ab1a2e921 100644 --- a/collectors/aws/cloudfront/getDistribution.js +++ b/collectors/aws/cloudfront/getDistribution.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var cloudfront = new AWS.CloudFront(AWSConfig); async.eachLimit(collection.cloudfront.listDistributions[AWSConfig.region].data, 15, function(distribution, cb){ @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'Id':distribution.Id }; - helpers.makeCustomCollectorCall(cloudfront, 'getDistribution', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(cloudfront, 'getDistribution', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.cloudfront.getDistribution[AWSConfig.region][distribution.Id].err = err; } diff --git a/collectors/aws/cloudtrail/listTags.js b/collectors/aws/cloudtrail/listTags.js index dc3c2cbc9e..2fdcf9239f 100644 --- a/collectors/aws/cloudtrail/listTags.js +++ b/collectors/aws/cloudtrail/listTags.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var cloudtrail = new AWS.CloudTrail(AWSConfig); async.eachLimit(collection.cloudtrail.describeTrails[AWSConfig.region].data, 15, function(trail, cb) { @@ -10,7 +10,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { ResourceIdList: [trail.TrailARN] }; - helpers.makeCustomCollectorCall(cloudtrail, 'listTags', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(cloudtrail, 'listTags', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { collection.cloudtrail.listTags[AWSConfig.region][trail.TrailARN] = {}; if (err || !data) { collection.cloudtrail.listTags[AWSConfig.region][trail.TrailARN].err = err; diff --git a/collectors/aws/cloudwatch/getEc2MetricStatistics.js b/collectors/aws/cloudwatch/getEc2MetricStatistics.js index 3742ea8762..1c896491e8 100644 --- a/collectors/aws/cloudwatch/getEc2MetricStatistics.js +++ b/collectors/aws/cloudwatch/getEc2MetricStatistics.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require('../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var cloudwatch = new AWS.CloudWatch(AWSConfig); async.eachLimit(collection.ec2.describeInstances[AWSConfig.region].data, 10, function(reservation, cb) { @@ -26,7 +26,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { ] }; - helpers.makeCustomCollectorCall(cloudwatch, 'getMetricStatistics', params,retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(cloudwatch, 'getMetricStatistics', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) collection.cloudwatch.getEc2MetricStatistics[AWSConfig.region][instance.InstanceId].err = err; if (data) collection.cloudwatch.getEc2MetricStatistics[AWSConfig.region][instance.InstanceId].data = data; }); diff --git a/collectors/aws/cloudwatch/getEcMetricStatistics.js b/collectors/aws/cloudwatch/getEcMetricStatistics.js index 5ecb621e26..2bfb12bdd7 100644 --- a/collectors/aws/cloudwatch/getEcMetricStatistics.js +++ b/collectors/aws/cloudwatch/getEcMetricStatistics.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var cloudwatch = new AWS.CloudWatch(AWSConfig); async.eachLimit(collection.elasticache.describeCacheClusters[AWSConfig.region].data, 10, function(cluster, cb){ @@ -25,7 +25,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { ] }; - helpers.makeCustomCollectorCall(cloudwatch, 'getMetricStatistics', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(cloudwatch, 'getMetricStatistics', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.cloudwatch.getEcMetricStatistics[AWSConfig.region][cluster.CacheClusterId].err = err; } diff --git a/collectors/aws/cloudwatch/getEsMetricStatistics.js b/collectors/aws/cloudwatch/getEsMetricStatistics.js index 559a3ee40a..08609c6ef7 100644 --- a/collectors/aws/cloudwatch/getEsMetricStatistics.js +++ b/collectors/aws/cloudwatch/getEsMetricStatistics.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var cloudwatch = new AWS.CloudWatch(AWSConfig); async.eachLimit(collection.opensearch.listDomainNames[AWSConfig.region].data, 10, function(domain, cb){ @@ -25,7 +25,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { ] }; - helpers.makeCustomCollectorCall(cloudwatch, 'getMetricStatistics', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(cloudwatch, 'getMetricStatistics', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.cloudwatch.getEsMetricStatistics[AWSConfig.region][domain.DomainName].err = err; } diff --git a/collectors/aws/cloudwatch/getRdsMetricStatistics.js b/collectors/aws/cloudwatch/getRdsMetricStatistics.js index afc81333a7..d724604061 100644 --- a/collectors/aws/cloudwatch/getRdsMetricStatistics.js +++ b/collectors/aws/cloudwatch/getRdsMetricStatistics.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var cloudwatch = new AWS.CloudWatch(AWSConfig); async.eachLimit(collection.rds.describeDBInstances[AWSConfig.region].data, 10, function(instance, cb){ @@ -25,7 +25,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { ] }; - helpers.makeCustomCollectorCall(cloudwatch, 'getMetricStatistics', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(cloudwatch, 'getMetricStatistics', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.cloudwatch.getRdsMetricStatistics[AWSConfig.region][instance.DBInstanceIdentifier].err = err; } diff --git a/collectors/aws/cloudwatch/getRdsReadIOPSMetricStatistics.js b/collectors/aws/cloudwatch/getRdsReadIOPSMetricStatistics.js index a080770755..82ec555d51 100644 --- a/collectors/aws/cloudwatch/getRdsReadIOPSMetricStatistics.js +++ b/collectors/aws/cloudwatch/getRdsReadIOPSMetricStatistics.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var cloudwatch = new AWS.CloudWatch(AWSConfig); async.eachLimit(collection.rds.describeDBInstances[AWSConfig.region].data, 10, function(instance, cb){ @@ -25,7 +25,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { ] }; - helpers.makeCustomCollectorCall(cloudwatch, 'getMetricStatistics', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(cloudwatch, 'getMetricStatistics', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.cloudwatch.getRdsReadIOPSMetricStatistics[AWSConfig.region][instance.DBInstanceIdentifier].err = err; } diff --git a/collectors/aws/cloudwatch/getRdsWriteIOPSMetricStatistics.js b/collectors/aws/cloudwatch/getRdsWriteIOPSMetricStatistics.js index 5f68bfecd0..4c5233acb8 100644 --- a/collectors/aws/cloudwatch/getRdsWriteIOPSMetricStatistics.js +++ b/collectors/aws/cloudwatch/getRdsWriteIOPSMetricStatistics.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var cloudwatch = new AWS.CloudWatch(AWSConfig); async.eachLimit(collection.rds.describeDBInstances[AWSConfig.region].data, 10, function(instance, cb){ @@ -25,7 +25,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { ] }; - helpers.makeCustomCollectorCall(cloudwatch, 'getMetricStatistics', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(cloudwatch, 'getMetricStatistics', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.cloudwatch.getRdsWriteIOPSMetricStatistics[AWSConfig.region][instance.DBInstanceIdentifier].err = err; } diff --git a/collectors/aws/cloudwatch/getredshiftMetricStatistics.js b/collectors/aws/cloudwatch/getredshiftMetricStatistics.js index 979f8543e6..6ae848cada 100644 --- a/collectors/aws/cloudwatch/getredshiftMetricStatistics.js +++ b/collectors/aws/cloudwatch/getredshiftMetricStatistics.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var cloudwatch = new AWS.CloudWatch(AWSConfig); async.eachLimit(collection.redshift.describeClusters[AWSConfig.region].data, 10, function(cluster, cb){ @@ -25,7 +25,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { ] }; - helpers.makeCustomCollectorCall(cloudwatch, 'getMetricStatistics', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(cloudwatch, 'getMetricStatistics', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.cloudwatch.getredshiftMetricStatistics[AWSConfig.region][cluster.ClusterIdentifier].err = err; } diff --git a/collectors/aws/codeartifact/getRepositoryPermissionsPolicy.js b/collectors/aws/codeartifact/getRepositoryPermissionsPolicy.js new file mode 100644 index 0000000000..ac49046f4d --- /dev/null +++ b/collectors/aws/codeartifact/getRepositoryPermissionsPolicy.js @@ -0,0 +1,28 @@ +var AWS = require('aws-sdk'); +var async = require('async'); +var helpers = require(__dirname + '/../../../helpers/aws'); + +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + var codeartifact = new AWS.CodeArtifact(AWSConfig); + + // Needs both domain and repository, so the generic single-key postcall path cannot be used + async.eachLimit(collection.codeartifact.listRepositories[AWSConfig.region].data, 10, function(repository, cb){ + collection.codeartifact.getRepositoryPermissionsPolicy[AWSConfig.region][repository.arn] = {}; + + var params = { + domain: repository.domainName, + repository: repository.name + }; + if (repository.domainOwner) params.domainOwner = repository.domainOwner; + + helpers.makeCustomCollectorCall(codeartifact, 'getRepositoryPermissionsPolicy', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { + if (err) { + collection.codeartifact.getRepositoryPermissionsPolicy[AWSConfig.region][repository.arn].err = err; + } + if (data) collection.codeartifact.getRepositoryPermissionsPolicy[AWSConfig.region][repository.arn].data = data; + cb(); + }); + }, function(){ + callback(); + }); +}; diff --git a/collectors/aws/codebuild/batchGetBuilds.js b/collectors/aws/codebuild/batchGetBuilds.js new file mode 100644 index 0000000000..22fc7093f5 --- /dev/null +++ b/collectors/aws/codebuild/batchGetBuilds.js @@ -0,0 +1,37 @@ +var AWS = require('aws-sdk'); +var async = require('async'); +var helpers = require(__dirname + '/../../../helpers/aws'); + +// batchGetBuilds accepts at most 100 build ids per request +var MAX_IDS_PER_CALL = 100; + +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + var codebuild = new AWS.CodeBuild(AWSConfig); + + // listBuilds returns bare id strings, so chunk them rather than calling per build + var ids = collection.codebuild.listBuilds[AWSConfig.region].data; + var chunks = []; + for (var i = 0; i < ids.length; i += MAX_IDS_PER_CALL) { + chunks.push(ids.slice(i, i + MAX_IDS_PER_CALL)); + } + + collection.codebuild.batchGetBuilds[AWSConfig.region].data = []; + + async.eachLimit(chunks, 5, function(chunk, cb){ + var params = { + ids: chunk + }; + + helpers.makeCustomCollectorCall(codebuild, 'batchGetBuilds', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { + if (err) { + collection.codebuild.batchGetBuilds[AWSConfig.region].err = err; + } else if (data && data.builds && data.builds.length) { + collection.codebuild.batchGetBuilds[AWSConfig.region].data = + collection.codebuild.batchGetBuilds[AWSConfig.region].data.concat(data.builds); + } + cb(); + }); + }, function(){ + callback(); + }); +}; diff --git a/collectors/aws/codebuild/batchGetProjects.js b/collectors/aws/codebuild/batchGetProjects.js index e176ce5d76..b8d865c9ef 100644 --- a/collectors/aws/codebuild/batchGetProjects.js +++ b/collectors/aws/codebuild/batchGetProjects.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var codebuild = new AWS.CodeBuild(AWSConfig); async.eachLimit(collection.codebuild.listProjects[AWSConfig.region].data, 15, function(project, cb){ @@ -12,7 +12,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { names: [project], }; - helpers.makeCustomCollectorCall(codebuild, 'batchGetProjects', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(codebuild, 'batchGetProjects', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.codebuild.batchGetProjects[AWSConfig.region][project].err = err; } diff --git a/collectors/aws/collector.js b/collectors/aws/collector.js index 6f7fa7b99a..b6663bc136 100644 --- a/collectors/aws/collector.js +++ b/collectors/aws/collector.js @@ -126,7 +126,7 @@ var collect = function(AWSConfig, settings, callback) { LocalAWSConfig.region = region; if (callObj.override) { - collectors[serviceLower][callKey](LocalAWSConfig, collection, retries, function() { + collectors[serviceLower][callKey](LocalAWSConfig, collection, retries, settings, AWSConfig, function() { if (callObj.rateLimit) { setTimeout(function() { regionCb(); @@ -191,7 +191,14 @@ var collect = function(AWSConfig, settings, callback) { } }, function(cb) { executor[callKey](localParams, function(err, data) { - return cb(err, data); + helpers.refreshCredentialsIfTokenExpired(err, settings, AWSConfig, LocalAWSConfig, function(refreshErr, newCreds) { + if (!newCreds) { + if (refreshErr) console.log('[WARN] Token refresh failed'); + return cb(err, data); + } + var newExecutor = debugMode ? (AWSXRay.captureAWSClient(new AWS[serviceName](LocalAWSConfig))) : new AWS[serviceName](LocalAWSConfig); + newExecutor[callKey](localParams, cb); + }); }); }, function(err, data){ executorCb(err, data); @@ -215,7 +222,14 @@ var collect = function(AWSConfig, settings, callback) { } }, function(cb) { executor[callKey](function(err, data) { - return cb(err, data); + helpers.refreshCredentialsIfTokenExpired(err, settings, AWSConfig, LocalAWSConfig, function(refreshErr, newCreds) { + if (!newCreds) { + if (refreshErr) console.log('[WARN] Token refresh failed'); + return cb(err, data); + } + var newExecutor = debugMode ? (AWSXRay.captureAWSClient(new AWS[serviceName](LocalAWSConfig))) : new AWS[serviceName](LocalAWSConfig); + newExecutor[callKey](cb); + }); }); }, function(err, data){ executorCb(err, data); @@ -294,7 +308,7 @@ var collect = function(AWSConfig, settings, callback) { if (callObj.signatureVersion) LocalAWSConfig.signatureVersion = callObj.signatureVersion; if (callObj.override) { - collectors[serviceLower][callKey](LocalAWSConfig, collection, retries, function() { + collectors[serviceLower][callKey](LocalAWSConfig, collection, retries, settings, AWSConfig, function() { if (callObj.rateLimit) { setTimeout(function() { @@ -336,16 +350,32 @@ var collect = function(AWSConfig, settings, callback) { } }, function(cb) { executor[callKey](filter, function(err, data) { - if (helpers.collectRateError(err, rateError)) { - return cb(err); - } else if (err) { - collection[serviceLower][callKey][LocalAWSConfig.region][dep[callObj.filterValue]].err = err; - helpers.logError(serviceLower, callKey, region, err, errors, apiCallErrors, apiCallTypeErrors, totalApiCallErrors, errorSummary, errorTypeSummary, debugMode); - return cb(); - } else { - collection[serviceLower][callKey][LocalAWSConfig.region][dep[callObj.filterValue]].data = data; - return cb(); - } + helpers.refreshCredentialsIfTokenExpired(err, settings, AWSConfig, LocalAWSConfig, function(refreshErr, newCreds) { + // No new creds = either not token-expired, or refresh failed: handle original err/data (rate error, store err, or store data) + if (!newCreds) { + if (refreshErr) console.log('[WARN] Token refresh failed'); + if (helpers.collectRateError(err, rateError)) return cb(err); + if (err) { + collection[serviceLower][callKey][LocalAWSConfig.region][dep[callObj.filterValue]].err = err; + helpers.logError(serviceLower, callKey, region, err, errors, apiCallErrors, apiCallTypeErrors, totalApiCallErrors, errorSummary, errorTypeSummary, debugMode); + return cb(); + } + collection[serviceLower][callKey][LocalAWSConfig.region][dep[callObj.filterValue]].data = data; + return cb(); + } + + var newExecutor = debugMode ? (AWSXRay.captureAWSClient(new AWS[serviceName](LocalAWSConfig))) : new AWS[serviceName](LocalAWSConfig); + newExecutor[callKey](filter, function(retryErr, retryData) { + if (helpers.collectRateError(retryErr, rateError)) return cb(retryErr); + if (retryErr) { + collection[serviceLower][callKey][LocalAWSConfig.region][dep[callObj.filterValue]].err = retryErr; + helpers.logError(serviceLower, callKey, region, retryErr, errors, apiCallErrors, apiCallTypeErrors, totalApiCallErrors, errorSummary, errorTypeSummary, debugMode); + return cb(); + } + collection[serviceLower][callKey][LocalAWSConfig.region][dep[callObj.filterValue]].data = retryData; + return cb(); + }); + }); }); }, function(){ diff --git a/collectors/aws/collector_multipart.js b/collectors/aws/collector_multipart.js index e9960d4aee..4cf57026fa 100644 --- a/collectors/aws/collector_multipart.js +++ b/collectors/aws/collector_multipart.js @@ -155,7 +155,7 @@ var collect = function(AWSConfig, settings, callback) { LocalAWSConfig.region = region; if (callObj.override) { - collectors[serviceLower][callKey](LocalAWSConfig, collection, retries, function() { + collectors[serviceLower][callKey](LocalAWSConfig, collection, retries, settings, AWSConfig, function() { if (callObj.rateLimit) { setTimeout(function() { regionCb(); @@ -334,7 +334,7 @@ var collect = function(AWSConfig, settings, callback) { if (callObj.signatureVersion) LocalAWSConfig.signatureVersion = callObj.signatureVersion; if (callObj.override) { - collectors[serviceLower][callKey](LocalAWSConfig, collection, retries, function() { + collectors[serviceLower][callKey](LocalAWSConfig, collection, retries, settings, AWSConfig, function() { if (callObj.rateLimit) { setTimeout(function() { diff --git a/collectors/aws/connect/instanceAttachmentStorageConfigs.js b/collectors/aws/connect/instanceAttachmentStorageConfigs.js index 3d147ab582..1e8c9915a8 100644 --- a/collectors/aws/connect/instanceAttachmentStorageConfigs.js +++ b/collectors/aws/connect/instanceAttachmentStorageConfigs.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var connect = new AWS.Connect(AWSConfig); async.eachLimit(collection.connect.listInstances[AWSConfig.region].data, 15, function(instance, cb){ @@ -12,7 +12,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'ResourceType': 'ATTACHMENTS' }; - helpers.makeCustomCollectorCall(connect, 'listInstanceStorageConfigs', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(connect, 'listInstanceStorageConfigs', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.connect.instanceAttachmentStorageConfigs[AWSConfig.region][instance.Id].err = err; } diff --git a/collectors/aws/connect/listInstanceCallRecordingStorageConfigs.js b/collectors/aws/connect/listInstanceCallRecordingStorageConfigs.js index 11bd731010..4a3d112581 100644 --- a/collectors/aws/connect/listInstanceCallRecordingStorageConfigs.js +++ b/collectors/aws/connect/listInstanceCallRecordingStorageConfigs.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var connect = new AWS.Connect(AWSConfig); async.eachLimit(collection.connect.listInstances[AWSConfig.region].data, 15, function(instance, cb){ @@ -12,7 +12,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'ResourceType': 'CALL_RECORDINGS' }; - helpers.makeCustomCollectorCall(connect, 'listInstanceStorageConfigs', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(connect, 'listInstanceStorageConfigs', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.connect.listInstanceCallRecordingStorageConfigs[AWSConfig.region][instance.Id].err = err; } diff --git a/collectors/aws/connect/listInstanceChatTranscriptStorageConfigs.js b/collectors/aws/connect/listInstanceChatTranscriptStorageConfigs.js index b65aafe668..3d8cfef146 100644 --- a/collectors/aws/connect/listInstanceChatTranscriptStorageConfigs.js +++ b/collectors/aws/connect/listInstanceChatTranscriptStorageConfigs.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var connect = new AWS.Connect(AWSConfig); async.eachLimit(collection.connect.listInstances[AWSConfig.region].data, 15, function(instance, cb){ @@ -12,7 +12,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'ResourceType': 'CHAT_TRANSCRIPTS' }; - helpers.makeCustomCollectorCall(connect, 'listInstanceStorageConfigs', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(connect, 'listInstanceStorageConfigs', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.connect.listInstanceChatTranscriptStorageConfigs[AWSConfig.region][instance.Id].err = err; } diff --git a/collectors/aws/connect/listInstanceExportedReportStorageConfigs.js b/collectors/aws/connect/listInstanceExportedReportStorageConfigs.js index 851b7ddf9a..170b301d2d 100644 --- a/collectors/aws/connect/listInstanceExportedReportStorageConfigs.js +++ b/collectors/aws/connect/listInstanceExportedReportStorageConfigs.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var connect = new AWS.Connect(AWSConfig); async.eachLimit(collection.connect.listInstances[AWSConfig.region].data, 15, function(instance, cb){ @@ -12,7 +12,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'ResourceType': 'SCHEDULED_REPORTS' }; - helpers.makeCustomCollectorCall(connect, 'listInstanceStorageConfigs', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(connect, 'listInstanceStorageConfigs', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.connect.listInstanceExportedReportStorageConfigs[AWSConfig.region][instance.Id].err = err; } diff --git a/collectors/aws/connect/listInstanceMediaStreamStorageConfigs.js b/collectors/aws/connect/listInstanceMediaStreamStorageConfigs.js index 4873a4ebe2..210b749924 100644 --- a/collectors/aws/connect/listInstanceMediaStreamStorageConfigs.js +++ b/collectors/aws/connect/listInstanceMediaStreamStorageConfigs.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var connect = new AWS.Connect(AWSConfig); async.eachLimit(collection.connect.listInstances[AWSConfig.region].data, 15, function(instance, cb){ @@ -12,7 +12,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'ResourceType': 'MEDIA_STREAMS' }; - helpers.makeCustomCollectorCall(connect, 'listInstanceStorageConfigs', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(connect, 'listInstanceStorageConfigs', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.connect.listInstanceMediaStreamStorageConfigs[AWSConfig.region][instance.Id].err = err; } diff --git a/collectors/aws/dynamodb/describeContinuousBackups.js b/collectors/aws/dynamodb/describeContinuousBackups.js index d7884b6b22..0482a76fda 100644 --- a/collectors/aws/dynamodb/describeContinuousBackups.js +++ b/collectors/aws/dynamodb/describeContinuousBackups.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var dynamodb = new AWS.DynamoDB(AWSConfig); async.eachLimit(collection.dynamodb.listTables[AWSConfig.region].data, 15, function(table, cb){ @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'TableName': table }; - helpers.makeCustomCollectorCall(dynamodb, 'describeContinuousBackups', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(dynamodb, 'describeContinuousBackups', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.dynamodb.describeContinuousBackups[AWSConfig.region][table].err = err; } diff --git a/collectors/aws/dynamodb/describeTable.js b/collectors/aws/dynamodb/describeTable.js index c6ab50676c..d44430017e 100644 --- a/collectors/aws/dynamodb/describeTable.js +++ b/collectors/aws/dynamodb/describeTable.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var dynamodb = new AWS.DynamoDB(AWSConfig); async.eachLimit(collection.dynamodb.listTables[AWSConfig.region].data, 15, function(table, cb){ @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'TableName': table }; - helpers.makeCustomCollectorCall(dynamodb, 'describeTable', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(dynamodb, 'describeTable', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.dynamodb.describeTable[AWSConfig.region][table].err = err; } diff --git a/collectors/aws/dynamodb/listBackups.js b/collectors/aws/dynamodb/listBackups.js index dd4138ed69..09e8762e0a 100644 --- a/collectors/aws/dynamodb/listBackups.js +++ b/collectors/aws/dynamodb/listBackups.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var dynamodb = new AWS.DynamoDB(AWSConfig); async.eachLimit(collection.dynamodb.listTables[AWSConfig.region].data, 15, function(table, cb){ @@ -14,7 +14,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { }; - helpers.makeCustomCollectorCall(dynamodb, 'listBackups', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(dynamodb, 'listBackups', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.dynamodb.listBackups[AWSConfig.region][table].err = err; } diff --git a/collectors/aws/ec2/describeAddresses.js b/collectors/aws/ec2/describeAddresses.js new file mode 100644 index 0000000000..5e98037b71 --- /dev/null +++ b/collectors/aws/ec2/describeAddresses.js @@ -0,0 +1,69 @@ +var async = require('async'); +var { EC2Client, DescribeAddressesCommand } = require('@aws-sdk/client-ec2'); +var helpers = require(__dirname + '/../../../helpers/aws'); + +var rateError = { message: 'rate', statusCode: 429 }; +var apiRetryAttempts = 2; +var apiRetryCap = 1000; +var apiRetryBackoff = 500; + +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + + var ec2Client = new EC2Client(helpers.buildV3ClientConfig(AWSConfig)); + var params = {}; + + function runOnce(cb) { + var command = new DescribeAddressesCommand(params); + ec2Client.send(command).then(function(data) { + return cb(null, data); + }).catch(function(err) { + helpers.refreshCredentialsIfTokenExpired(err, settings, scanAWSConfig, AWSConfig, function(refreshErr, newCreds) { + if (!newCreds) { + if (refreshErr) console.log('[WARN] Token refresh failed'); + return cb(err, null); + } + try { + ec2Client = new EC2Client(helpers.buildV3ClientConfig(AWSConfig)); + } catch (e) { + return cb(err, null); + } + var retryCommand = new DescribeAddressesCommand(params); + ec2Client.send(retryCommand).then(function(data) { + return cb(null, data); + }).catch(function(retryErr) { + return cb(retryErr, null); + }); + }); + }); + } + + async.retry({ + times: apiRetryAttempts, + interval: function(retryCount) { + let retryExponential = 3; + let retryLeveler = 3; + let timestamp = parseInt(((new Date()).getTime()).toString().slice(-1)); + let retry_temp = Math.min(apiRetryCap, (apiRetryBackoff * (retryExponential + timestamp) ** retryCount)); + let retry_seconds = Math.round(retry_temp / retryLeveler + Math.random(0, retry_temp) * 5000); + + console.log(`Trying DescribeAddressesCommand again in: ${retry_seconds / 1000} seconds`); + retries.push({ seconds: Math.round(retry_seconds / 1000) }); + return retry_seconds; + }, + errorFilter: function(err) { + return helpers.collectRateError(err, rateError); + } + }, function(cb) { + runOnce(cb); + }, function(err, data) { + if (err) { + collection.ec2.describeAddresses[AWSConfig.region].err = err; + } else if (data) { + collection.ec2.describeAddresses[AWSConfig.region].data = data.Addresses || []; + } else if (!collection.ec2.describeAddresses[AWSConfig.region].data) { + collection.ec2.describeAddresses[AWSConfig.region].data = []; + } + + callback(); + }); +}; diff --git a/collectors/aws/ec2/describeSnapshotAttribute.js b/collectors/aws/ec2/describeSnapshotAttribute.js index 8439c61db1..a2fae7f641 100644 --- a/collectors/aws/ec2/describeSnapshotAttribute.js +++ b/collectors/aws/ec2/describeSnapshotAttribute.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var ec2 = new AWS.EC2(AWSConfig); async.eachLimit(collection.ec2.describeSnapshots[AWSConfig.region].data, 20, function(snapshot, cb){ @@ -12,7 +12,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { SnapshotId: snapshot.SnapshotId }; - helpers.makeCustomCollectorCall(ec2, 'describeSnapshotAttribute', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(ec2, 'describeSnapshotAttribute', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.ec2.describeSnapshotAttribute[AWSConfig.region][snapshot.SnapshotId].err = err; } diff --git a/collectors/aws/ec2/describeSnapshots.js b/collectors/aws/ec2/describeSnapshots.js index 11a65e4862..47b7ecae79 100644 --- a/collectors/aws/ec2/describeSnapshots.js +++ b/collectors/aws/ec2/describeSnapshots.js @@ -5,7 +5,7 @@ var helpers = require(__dirname + '/../../../helpers/aws'); // default call retrieves every snapshot // available, including public ones -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var ec2 = new AWS.EC2(AWSConfig); var sts = new AWS.STS(AWSConfig); var paginating = false; @@ -13,7 +13,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { var createdTime = new Date(); createdTime.setDate(createdTime.getDate() - 30); - helpers.makeCustomCollectorCall(sts, 'getCallerIdentity', {}, retries, null, null, null, function(stsErr, stsData) { + helpers.makeCustomCollectorCall(sts, 'getCallerIdentity', {}, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(stsErr, stsData) { if (stsErr || !stsData.Account) { collection.ec2.describeSnapshots[AWSConfig.region].err = 'Unable to filter by owner ID'; return callback(); @@ -68,9 +68,9 @@ module.exports = function(AWSConfig, collection, retries, callback) { var localParams = JSON.parse(JSON.stringify(params || {})); if (nextToken) localParams['NextToken'] = nextToken; if (nextToken) { - helpers.makeCustomCollectorCall(ec2, 'describeSnapshots', localParams, retries, null, null, null, paginateCb); + helpers.makeCustomCollectorCall(ec2, 'describeSnapshots', localParams, retries, null, null, null, settings, scanAWSConfig, AWSConfig, paginateCb); } else { - helpers.makeCustomCollectorCall(ec2, 'describeSnapshots', params, retries, null, null, null, paginateCb); + helpers.makeCustomCollectorCall(ec2, 'describeSnapshots', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, paginateCb); } } execute(); diff --git a/collectors/aws/ec2/describeSubnets.js b/collectors/aws/ec2/describeSubnets.js index 0ecc6857c3..b28f897003 100644 --- a/collectors/aws/ec2/describeSubnets.js +++ b/collectors/aws/ec2/describeSubnets.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var ec2 = new AWS.EC2(AWSConfig); async.eachLimit(collection.ec2.describeVpcs[AWSConfig.region].data, 15, function(vpc, cb){ @@ -20,7 +20,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { ] }; - helpers.makeCustomCollectorCall(ec2, 'describeSubnets', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(ec2, 'describeSubnets', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.ec2.describeSubnets[AWSConfig.region][vpc.VpcId].err = err; } diff --git a/collectors/aws/ecs/describeCluster.js b/collectors/aws/ecs/describeCluster.js index a539683097..8010250c0f 100644 --- a/collectors/aws/ecs/describeCluster.js +++ b/collectors/aws/ecs/describeCluster.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var ecs = new AWS.ECS(AWSConfig); async.eachLimit(collection.ecs.listClusters[AWSConfig.region].data, 10, function(cluster, cb){ @@ -14,7 +14,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'include': ['SETTINGS'] }; - helpers.makeCustomCollectorCall(ecs, 'describeClusters', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(ecs, 'describeClusters', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.ecs.describeCluster[AWSConfig.region][cluster].err = err; } diff --git a/collectors/aws/ecs/describeContainerInstances.js b/collectors/aws/ecs/describeContainerInstances.js index a03285a20a..54549ff8a2 100644 --- a/collectors/aws/ecs/describeContainerInstances.js +++ b/collectors/aws/ecs/describeContainerInstances.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var ecs = new AWS.ECS(AWSConfig); async.eachOfLimit(collection.ecs.listContainerInstances[AWSConfig.region], 10, function(containerInstanceData,instance, cb){ @@ -17,7 +17,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { cluster : clusterName, };collection.ecs.describeContainerInstances[AWSConfig.region][containerInstance] = {}; - helpers.makeCustomCollectorCall(ecs, 'describeContainerInstances', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(ecs, 'describeContainerInstances', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.ecs.describeContainerInstances[AWSConfig.region][containerInstance].err = err; } diff --git a/collectors/aws/ecs/describeServices.js b/collectors/aws/ecs/describeServices.js index 87fa1d7034..57998d393a 100644 --- a/collectors/aws/ecs/describeServices.js +++ b/collectors/aws/ecs/describeServices.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var ecs = new AWS.ECS(AWSConfig); async.eachOfLimit(collection.ecs.listServices[AWSConfig.region], 10, function(servicesData,instance, cb){ @@ -17,7 +17,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { cluster : clusterName, }; - helpers.makeCustomCollectorCall(ecs, 'describeServices', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(ecs, 'describeServices', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.ecs.describeServices[AWSConfig.region][service].err = err; } diff --git a/collectors/aws/ecs/describeTasks.js b/collectors/aws/ecs/describeTasks.js index fad0738b3a..c372340753 100644 --- a/collectors/aws/ecs/describeTasks.js +++ b/collectors/aws/ecs/describeTasks.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var ecs = new AWS.ECS(AWSConfig); async.eachOfLimit(collection.ecs.listTasks[AWSConfig.region], 10, function(tasksData,instance, cb){ @@ -17,7 +17,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { cluster : clusterName, }; - helpers.makeCustomCollectorCall(ecs, 'describeTasks', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(ecs, 'describeTasks', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.ecs.describeTasks[AWSConfig.region][task].err = err; } diff --git a/collectors/aws/ecs/listContainerInstances.js b/collectors/aws/ecs/listContainerInstances.js index c7b9eb175e..5316d95aa7 100644 --- a/collectors/aws/ecs/listContainerInstances.js +++ b/collectors/aws/ecs/listContainerInstances.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var ecs = new AWS.ECS(AWSConfig); async.eachLimit(collection.ecs.listClusters[AWSConfig.region].data, 10, function(cluster, cb){ @@ -13,7 +13,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { cluster: cluster }; - helpers.makeCustomCollectorCall(ecs, 'listContainerInstances', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(ecs, 'listContainerInstances', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.ecs.listContainerInstances[AWSConfig.region][cluster].err = err; } else if (data && data.containerInstanceArns) { diff --git a/collectors/aws/ecs/listServices.js b/collectors/aws/ecs/listServices.js index 4898290ad1..74be653672 100644 --- a/collectors/aws/ecs/listServices.js +++ b/collectors/aws/ecs/listServices.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var ecs = new AWS.ECS(AWSConfig); async.eachLimit(collection.ecs.listClusters[AWSConfig.region].data, 10, function(cluster, cb){ @@ -15,7 +15,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { cluster: clusterName }; - helpers.makeCustomCollectorCall(ecs, 'listServices', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(ecs, 'listServices', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.ecs.listServices[AWSConfig.region][cluster].err = err; } diff --git a/collectors/aws/ecs/listTasks.js b/collectors/aws/ecs/listTasks.js index 082cad3ec9..4623902dc1 100644 --- a/collectors/aws/ecs/listTasks.js +++ b/collectors/aws/ecs/listTasks.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var ecs = new AWS.ECS(AWSConfig); async.eachLimit(collection.ecs.listClusters[AWSConfig.region].data, 10, function(cluster, cb){ @@ -15,7 +15,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { cluster: clusterName }; - helpers.makeCustomCollectorCall(ecs, 'listTasks', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(ecs, 'listTasks', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.ecs.listTasks[AWSConfig.region][cluster].err = err; } else if (data && data.taskArns) { diff --git a/collectors/aws/eks/describeCluster.js b/collectors/aws/eks/describeCluster.js index e5e485badc..6441747c73 100644 --- a/collectors/aws/eks/describeCluster.js +++ b/collectors/aws/eks/describeCluster.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var eks = new AWS.EKS(AWSConfig); async.eachLimit(collection.eks.listClusters[AWSConfig.region].data, 10, function(cluster, cb){ @@ -13,7 +13,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { name: cluster }; - helpers.makeCustomCollectorCall(eks, 'describeCluster', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(eks, 'describeCluster', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) collection.eks.describeCluster[AWSConfig.region][cluster].err = err; if (data) collection.eks.describeCluster[AWSConfig.region][cluster].data = data; diff --git a/collectors/aws/eks/describeNodegroups.js b/collectors/aws/eks/describeNodegroups.js index bba92226ef..8267a29bf7 100644 --- a/collectors/aws/eks/describeNodegroups.js +++ b/collectors/aws/eks/describeNodegroups.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var eks = new AWS.EKS(AWSConfig); //var autoscaling = new AWS.AutoScaling(AWSConfig); @@ -16,7 +16,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { nodegroupName: nodeGroup }; - helpers.makeCustomCollectorCall(eks, 'describeNodegroup', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(eks, 'describeNodegroup', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) collection.eks.describeNodegroups[AWSConfig.region][cluster][nodeGroup].err = err; //var autoScalingGroupNames = []; if (data) collection.eks.describeNodegroups[AWSConfig.region][cluster][nodeGroup].data = data.nodegroup; diff --git a/collectors/aws/eks/listNodegroups.js b/collectors/aws/eks/listNodegroups.js index 3679225bfb..c1901a228b 100644 --- a/collectors/aws/eks/listNodegroups.js +++ b/collectors/aws/eks/listNodegroups.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var eks = new AWS.EKS(AWSConfig); async.eachLimit(collection.eks.listClusters[AWSConfig.region].data, 10, function(cluster, cb){ @@ -13,7 +13,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { clusterName: cluster }; - helpers.makeCustomCollectorCall(eks, 'listNodegroups', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(eks, 'listNodegroups', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) collection.eks.listNodegroups[AWSConfig.region][cluster].err = err; if (data) collection.eks.listNodegroups[AWSConfig.region][cluster].data = data.nodegroups; diff --git a/collectors/aws/elasticache/describeCacheSubnetGroups.js b/collectors/aws/elasticache/describeCacheSubnetGroups.js index 41736b4956..c27a51c348 100644 --- a/collectors/aws/elasticache/describeCacheSubnetGroups.js +++ b/collectors/aws/elasticache/describeCacheSubnetGroups.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var elasticache = new AWS.ElastiCache(AWSConfig); async.eachLimit(collection.elasticache.describeCacheClusters[AWSConfig.region].data, 15, function(cluster, cb){ @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { CacheSubnetGroupName: cluster.CacheSubnetGroupName }; - helpers.makeCustomCollectorCall(elasticache, 'describeCacheSubnetGroups', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(elasticache, 'describeCacheSubnetGroups', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.elasticache.describeCacheSubnetGroups[AWSConfig.region][cluster.CacheSubnetGroupName].err = err; } diff --git a/collectors/aws/elasticbeanstalk/describeConfigurationSettings.js b/collectors/aws/elasticbeanstalk/describeConfigurationSettings.js index 287476cd50..4b01885e07 100644 --- a/collectors/aws/elasticbeanstalk/describeConfigurationSettings.js +++ b/collectors/aws/elasticbeanstalk/describeConfigurationSettings.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var elasticbeanstalk = new AWS.ElasticBeanstalk(AWSConfig); async.eachLimit(collection.elasticbeanstalk.describeEnvironments[AWSConfig.region].data, 15, function(environment, cb) { @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { EnvironmentName: environment.EnvironmentName }; - helpers.makeCustomCollectorCall(elasticbeanstalk, 'describeConfigurationSettings', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(elasticbeanstalk, 'describeConfigurationSettings', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { collection.elasticbeanstalk.describeConfigurationSettings[AWSConfig.region][environment.EnvironmentArn] = {}; if (err || !data) { collection.elasticbeanstalk.describeConfigurationSettings[AWSConfig.region][environment.EnvironmentArn].err = err; diff --git a/collectors/aws/elb/describeInstanceHealth.js b/collectors/aws/elb/describeInstanceHealth.js index d7bfa57ebd..63c2144447 100644 --- a/collectors/aws/elb/describeInstanceHealth.js +++ b/collectors/aws/elb/describeInstanceHealth.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var elb = new AWS.ELB(AWSConfig); async.eachLimit(collection.elb.describeLoadBalancers[AWSConfig.region].data, 15, function(lb, cb){ @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'LoadBalancerName':lb.LoadBalancerName }; - helpers.makeCustomCollectorCall(elb, 'describeInstanceHealth', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(elb, 'describeInstanceHealth', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.elb.describeInstanceHealth[AWSConfig.region][lb.DNSName].err = err; } diff --git a/collectors/aws/elb/describeLoadBalancerAttributes.js b/collectors/aws/elb/describeLoadBalancerAttributes.js index 282ee9ef2b..c5256def6b 100644 --- a/collectors/aws/elb/describeLoadBalancerAttributes.js +++ b/collectors/aws/elb/describeLoadBalancerAttributes.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var elb = new AWS.ELB(AWSConfig); async.eachLimit(collection.elb.describeLoadBalancers[AWSConfig.region].data, 15, function(lb, cb){ @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'LoadBalancerName':lb.LoadBalancerName }; - helpers.makeCustomCollectorCall(elb, 'describeLoadBalancerAttributes', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(elb, 'describeLoadBalancerAttributes', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.elb.describeLoadBalancerAttributes[AWSConfig.region][lb.DNSName].err = err; } diff --git a/collectors/aws/elb/describeLoadBalancerPolicies.js b/collectors/aws/elb/describeLoadBalancerPolicies.js index e0c70dc934..caea948a56 100644 --- a/collectors/aws/elb/describeLoadBalancerPolicies.js +++ b/collectors/aws/elb/describeLoadBalancerPolicies.js @@ -4,7 +4,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var elb = new AWS.ELB(AWSConfig); // Gather list of policies from load balancers @@ -47,7 +47,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { PolicyNames: policy.PolicyNames }; - helpers.makeCustomCollectorCall(elb, 'describeLoadBalancerPolicies', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(elb, 'describeLoadBalancerPolicies', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.elb.describeLoadBalancerPolicies[AWSConfig.region][policy.DNSName].err = err; } else if (data) { diff --git a/collectors/aws/elb/describeTags.js b/collectors/aws/elb/describeTags.js index d673d44d4e..25d09a6ffb 100644 --- a/collectors/aws/elb/describeTags.js +++ b/collectors/aws/elb/describeTags.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var elb = new AWS.ELB(AWSConfig); async.eachLimit(collection.elb.describeLoadBalancers[AWSConfig.region].data, 15, function(lb, cb){ @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'LoadBalancerNames': [lb.LoadBalancerName] }; - helpers.makeCustomCollectorCall(elb, 'describeTags', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(elb, 'describeTags', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.elb.describeTags[AWSConfig.region][lb.LoadBalancerName].err = err; } diff --git a/collectors/aws/elbv2/describeListeners.js b/collectors/aws/elbv2/describeListeners.js index 794a1fd53c..b4dfadcd14 100644 --- a/collectors/aws/elbv2/describeListeners.js +++ b/collectors/aws/elbv2/describeListeners.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var elb = new AWS.ELBv2(AWSConfig); async.eachLimit(collection.elbv2.describeLoadBalancers[AWSConfig.region].data, 15, function(lb, cb){ @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'LoadBalancerArn':lb.LoadBalancerArn }; - helpers.makeCustomCollectorCall(elb, 'describeListeners', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(elb, 'describeListeners', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.elbv2.describeListeners[AWSConfig.region][lb.DNSName].err = err; } diff --git a/collectors/aws/elbv2/describeLoadBalancerAttributes.js b/collectors/aws/elbv2/describeLoadBalancerAttributes.js index 0e36f521a1..a29562f74d 100644 --- a/collectors/aws/elbv2/describeLoadBalancerAttributes.js +++ b/collectors/aws/elbv2/describeLoadBalancerAttributes.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var elb = new AWS.ELBv2(AWSConfig); async.eachLimit(collection.elbv2.describeLoadBalancers[AWSConfig.region].data, 15, function(lb, cb){ @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'LoadBalancerArn':lb.LoadBalancerArn }; - helpers.makeCustomCollectorCall(elb, 'describeLoadBalancerAttributes', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(elb, 'describeLoadBalancerAttributes', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.elbv2.describeLoadBalancerAttributes[AWSConfig.region][lb.DNSName].err = err; } diff --git a/collectors/aws/elbv2/describeTags.js b/collectors/aws/elbv2/describeTags.js index cb41af06d0..b01f3842ee 100644 --- a/collectors/aws/elbv2/describeTags.js +++ b/collectors/aws/elbv2/describeTags.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var elb = new AWS.ELBv2(AWSConfig); async.eachLimit(collection.elbv2.describeLoadBalancers[AWSConfig.region].data, 15, function(lb, cb){ @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'ResourceArns': [lb.LoadBalancerArn] }; - helpers.makeCustomCollectorCall(elb, 'describeTags', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(elb, 'describeTags', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.elbv2.describeTags[AWSConfig.region][lb.DNSName].err = err; } diff --git a/collectors/aws/elbv2/describeTargetGroups.js b/collectors/aws/elbv2/describeTargetGroups.js index 410b9a9ff7..775e143bdd 100644 --- a/collectors/aws/elbv2/describeTargetGroups.js +++ b/collectors/aws/elbv2/describeTargetGroups.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var elb = new AWS.ELBv2(AWSConfig); async.eachLimit(collection.elbv2.describeLoadBalancers[AWSConfig.region].data, 15, function(lb, cb){ @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'LoadBalancerArn':lb.LoadBalancerArn }; - helpers.makeCustomCollectorCall(elb, 'describeTargetGroups', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(elb, 'describeTargetGroups', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.elbv2.describeTargetGroups[AWSConfig.region][lb.DNSName].err = err; } diff --git a/collectors/aws/emr/describeSecurityConfiguration.js b/collectors/aws/emr/describeSecurityConfiguration.js index f919eb8da8..e31dd1b2b7 100644 --- a/collectors/aws/emr/describeSecurityConfiguration.js +++ b/collectors/aws/emr/describeSecurityConfiguration.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var emr = new AWS.EMR(AWSConfig); async.eachLimit(collection.emr.listClusters[AWSConfig.region].data, 15, function(cluster, cb){ @@ -22,7 +22,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'Name': securityConfigurationName }; - helpers.makeCustomCollectorCall(emr, 'describeSecurityConfiguration', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(emr, 'describeSecurityConfiguration', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.emr.describeSecurityConfiguration[AWSConfig.region][securityConfigurationName].err = err; } diff --git a/collectors/aws/firehose/describeDeliveryStream.js b/collectors/aws/firehose/describeDeliveryStream.js index abebc7e57f..16d16a911a 100644 --- a/collectors/aws/firehose/describeDeliveryStream.js +++ b/collectors/aws/firehose/describeDeliveryStream.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var firehose = new AWS.Firehose(AWSConfig); async.eachLimit(collection.firehose.listDeliveryStreams[AWSConfig.region].data, 15, function(deliverystream, cb){ @@ -12,7 +12,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { DeliveryStreamName: deliverystream }; - helpers.makeCustomCollectorCall(firehose, 'describeDeliveryStream', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(firehose, 'describeDeliveryStream', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.firehose.describeDeliveryStream[AWSConfig.region][deliverystream].err = err; } diff --git a/collectors/aws/guardduty/describePublishingDestination.js b/collectors/aws/guardduty/describePublishingDestination.js index 897608ef16..dcecebc862 100644 --- a/collectors/aws/guardduty/describePublishingDestination.js +++ b/collectors/aws/guardduty/describePublishingDestination.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var guardduty = new AWS.GuardDuty(AWSConfig); if (!collection.guardduty || @@ -26,7 +26,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { collection.guardduty.describePublishingDestination[AWSConfig.region][destination.DestinationId] = {}; // Make the describe destinations call - helpers.makeCustomCollectorCall(guardduty, 'describePublishingDestination', {DestinationId: destination.DestinationId, DetectorId: detectorId}, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(guardduty, 'describePublishingDestination', {DestinationId: destination.DestinationId, DetectorId: detectorId}, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.guardduty.describePublishingDestination[AWSConfig.region][destination.DestinationId].err = err; } diff --git a/collectors/aws/guardduty/getDetector.js b/collectors/aws/guardduty/getDetector.js index b04b7c3d71..e2f69fe448 100644 --- a/collectors/aws/guardduty/getDetector.js +++ b/collectors/aws/guardduty/getDetector.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var guardduty = new AWS.GuardDuty(AWSConfig); async.eachLimit(collection.guardduty.listDetectors[AWSConfig.region].data, 15, function(detectorId, cb) { collection.guardduty.getDetector[AWSConfig.region][detectorId] = {}; @@ -10,7 +10,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'DetectorId': detectorId }; - helpers.makeCustomCollectorCall(guardduty, 'getDetector', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(guardduty, 'getDetector', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.guardduty.getDetector[AWSConfig.region][detectorId].err = err; } diff --git a/collectors/aws/guardduty/getFindings.js b/collectors/aws/guardduty/getFindings.js index 26132a0fa7..5576b18d7a 100644 --- a/collectors/aws/guardduty/getFindings.js +++ b/collectors/aws/guardduty/getFindings.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var guardduty = new AWS.GuardDuty(AWSConfig); async.eachLimit(collection.guardduty.listDetectors[AWSConfig.region].data, 15, function(detectorId, dcb) { if (!collection.guardduty || @@ -22,7 +22,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { FindingIds: findingIds }; - helpers.makeCustomCollectorCall(guardduty, 'getFindings', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(guardduty, 'getFindings', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.guardduty.getFindings[AWSConfig.region][detectorId].err = err; } diff --git a/collectors/aws/guardduty/getMasterAccount.js b/collectors/aws/guardduty/getMasterAccount.js index 2e399f38f0..c1dcca0e8a 100644 --- a/collectors/aws/guardduty/getMasterAccount.js +++ b/collectors/aws/guardduty/getMasterAccount.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var guardduty = new AWS.GuardDuty(AWSConfig); async.eachLimit(collection.guardduty.listDetectors[AWSConfig.region].data, 15, function(detectorId, cb) { collection.guardduty.getMasterAccount[AWSConfig.region][detectorId] = {}; @@ -10,7 +10,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'DetectorId': detectorId }; - helpers.makeCustomCollectorCall(guardduty, 'getMasterAccount', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(guardduty, 'getMasterAccount', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.guardduty.getMasterAccount[AWSConfig.region][detectorId].err = err; } diff --git a/collectors/aws/guardduty/listFindings.js b/collectors/aws/guardduty/listFindings.js index 7e2826f89f..7ea391f138 100644 --- a/collectors/aws/guardduty/listFindings.js +++ b/collectors/aws/guardduty/listFindings.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var guardduty = new AWS.GuardDuty(AWSConfig); async.eachLimit(collection.guardduty.listDetectors[AWSConfig.region].data, 15, function(detectorId, cb) { collection.guardduty.listFindings[AWSConfig.region][detectorId] = {}; @@ -17,7 +17,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { } }; - helpers.makeCustomCollectorCall(guardduty, 'listFindings', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(guardduty, 'listFindings', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.guardduty.listFindings[AWSConfig.region][detectorId].err = err; } diff --git a/collectors/aws/guardduty/listPublishingDestinations.js b/collectors/aws/guardduty/listPublishingDestinations.js index e6d7f7a3b7..fd4a117566 100644 --- a/collectors/aws/guardduty/listPublishingDestinations.js +++ b/collectors/aws/guardduty/listPublishingDestinations.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var guardduty = new AWS.GuardDuty(AWSConfig); async.eachLimit(collection.guardduty.listDetectors[AWSConfig.region].data, 15, function(detectorId, cb) { collection.guardduty.listPublishingDestinations[AWSConfig.region][detectorId] = {}; @@ -10,7 +10,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'DetectorId': detectorId }; - helpers.makeCustomCollectorCall(guardduty, 'listPublishingDestinations', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(guardduty, 'listPublishingDestinations', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.guardduty.listPublishingDestinations[AWSConfig.region][detectorId].err = err; } diff --git a/collectors/aws/iam/generateCredentialReport.js b/collectors/aws/iam/generateCredentialReport.js index 4ee1fdb2f3..8838475b80 100644 --- a/collectors/aws/iam/generateCredentialReport.js +++ b/collectors/aws/iam/generateCredentialReport.js @@ -1,7 +1,7 @@ var AWS = require('aws-sdk'); var async = require('async'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var iam = new AWS.IAM(AWSConfig); var generateCredentialReport = function(genCb) { diff --git a/collectors/aws/iam/getGroupPolicy.js b/collectors/aws/iam/getGroupPolicy.js index 95b2512819..40f4a4b7af 100644 --- a/collectors/aws/iam/getGroupPolicy.js +++ b/collectors/aws/iam/getGroupPolicy.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var iam = new AWS.IAM(AWSConfig); if (!collection.iam || @@ -39,7 +39,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { async.eachLimit(collection.iam.listGroupPolicies[AWSConfig.region][group.GroupName].data.PolicyNames, 5, function(policyName, pCb){ collection.iam.getGroupPolicy[AWSConfig.region][group.GroupName][policyName] = {}; - helpers.makeCustomCollectorCall(iam, 'getGroupPolicy', {PolicyName: policyName, GroupName: group.GroupName}, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(iam, 'getGroupPolicy', {PolicyName: policyName, GroupName: group.GroupName}, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.iam.getGroupPolicy[AWSConfig.region][group.GroupName][policyName].err = err; return pCb(); diff --git a/collectors/aws/iam/getInstanceProfile.js b/collectors/aws/iam/getInstanceProfile.js index 453e2a78fa..8358155761 100644 --- a/collectors/aws/iam/getInstanceProfile.js +++ b/collectors/aws/iam/getInstanceProfile.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var iam = new AWS.IAM(AWSConfig); if (!collection.ec2 || @@ -28,7 +28,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { collection.iam.getInstanceProfile[AWSConfig.region][instance.IamInstanceProfile.Arn] = {}; - helpers.makeCustomCollectorCall(iam, 'getInstanceProfile', {InstanceProfileName: iamInstanceProfileName}, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(iam, 'getInstanceProfile', {InstanceProfileName: iamInstanceProfileName}, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.iam.getInstanceProfile[AWSConfig.region][instance.IamInstanceProfile.Arn].err = err; } diff --git a/collectors/aws/iam/getPolicyVersion.js b/collectors/aws/iam/getPolicyVersion.js index 70bb12a38f..3c46c052d0 100644 --- a/collectors/aws/iam/getPolicyVersion.js +++ b/collectors/aws/iam/getPolicyVersion.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var iam = new AWS.IAM(AWSConfig); if (!collection.iam || @@ -25,7 +25,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { var versionId = collection.iam.getPolicy[AWSConfig.region][policy.Arn].data.Policy.DefaultVersionId; collection.iam.getPolicyVersion[AWSConfig.region][policy.Arn] = {}; - helpers.makeCustomCollectorCall(iam, 'getPolicyVersion', {PolicyArn: policy.Arn, VersionId: versionId}, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(iam, 'getPolicyVersion', {PolicyArn: policy.Arn, VersionId: versionId}, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.iam.getPolicyVersion[AWSConfig.region][policy.Arn].err = err; } diff --git a/collectors/aws/iam/getRole.js b/collectors/aws/iam/getRole.js index 5ec172fe45..4b37a4ab0b 100644 --- a/collectors/aws/iam/getRole.js +++ b/collectors/aws/iam/getRole.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var iam = new AWS.IAM(AWSConfig); if (!collection.iam || @@ -21,7 +21,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { collection.iam.getRole[AWSConfig.region][role.RoleName] = {}; - helpers.makeCustomCollectorCall(iam, 'getRole', {RoleName: role.RoleName}, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(iam, 'getRole', {RoleName: role.RoleName}, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.iam.getRole[AWSConfig.region][role.RoleName].err = err; } diff --git a/collectors/aws/iam/getRolePolicy.js b/collectors/aws/iam/getRolePolicy.js index 239d1e45a9..e050c89ffc 100644 --- a/collectors/aws/iam/getRolePolicy.js +++ b/collectors/aws/iam/getRolePolicy.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var iam = new AWS.IAM(AWSConfig); if (!collection.iam || @@ -51,7 +51,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { async.eachLimit(collection.iam.listRolePolicies[AWSConfig.region][role.RoleName].data.PolicyNames, 5, function(policyName, pCb){ collection.iam.getRolePolicy[AWSConfig.region][role.RoleName][policyName] = {}; - helpers.makeCustomCollectorCall(iam, 'getRolePolicy', {PolicyName: policyName,RoleName: role.RoleName}, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(iam, 'getRolePolicy', {PolicyName: policyName,RoleName: role.RoleName}, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.iam.getRolePolicy[AWSConfig.region][role.RoleName][policyName].err = err; return pCb(); diff --git a/collectors/aws/iam/getUserPolicy.js b/collectors/aws/iam/getUserPolicy.js index d40a3a20d9..077ad47274 100644 --- a/collectors/aws/iam/getUserPolicy.js +++ b/collectors/aws/iam/getUserPolicy.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var iam = new AWS.IAM(AWSConfig); if (!collection.iam || @@ -49,7 +49,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { async.each(collection.iam.listUserPolicies[AWSConfig.region][user.UserName].data.PolicyNames, function(policyName, pCb){ collection.iam.getUserPolicy[AWSConfig.region][user.UserName][policyName] = {}; - helpers.makeCustomCollectorCall(iam, 'getUserPolicy', {PolicyName: policyName,UserName: user.UserName}, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(iam, 'getUserPolicy', {PolicyName: policyName,UserName: user.UserName}, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.iam.getUserPolicy[AWSConfig.region][user.UserName][policyName].err = err; return pCb(); diff --git a/collectors/aws/iam/listRoles.js b/collectors/aws/iam/listRoles.js index c16f2a5c49..86540d6d66 100644 --- a/collectors/aws/iam/listRoles.js +++ b/collectors/aws/iam/listRoles.js @@ -1,7 +1,7 @@ var AWS = require('aws-sdk'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var iam = new AWS.IAM(AWSConfig); collection.iam.listRoles[AWSConfig.region] = {}; var params = {}; @@ -33,7 +33,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { function execute(marker) { var localParams = JSON.parse(JSON.stringify(params || {})); if (marker) localParams['Marker'] = marker; - helpers.makeCustomCollectorCall(iam, 'listRoles', localParams, retries, null, null, null, paginateCb); + helpers.makeCustomCollectorCall(iam, 'listRoles', localParams, retries, null, null, null, settings, scanAWSConfig, AWSConfig, paginateCb); } execute(); diff --git a/collectors/aws/kinesis/describeStream.js b/collectors/aws/kinesis/describeStream.js index 31bcb0b1a1..a06defbda8 100644 --- a/collectors/aws/kinesis/describeStream.js +++ b/collectors/aws/kinesis/describeStream.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var kinesis = new AWS.Kinesis(AWSConfig); async.eachLimit(collection.kinesis.listStreams[AWSConfig.region].data, 15, function(stream, cb){ @@ -12,7 +12,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { StreamName: stream }; - helpers.makeCustomCollectorCall(kinesis, 'describeStream', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(kinesis, 'describeStream', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.kinesis.describeStream[AWSConfig.region][stream].err = err; } diff --git a/collectors/aws/kms/getKeyPolicy.js b/collectors/aws/kms/getKeyPolicy.js index 4e562042f3..d11091aa36 100644 --- a/collectors/aws/kms/getKeyPolicy.js +++ b/collectors/aws/kms/getKeyPolicy.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var kms = new AWS.KMS(AWSConfig); async.eachLimit(collection.kms.listKeys[AWSConfig.region].data, 15, function(key, cb){ @@ -16,7 +16,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { PolicyName: 'default' }; - helpers.makeCustomCollectorCall(kms, 'getKeyPolicy', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(kms, 'getKeyPolicy', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.kms.getKeyPolicy[AWSConfig.region][key.KeyId].err = err; } diff --git a/collectors/aws/kms/listGrants.js b/collectors/aws/kms/listGrants.js index 4272e478b5..a5c24a9df6 100644 --- a/collectors/aws/kms/listGrants.js +++ b/collectors/aws/kms/listGrants.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var kms = new AWS.KMS(AWSConfig); async.eachLimit(collection.kms.listKeys[AWSConfig.region].data, 15, function(key, cb) { collection.kms.listGrants[AWSConfig.region][key.KeyId] = {}; @@ -36,9 +36,9 @@ module.exports = function(AWSConfig, collection, retries, callback) { var localParams = JSON.parse(JSON.stringify(params || {})); if (marker) localParams['Marker'] = marker; if (marker) { - helpers.makeCustomCollectorCall(kms, 'listGrants', localParams, retries, null, null, null, paginateCb); + helpers.makeCustomCollectorCall(kms, 'listGrants', localParams, retries, null, null, null, settings, scanAWSConfig, AWSConfig, paginateCb); } else { - helpers.makeCustomCollectorCall(kms, 'listGrants', params, retries, null, null, null, paginateCb); + helpers.makeCustomCollectorCall(kms, 'listGrants', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, paginateCb); } } diff --git a/collectors/aws/lexmodelsv2/describeBotAlias.js b/collectors/aws/lexmodelsv2/describeBotAlias.js index fb6c951af8..a4ba34ea31 100644 --- a/collectors/aws/lexmodelsv2/describeBotAlias.js +++ b/collectors/aws/lexmodelsv2/describeBotAlias.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var lexmodelsv2 = new AWS.LexModelsV2(AWSConfig); if (!collection.lexmodelsv2 || @@ -24,7 +24,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { async.eachLimit(collection.lexmodelsv2.listBotAliases[AWSConfig.region][bot.botId].data.botAliasSummaries, 3, function(alias, pCb){ collection.lexmodelsv2.describeBotAlias[AWSConfig.region][alias.botAliasId] = {}; - helpers.makeCustomCollectorCall(lexmodelsv2, 'describeBotAlias', {botAliasId: alias.botAliasId,botId: bot.botId}, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(lexmodelsv2, 'describeBotAlias', {botAliasId: alias.botAliasId,botId: bot.botId}, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.lexmodelsv2.describeBotAlias[AWSConfig.region][alias.botAliasId].err = err; } diff --git a/collectors/aws/lookoutvision/describeModel.js b/collectors/aws/lookoutvision/describeModel.js index a3216bf2c2..75d543d3aa 100644 --- a/collectors/aws/lookoutvision/describeModel.js +++ b/collectors/aws/lookoutvision/describeModel.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var lookoutvision = new AWS.LookoutVision(AWSConfig); if (!collection.lookoutvision || @@ -26,7 +26,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { collection.lookoutvision.describeModel[AWSConfig.region][model.ModelArn] = {}; // Make the describe Models call - helpers.makeCustomCollectorCall(lookoutvision, 'describeModel', {ModelVersion: model.ModelVersion,ProjectName: project.ProjectName}, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(lookoutvision, 'describeModel', {ModelVersion: model.ModelVersion,ProjectName: project.ProjectName}, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.lookoutvision.describeModel[AWSConfig.region][model.ModelArn].err = err; } diff --git a/collectors/aws/managedblockchain/getMember.js b/collectors/aws/managedblockchain/getMember.js index 17b99ffe65..eb6bf5e604 100644 --- a/collectors/aws/managedblockchain/getMember.js +++ b/collectors/aws/managedblockchain/getMember.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var managedblockchain = new AWS.ManagedBlockchain(AWSConfig); if (!collection.managedblockchain || @@ -23,7 +23,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { async.eachLimit(collection.managedblockchain.listMembers[AWSConfig.region][network.Id].data.Members, 5, function(member, mcb){ collection.managedblockchain.getMember[AWSConfig.region][member.Id] = {}; - helpers.makeCustomCollectorCall(managedblockchain, 'getMember', {MemberId: member.Id,NetworkId: network.Id}, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(managedblockchain, 'getMember', {MemberId: member.Id,NetworkId: network.Id}, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.managedblockchain.getMember[AWSConfig.region][member.Id].err = err; } diff --git a/collectors/aws/mwaa/getEnvironment.js b/collectors/aws/mwaa/getEnvironment.js index 9d992a124b..21d95a357f 100644 --- a/collectors/aws/mwaa/getEnvironment.js +++ b/collectors/aws/mwaa/getEnvironment.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var mwaa = new AWS.MWAA(AWSConfig); async.eachLimit(collection.mwaa.listEnvironments[AWSConfig.region].data, 15, function(env, cb){ @@ -12,7 +12,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { Name: env }; - helpers.makeCustomCollectorCall(mwaa, 'getEnvironment', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(mwaa, 'getEnvironment', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.mwaa.getEnvironment[AWSConfig.region][env].err = err; } diff --git a/collectors/aws/opensearchserverless/getEncryptionSecurityPolicy.js b/collectors/aws/opensearchserverless/getEncryptionSecurityPolicy.js index 8944a652cd..bea3e24fbe 100644 --- a/collectors/aws/opensearchserverless/getEncryptionSecurityPolicy.js +++ b/collectors/aws/opensearchserverless/getEncryptionSecurityPolicy.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var ecs = new AWS.OpenSearchServerless(AWSConfig); async.eachLimit(collection.opensearchserverless.listEncryptionSecurityPolicies[AWSConfig.region].data, 10, function(policy, cb){ @@ -12,7 +12,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { type: 'encryption' }; - helpers.makeCustomCollectorCall(ecs, 'getSecurityPolicy', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(ecs, 'getSecurityPolicy', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.opensearchserverless.getEncryptionSecurityPolicy[AWSConfig.region][policy.name].err = err; } diff --git a/collectors/aws/opensearchserverless/getNetworkSecurityPolicy.js b/collectors/aws/opensearchserverless/getNetworkSecurityPolicy.js index cc87011fcf..ba30f6aef1 100644 --- a/collectors/aws/opensearchserverless/getNetworkSecurityPolicy.js +++ b/collectors/aws/opensearchserverless/getNetworkSecurityPolicy.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var ecs = new AWS.OpenSearchServerless(AWSConfig); async.eachLimit(collection.opensearchserverless.listNetworkSecurityPolicies[AWSConfig.region].data, 10, function(policy, cb){ collection.opensearchserverless.getNetworkSecurityPolicy[AWSConfig.region][policy.name] = {}; @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { type: 'network' }; - helpers.makeCustomCollectorCall(ecs, 'getSecurityPolicy', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(ecs, 'getSecurityPolicy', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.opensearchserverless.getNetworkSecurityPolicy[AWSConfig.region][policy.name].err = err; } diff --git a/collectors/aws/opensearchserverless/listEncryptionSecurityPolicies.js b/collectors/aws/opensearchserverless/listEncryptionSecurityPolicies.js index 590dbc71dc..a7e285aaea 100644 --- a/collectors/aws/opensearchserverless/listEncryptionSecurityPolicies.js +++ b/collectors/aws/opensearchserverless/listEncryptionSecurityPolicies.js @@ -1,13 +1,13 @@ var AWS = require('aws-sdk'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var opensearch = new AWS.OpenSearchServerless(AWSConfig); collection.opensearchserverless.listEncryptionSecurityPolicies[AWSConfig.region] = {}; let params = { type: 'encryption' }; - helpers.makeCustomCollectorCall(opensearch, 'listSecurityPolicies', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(opensearch, 'listSecurityPolicies', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.opensearchserverless.listEncryptionSecurityPolicies[AWSConfig.region].err = err; } else if (data && data.securityPolicySummaries){ diff --git a/collectors/aws/opensearchserverless/listNetworkSecurityPolicies.js b/collectors/aws/opensearchserverless/listNetworkSecurityPolicies.js index f1f55ca919..c1742478ad 100644 --- a/collectors/aws/opensearchserverless/listNetworkSecurityPolicies.js +++ b/collectors/aws/opensearchserverless/listNetworkSecurityPolicies.js @@ -1,13 +1,13 @@ var AWS = require('aws-sdk'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var opensearch = new AWS.OpenSearchServerless(AWSConfig); collection.opensearchserverless.listNetworkSecurityPolicies[AWSConfig.region] = {}; let params = { type: 'network' }; - helpers.makeCustomCollectorCall(opensearch, 'listSecurityPolicies', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(opensearch, 'listSecurityPolicies', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.opensearchserverless.listNetworkSecurityPolicies[AWSConfig.region].err = err; } else if (data && data.securityPolicySummaries) { diff --git a/collectors/aws/rds/describeDBParameters.js b/collectors/aws/rds/describeDBParameters.js index 5cf608fa16..c158137981 100644 --- a/collectors/aws/rds/describeDBParameters.js +++ b/collectors/aws/rds/describeDBParameters.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var rds = new AWS.RDS(AWSConfig); async.eachLimit(collection.rds.describeDBParameterGroups[AWSConfig.region].data, 15, function(group, cb) { collection.rds.describeDBParameters[AWSConfig.region][group.DBParameterGroupName] = {}; @@ -36,9 +36,9 @@ module.exports = function(AWSConfig, collection, retries, callback) { var localParams = JSON.parse(JSON.stringify(params || {})); if (marker) localParams['Marker'] = marker; if (marker) { - helpers.makeCustomCollectorCall(rds, 'describeDBParameters', localParams, retries, null, null, null, paginateCb); + helpers.makeCustomCollectorCall(rds, 'describeDBParameters', localParams, retries, null, null, null, settings, scanAWSConfig, AWSConfig, paginateCb); } else { - helpers.makeCustomCollectorCall(rds, 'describeDBParameters', params, retries, null, null, null, paginateCb); + helpers.makeCustomCollectorCall(rds, 'describeDBParameters', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, paginateCb); } } diff --git a/collectors/aws/s3/getBucketAcl.js b/collectors/aws/s3/getBucketAcl.js index e0dc545e47..0c38c123ed 100644 --- a/collectors/aws/s3/getBucketAcl.js +++ b/collectors/aws/s3/getBucketAcl.js @@ -1,5 +1,5 @@ var index = require(__dirname + '/index.js'); -module.exports = function(AWSConfig, collection, retries, callback) { - index('getBucketAcl', false, AWSConfig, collection, retries, callback); +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + index('getBucketAcl', false, AWSConfig, collection, retries, settings, scanAWSConfig, callback); }; \ No newline at end of file diff --git a/collectors/aws/s3/getBucketEncryption.js b/collectors/aws/s3/getBucketEncryption.js index 07eb28a2a7..8ff58568d9 100644 --- a/collectors/aws/s3/getBucketEncryption.js +++ b/collectors/aws/s3/getBucketEncryption.js @@ -1,5 +1,5 @@ var index = require(__dirname + '/index.js'); -module.exports = function(AWSConfig, collection, retries, callback) { - index('getBucketEncryption', false, AWSConfig, collection, retries, callback); +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + index('getBucketEncryption', false, AWSConfig, collection, retries, settings, scanAWSConfig, callback); }; \ No newline at end of file diff --git a/collectors/aws/s3/getBucketLifecycleConfiguration.js b/collectors/aws/s3/getBucketLifecycleConfiguration.js index 2ccd972743..2f2540c70c 100644 --- a/collectors/aws/s3/getBucketLifecycleConfiguration.js +++ b/collectors/aws/s3/getBucketLifecycleConfiguration.js @@ -1,5 +1,5 @@ var index = require(__dirname + '/index.js'); -module.exports = function(AWSConfig, collection, retries, callback) { - index('getBucketLifecycleConfiguration', false, AWSConfig, collection, retries, callback); +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + index('getBucketLifecycleConfiguration', false, AWSConfig, collection, retries, settings, scanAWSConfig, callback); }; \ No newline at end of file diff --git a/collectors/aws/s3/getBucketLocation.js b/collectors/aws/s3/getBucketLocation.js index 1f765eebf8..b1105bf6d4 100644 --- a/collectors/aws/s3/getBucketLocation.js +++ b/collectors/aws/s3/getBucketLocation.js @@ -1,5 +1,5 @@ var index = require(__dirname + '/index.js'); -module.exports = function(AWSConfig, collection, retries, callback) { - index('getBucketLocation', false, AWSConfig, collection, retries, callback); +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + index('getBucketLocation', false, AWSConfig, collection, retries, settings, scanAWSConfig, callback); }; \ No newline at end of file diff --git a/collectors/aws/s3/getBucketLogging.js b/collectors/aws/s3/getBucketLogging.js index f9eb082c3a..29fdce76dc 100644 --- a/collectors/aws/s3/getBucketLogging.js +++ b/collectors/aws/s3/getBucketLogging.js @@ -1,5 +1,5 @@ var index = require(__dirname + '/index.js'); -module.exports = function(AWSConfig, collection, retries, callback) { - index('getBucketLogging', false, AWSConfig, collection, retries, callback); +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + index('getBucketLogging', false, AWSConfig, collection, retries, settings, scanAWSConfig, callback); }; \ No newline at end of file diff --git a/collectors/aws/s3/getBucketPolicy.js b/collectors/aws/s3/getBucketPolicy.js index 0d02b83d42..667129ce5a 100644 --- a/collectors/aws/s3/getBucketPolicy.js +++ b/collectors/aws/s3/getBucketPolicy.js @@ -1,5 +1,5 @@ var index = require(__dirname + '/index.js'); -module.exports = function(AWSConfig, collection, retries, callback) { - index('getBucketPolicy', false, AWSConfig, collection, retries, callback); +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + index('getBucketPolicy', false, AWSConfig, collection, retries, settings, scanAWSConfig, callback); }; \ No newline at end of file diff --git a/collectors/aws/s3/getBucketPolicyStatus.js b/collectors/aws/s3/getBucketPolicyStatus.js index 7f91143fa1..7b30fb8533 100644 --- a/collectors/aws/s3/getBucketPolicyStatus.js +++ b/collectors/aws/s3/getBucketPolicyStatus.js @@ -1,5 +1,5 @@ var index = require(__dirname + '/index.js'); -module.exports = function(AWSConfig, collection, retries, callback) { - index('getBucketPolicyStatus', false, AWSConfig, collection, retries, callback); +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + index('getBucketPolicyStatus', false, AWSConfig, collection, retries, settings, scanAWSConfig, callback); }; \ No newline at end of file diff --git a/collectors/aws/s3/getBucketTagging.js b/collectors/aws/s3/getBucketTagging.js index b6197f9f12..ddf2f234bc 100644 --- a/collectors/aws/s3/getBucketTagging.js +++ b/collectors/aws/s3/getBucketTagging.js @@ -1,5 +1,5 @@ var index = require(__dirname + '/index.js'); -module.exports = function(AWSConfig, collection, retries, callback) { - index('getBucketTagging', false, AWSConfig, collection, retries, callback); +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + index('getBucketTagging', false, AWSConfig, collection, retries, settings, scanAWSConfig, callback); }; diff --git a/collectors/aws/s3/getBucketVersioning.js b/collectors/aws/s3/getBucketVersioning.js index 8a114cfe52..9a842f761f 100644 --- a/collectors/aws/s3/getBucketVersioning.js +++ b/collectors/aws/s3/getBucketVersioning.js @@ -1,5 +1,5 @@ var index = require(__dirname + '/index.js'); -module.exports = function(AWSConfig, collection, retries, callback) { - index('getBucketVersioning', false, AWSConfig, collection, retries, callback); +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + index('getBucketVersioning', false, AWSConfig, collection, retries, settings, scanAWSConfig, callback); }; \ No newline at end of file diff --git a/collectors/aws/s3/getBucketWebsite.js b/collectors/aws/s3/getBucketWebsite.js index 0357b60df0..ab61437a65 100644 --- a/collectors/aws/s3/getBucketWebsite.js +++ b/collectors/aws/s3/getBucketWebsite.js @@ -1,5 +1,5 @@ var index = require(__dirname + '/index.js'); -module.exports = function(AWSConfig, collection, retries, callback) { - index('getBucketWebsite', false, AWSConfig, collection, retries, callback); +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + index('getBucketWebsite', false, AWSConfig, collection, retries, settings, scanAWSConfig, callback); }; \ No newline at end of file diff --git a/collectors/aws/s3/getObjectLockConfiguration.js b/collectors/aws/s3/getObjectLockConfiguration.js index fb280059d8..1c61e923f0 100644 --- a/collectors/aws/s3/getObjectLockConfiguration.js +++ b/collectors/aws/s3/getObjectLockConfiguration.js @@ -1,5 +1,5 @@ var index = require(__dirname + '/index.js'); -module.exports = function(AWSConfig, collection, retries, callback) { - index('getObjectLockConfiguration', false, AWSConfig, collection, retries, callback); +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + index('getObjectLockConfiguration', false, AWSConfig, collection, retries, settings, scanAWSConfig, callback); }; \ No newline at end of file diff --git a/collectors/aws/s3/getPublicAccessBlock.js b/collectors/aws/s3/getPublicAccessBlock.js index dddf5be6a6..f14ea6dcef 100644 --- a/collectors/aws/s3/getPublicAccessBlock.js +++ b/collectors/aws/s3/getPublicAccessBlock.js @@ -1,5 +1,5 @@ var index = require(__dirname + '/index.js'); -module.exports = function(AWSConfig, collection, retries, callback) { - index('getPublicAccessBlock', false, AWSConfig, collection, retries, callback); +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + index('getPublicAccessBlock', false, AWSConfig, collection, retries, settings, scanAWSConfig, callback); }; \ No newline at end of file diff --git a/collectors/aws/s3/index.js b/collectors/aws/s3/index.js index bbcac26df5..761decdb06 100644 --- a/collectors/aws/s3/index.js +++ b/collectors/aws/s3/index.js @@ -2,8 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(callKey, forceCloudTrail, AWSConfig, collection, retries, callback) { - var s3 = new AWS.S3(AWSConfig); +module.exports = function(callKey, forceCloudTrail, AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var knownBuckets = []; @@ -26,7 +25,7 @@ module.exports = function(callKey, forceCloudTrail, AWSConfig, collection, retri for (var t in collection.cloudtrail.describeTrails[region].data) { var trail = collection.cloudtrail.describeTrails[region].data[t]; - + if (knownBuckets.indexOf(trail.S3BucketName) === -1) { knownBuckets.push(trail.S3BucketName); } @@ -37,18 +36,19 @@ module.exports = function(callKey, forceCloudTrail, AWSConfig, collection, retri if (!knownBuckets || !knownBuckets.length) return callback(); async.eachLimit(knownBuckets, 10, function(bucket, bcb){ + var s3 = new AWS.S3(AWSConfig); collection['s3'][callKey][AWSConfig.region][bucket] = {}; - helpers.makeCustomCollectorCall(s3, callKey, {Bucket:bucket}, retries, null, null, null, function(bErr, bData) { + helpers.makeCustomCollectorCall(s3, callKey, {Bucket:bucket}, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(bErr, bData) { if (bErr) { collection['s3'][callKey][AWSConfig.region][bucket].err = bErr; if (bErr.statusCode && bErr.statusCode == 301) { - helpers.makeCustomCollectorCall(s3, 'getBucketLocation', {Bucket:bucket}, retries, null, null, null, function(locErr, locData) { + helpers.makeCustomCollectorCall(s3, 'getBucketLocation', {Bucket:bucket}, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(locErr, locData) { if (locErr || !locData || !locData.LocationConstraint) return bcb(); // Special case where location constraint is EU - rewrite as eu-west-1 if (locData.LocationConstraint == 'EU') locData.LocationConstraint = 'eu-west-1'; - + var altAWSConfig = JSON.parse(JSON.stringify(AWSConfig)); altAWSConfig.region = locData.LocationConstraint; var s3Alt = new AWS.S3(altAWSConfig); @@ -74,4 +74,4 @@ module.exports = function(callKey, forceCloudTrail, AWSConfig, collection, retri }, function(){ callback(); }); -}; \ No newline at end of file +}; diff --git a/collectors/aws/s3control/getPublicAccessBlock.js b/collectors/aws/s3control/getPublicAccessBlock.js index 0ea179f5f1..6d5b90cd2e 100644 --- a/collectors/aws/s3control/getPublicAccessBlock.js +++ b/collectors/aws/s3control/getPublicAccessBlock.js @@ -1,7 +1,7 @@ var AWS = require('aws-sdk'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var s3control = new AWS.S3Control(AWSConfig); var accountId = collection.sts.getCallerIdentity[AWSConfig.region].data; @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { AccountId: accountId }; - helpers.makeCustomCollectorCall(s3control, 'getPublicAccessBlock', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(s3control, 'getPublicAccessBlock', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.s3control.getPublicAccessBlock[AWSConfig.region][accountId].err = err; } diff --git a/collectors/aws/securityhub/getFindings.js b/collectors/aws/securityhub/getFindings.js index 52e94a459d..2b7f84f8fb 100644 --- a/collectors/aws/securityhub/getFindings.js +++ b/collectors/aws/securityhub/getFindings.js @@ -1,7 +1,7 @@ var AWS = require('aws-sdk'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var securityhub = new AWS.SecurityHub(AWSConfig); collection.securityhub.getFindings[AWSConfig.region] = {}; @@ -34,7 +34,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { }; function execute() { - helpers.makeCustomCollectorCall(securityhub, 'getFindings', params, retries, null, null, null, paginateCb); + helpers.makeCustomCollectorCall(securityhub, 'getFindings', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, paginateCb); } execute(); }; diff --git a/collectors/aws/ses/getIdentityDkimAttributes.js b/collectors/aws/ses/getIdentityDkimAttributes.js index 3e51064970..d47ed4fec6 100644 --- a/collectors/aws/ses/getIdentityDkimAttributes.js +++ b/collectors/aws/ses/getIdentityDkimAttributes.js @@ -1,7 +1,7 @@ var AWS = require('aws-sdk'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var ses = new AWS.SES(AWSConfig); collection.ses.getIdentityDkimAttributes[AWSConfig.region] = {}; @@ -23,7 +23,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { }; setTimeout(function() { - helpers.makeCustomCollectorCall(ses, 'getIdentityDkimAttributes', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(ses, 'getIdentityDkimAttributes', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.ses.getIdentityDkimAttributes[AWSConfig.region].err = err; } else if (data && data.DkimAttributes) { diff --git a/collectors/aws/sqs/getQueueAttributes.js b/collectors/aws/sqs/getQueueAttributes.js index b85e355c25..64ad1e3cb9 100644 --- a/collectors/aws/sqs/getQueueAttributes.js +++ b/collectors/aws/sqs/getQueueAttributes.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var sqs = new AWS.SQS(AWSConfig); async.eachLimit(collection.sqs.listQueues[AWSConfig.region].data, 15, function(queue, cb){ @@ -15,7 +15,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { ] }; - helpers.makeCustomCollectorCall(sqs, 'getQueueAttributes', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(sqs, 'getQueueAttributes', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.sqs.getQueueAttributes[AWSConfig.region][queue].err = err; } diff --git a/collectors/aws/ssm/describeDocumentPermission.js b/collectors/aws/ssm/describeDocumentPermission.js new file mode 100644 index 0000000000..45da3899ad --- /dev/null +++ b/collectors/aws/ssm/describeDocumentPermission.js @@ -0,0 +1,48 @@ +var AWS = require('aws-sdk'); +var async = require('async'); +var helpers = require(__dirname + '/../../../helpers/aws'); + +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + var ssm = new AWS.SSM(AWSConfig); + + async.eachLimit(collection.ssm.listDocuments[AWSConfig.region].data, 10, function(doc, cb){ + collection.ssm.describeDocumentPermission[AWSConfig.region][doc.Name] = {}; + + var paginating = false; + var paginateCb = function(err, data) { + if (err) { + collection.ssm.describeDocumentPermission[AWSConfig.region][doc.Name].err = err; + } else if (data) { + var existing = collection.ssm.describeDocumentPermission[AWSConfig.region][doc.Name].data; + if (paginating && existing) { + existing.AccountIds = (existing.AccountIds || []).concat(data.AccountIds || []); + existing.AccountSharingInfoList = (existing.AccountSharingInfoList || []).concat(data.AccountSharingInfoList || []); + delete existing.NextToken; + } else { + collection.ssm.describeDocumentPermission[AWSConfig.region][doc.Name].data = data; + } + + if (data.NextToken && data.NextToken.length) { + paginating = true; + return execute(data.NextToken); + } + } + + cb(); + }; + + function execute(nextToken) { + var params = { + Name: doc.Name, + PermissionType: 'Share' + }; + if (nextToken) params.NextToken = nextToken; + + helpers.makeCustomCollectorCall(ssm, 'describeDocumentPermission', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, paginateCb); + } + + execute(); + }, function(){ + callback(); + }); +}; diff --git a/collectors/aws/ssm/describeParameters.js b/collectors/aws/ssm/describeParameters.js index 4c7eb39321..0a5257af49 100644 --- a/collectors/aws/ssm/describeParameters.js +++ b/collectors/aws/ssm/describeParameters.js @@ -1,7 +1,7 @@ var AWS = require('aws-sdk'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var ssm = new AWS.SSM(AWSConfig); collection.ssm.describeParameters[AWSConfig.region] = {}; var params = {}; @@ -33,7 +33,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { function execute(marker) { var localParams = JSON.parse(JSON.stringify(params || {})); if (marker) localParams['NextToken'] = marker; - helpers.makeCustomCollectorCall(ssm, 'describeParameters', localParams, retries, null, null, null, paginateCb); + helpers.makeCustomCollectorCall(ssm, 'describeParameters', localParams, retries, null, null, null, settings, scanAWSConfig, AWSConfig, paginateCb); } execute(); diff --git a/collectors/aws/storagegateway/describeNFSFileShares.js b/collectors/aws/storagegateway/describeNFSFileShares.js new file mode 100644 index 0000000000..8fe473ade1 --- /dev/null +++ b/collectors/aws/storagegateway/describeNFSFileShares.js @@ -0,0 +1,43 @@ +var AWS = require('aws-sdk'); +var async = require('async'); +var helpers = require(__dirname + '/../../../helpers/aws'); + +// DescribeNFSFileShares accepts at most 10 file share ARNs per request +var MAX_ARNS_PER_CALL = 10; + +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + var storagegateway = new AWS.StorageGateway(AWSConfig); + + var arns = collection.storagegateway.listFileShares[AWSConfig.region].data + .filter(function(share) { + return share.FileShareType === 'NFS' && share.FileShareARN; + }) + .map(function(share) { + return share.FileShareARN; + }); + + var chunks = []; + for (var i = 0; i < arns.length; i += MAX_ARNS_PER_CALL) { + chunks.push(arns.slice(i, i + MAX_ARNS_PER_CALL)); + } + + collection.storagegateway.describeNFSFileShares[AWSConfig.region].data = []; + + async.eachLimit(chunks, 5, function(chunk, cb){ + var params = { + FileShareARNList: chunk + }; + + helpers.makeCustomCollectorCall(storagegateway, 'describeNFSFileShares', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { + if (err) { + collection.storagegateway.describeNFSFileShares[AWSConfig.region].err = err; + } else if (data && data.NFSFileShareInfoList && data.NFSFileShareInfoList.length) { + collection.storagegateway.describeNFSFileShares[AWSConfig.region].data = + collection.storagegateway.describeNFSFileShares[AWSConfig.region].data.concat(data.NFSFileShareInfoList); + } + cb(); + }); + }, function(){ + callback(); + }); +}; diff --git a/collectors/aws/storagegateway/describeSMBFileShares.js b/collectors/aws/storagegateway/describeSMBFileShares.js new file mode 100644 index 0000000000..9300d3b714 --- /dev/null +++ b/collectors/aws/storagegateway/describeSMBFileShares.js @@ -0,0 +1,43 @@ +var AWS = require('aws-sdk'); +var async = require('async'); +var helpers = require(__dirname + '/../../../helpers/aws'); + +// DescribeSMBFileShares accepts at most 10 file share ARNs per request +var MAX_ARNS_PER_CALL = 10; + +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + var storagegateway = new AWS.StorageGateway(AWSConfig); + + var arns = collection.storagegateway.listFileShares[AWSConfig.region].data + .filter(function(share) { + return share.FileShareType === 'SMB' && share.FileShareARN; + }) + .map(function(share) { + return share.FileShareARN; + }); + + var chunks = []; + for (var i = 0; i < arns.length; i += MAX_ARNS_PER_CALL) { + chunks.push(arns.slice(i, i + MAX_ARNS_PER_CALL)); + } + + collection.storagegateway.describeSMBFileShares[AWSConfig.region].data = []; + + async.eachLimit(chunks, 5, function(chunk, cb){ + var params = { + FileShareARNList: chunk + }; + + helpers.makeCustomCollectorCall(storagegateway, 'describeSMBFileShares', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { + if (err) { + collection.storagegateway.describeSMBFileShares[AWSConfig.region].err = err; + } else if (data && data.SMBFileShareInfoList && data.SMBFileShareInfoList.length) { + collection.storagegateway.describeSMBFileShares[AWSConfig.region].data = + collection.storagegateway.describeSMBFileShares[AWSConfig.region].data.concat(data.SMBFileShareInfoList); + } + cb(); + }); + }, function(){ + callback(); + }); +}; diff --git a/collectors/aws/storagegateway/listFileShares.js b/collectors/aws/storagegateway/listFileShares.js new file mode 100644 index 0000000000..94b4eb2917 --- /dev/null +++ b/collectors/aws/storagegateway/listFileShares.js @@ -0,0 +1,45 @@ +var AWS = require('aws-sdk'); +var async = require('async'); +var helpers = require(__dirname + '/../../../helpers/aws'); + +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { + var storagegateway = new AWS.StorageGateway(AWSConfig); + + // Stored as a flat list rather than keyed by gateway so that the + // describe*FileShares postcalls can depend on it in the usual way + collection.storagegateway.listFileShares[AWSConfig.region].data = []; + + async.eachLimit(collection.storagegateway.listGateways[AWSConfig.region].data, 5, function(gateway, cb){ + var paginateCb = function(err, data) { + if (err) { + collection.storagegateway.listFileShares[AWSConfig.region].err = err; + return cb(); + } + + if (data && data.FileShareInfoList && data.FileShareInfoList.length) { + collection.storagegateway.listFileShares[AWSConfig.region].data = + collection.storagegateway.listFileShares[AWSConfig.region].data.concat(data.FileShareInfoList); + } + + // NextMarker is the token; it is sent back as Marker + if (data && data.NextMarker && data.NextMarker.length) { + return execute(data.NextMarker); + } + + cb(); + }; + + function execute(marker) { + var params = { + GatewayARN: gateway.GatewayARN + }; + if (marker) params.Marker = marker; + + helpers.makeCustomCollectorCall(storagegateway, 'listFileShares', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, paginateCb); + } + + execute(); + }, function(){ + callback(); + }); +}; diff --git a/collectors/aws/support/describeTrustedAdvisorCheckResult.js b/collectors/aws/support/describeTrustedAdvisorCheckResult.js index 76ed78cd1e..c535a9cab0 100644 --- a/collectors/aws/support/describeTrustedAdvisorCheckResult.js +++ b/collectors/aws/support/describeTrustedAdvisorCheckResult.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var support = new AWS.Support(AWSConfig); async.eachLimit(collection.support.describeTrustedAdvisorChecks[AWSConfig.region].data, 15, function(check, cb) { @@ -12,7 +12,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { checkId: check, }; - helpers.makeCustomCollectorCall(support, 'describeTrustedAdvisorCheckResult', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(support, 'describeTrustedAdvisorCheckResult', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.support.describeTrustedAdvisorChecks[AWSConfig.region][check].err = err; } diff --git a/collectors/aws/wafregional/listResourcesForWebACL.js b/collectors/aws/wafregional/listResourcesForWebACL.js index c1728c507d..9424b9ed34 100644 --- a/collectors/aws/wafregional/listResourcesForWebACL.js +++ b/collectors/aws/wafregional/listResourcesForWebACL.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var wafregional = new AWS.WAFRegional(AWSConfig); async.eachLimit(collection.wafregional.listWebACLs[AWSConfig.region].data, 15, function(dep, depCb){ async.eachLimit(['APPLICATION_LOAD_BALANCER', 'API_GATEWAY'], 1, function(thisCheck, tcCb){ @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { var filter = {}; filter['WebACLId'] = dep['WebACLId']; filter['ResourceType'] = thisCheck; - helpers.makeCustomCollectorCall(wafregional, 'listResourcesForWebACL', filter, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(wafregional, 'listResourcesForWebACL', filter, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection['wafregional']['listResourcesForWebACL'][AWSConfig.region][dep['WebACLId']].err = err; return tcCb(); diff --git a/collectors/aws/wafv2/getWebACL.js b/collectors/aws/wafv2/getWebACL.js index e2ed82a7c1..e58f56ff1d 100644 --- a/collectors/aws/wafv2/getWebACL.js +++ b/collectors/aws/wafv2/getWebACL.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var wafv2 = new AWS.WAFV2(AWSConfig); async.eachLimit(collection.wafv2.listWebACLs[AWSConfig.region].data, 15, function(acl, cb){ @@ -12,7 +12,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'Scope': 'REGIONAL' }; - helpers.makeCustomCollectorCall(wafv2, 'getWebACL', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(wafv2, 'getWebACL', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { collection.wafv2.getWebACL[AWSConfig.region][acl.ARN] = {}; if (err) { diff --git a/collectors/aws/wafv2/getWebACLForCognitoUserPool.js b/collectors/aws/wafv2/getWebACLForCognitoUserPool.js index 756032c4d8..caf80e738b 100644 --- a/collectors/aws/wafv2/getWebACLForCognitoUserPool.js +++ b/collectors/aws/wafv2/getWebACLForCognitoUserPool.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var wafv2 = new AWS.WAFV2(AWSConfig); var region = 'us-east-1'; @@ -20,7 +20,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { 'ResourceArn':`arn:${partition}:cognito-idp:${AWSConfig.region}:${collection.sts.getCallerIdentity[region].data}:userpool/${up.Id}` }; - helpers.makeCustomCollectorCall(wafv2, 'getWebACLForResource', params, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(wafv2, 'getWebACLForResource', params, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection.wafv2.getWebACLForCognitoUserPool[AWSConfig.region][up.Id].err = err; } diff --git a/collectors/aws/wafv2/listResourcesForWebACL.js b/collectors/aws/wafv2/listResourcesForWebACL.js index 711a45dbef..36c039cc89 100644 --- a/collectors/aws/wafv2/listResourcesForWebACL.js +++ b/collectors/aws/wafv2/listResourcesForWebACL.js @@ -2,7 +2,7 @@ var AWS = require('aws-sdk'); var async = require('async'); var helpers = require(__dirname + '/../../../helpers/aws'); -module.exports = function(AWSConfig, collection, retries, callback) { +module.exports = function(AWSConfig, collection, retries, settings, scanAWSConfig, callback) { var wafv2 = new AWS.WAFV2(AWSConfig); async.eachLimit(collection.wafv2.listWebACLs[AWSConfig.region].data, 15, function(dep, depCb){ async.eachLimit(['APPLICATION_LOAD_BALANCER', 'API_GATEWAY'], 1, function(thisCheck, tcCb){ @@ -11,7 +11,7 @@ module.exports = function(AWSConfig, collection, retries, callback) { var filter = {}; filter['WebACLArn'] = dep['ARN']; filter['ResourceType'] = thisCheck; - helpers.makeCustomCollectorCall(wafv2, 'listResourcesForWebACL', filter, retries, null, null, null, function(err, data) { + helpers.makeCustomCollectorCall(wafv2, 'listResourcesForWebACL', filter, retries, null, null, null, settings, scanAWSConfig, AWSConfig, function(err, data) { if (err) { collection['wafv2']['listResourcesForWebACL'][AWSConfig.region][dep['ARN']].err = err; return tcCb(); diff --git a/engine.spec.js b/engine.spec.js index 4faabcf89f..22b0cca6e4 100644 --- a/engine.spec.js +++ b/engine.spec.js @@ -2,6 +2,8 @@ var engine = require('./engine'); describe('engine', function () { + this.timeout(10000); + it('should run with no arguments', function () { // Although we don't pass in anything, this is enough to test // that our dependencies are actually installed. diff --git a/exports.spec.js b/exports.spec.js index 2bfbd7b192..425d079c94 100644 --- a/exports.spec.js +++ b/exports.spec.js @@ -13,6 +13,8 @@ function getParamNames(func) { } describe('exports', function () { + this.timeout(10000); + it('should use the proper format for each test', function () { for (var cloud in tests) { for (var test in tests[cloud]) { diff --git a/helpers/aws/api.js b/helpers/aws/api.js index 8f0dc0758c..82e750eb78 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -727,6 +727,12 @@ var calls = { paginate: 'NextToken' } }, + Amp: { + listWorkspaces: { + property: 'workspaces', + paginate: 'nextToken' + } + }, Appflow: { listFlows: { property: 'flows', @@ -864,6 +870,10 @@ var calls = { listDomains: { property: 'domains', paginate: 'nextToken' + }, + listRepositories: { + property: 'repositories', + paginate: 'nextToken' } }, CodeStar: { @@ -876,6 +886,16 @@ var calls = { listProjects: { property: 'projects', paginate: 'nextToken' + }, + listBuilds: { + property: 'ids', + paginate: 'nextToken' + } + }, + CodeCommit: { + listRepositories: { + property: 'repositories', + paginate: 'nextToken' } }, CognitoIdentityServiceProvider: { @@ -988,6 +1008,9 @@ var calls = { listNotificationChannels: { property: 'Channels', paginate: 'NextToken' + }, + describeServiceIntegration: { + property: 'ServiceIntegration' } }, DirectConnect: { @@ -1011,6 +1034,16 @@ var calls = { describeReplicationInstances: { property: 'ReplicationInstances', paginate: 'Marker' + }, + describeEndpoints: { + property: 'Endpoints', + paginate: 'Marker' + } + }, + Drs: { + describeReplicationConfigurationTemplates: { + property: 'items', + paginate: 'nextToken' } }, DocDB: { @@ -1027,6 +1060,10 @@ var calls = { } ] } + }, + describeDBClusterSnapshots: { + property: 'DBClusterSnapshots', + paginate: 'Marker' } }, DynamoDB: { @@ -1057,7 +1094,11 @@ var calls = { paginate: 'NextToken' }, describeAddresses: { - property: 'Addresses' + property: 'Addresses', + override: true + }, + describeRegions: { + property: 'Regions' }, describeVolumes: { property: 'Volumes' @@ -1209,6 +1250,10 @@ var calls = { describeReservedCacheNodes: { property: 'ReservedCacheNodes', paginate: 'Marker' + }, + describeSnapshots: { + property: 'Snapshots', + paginate: 'Marker' } }, ECR: { @@ -1274,11 +1319,6 @@ var calls = { property: 'TargetGroups', paginate: 'NextMarker', paginateReqProp: 'Marker' - }, - describeTargetHealth: { - property: 'TargetGroups', - paginate: 'NextMarker', - paginateReqProp: 'Marker' } }, EMR: { @@ -1329,12 +1369,20 @@ var calls = { listForecastExportJobs: { property: 'ForecastExportJobs', paginate: 'NextToken' + }, + listPredictors: { + property: 'Predictors', + paginate: 'NextToken' } }, FSx: { describeFileSystems: { property: 'FileSystems', paginate: 'NextToken' + }, + describeBackups: { + property: 'Backups', + paginate: 'NextToken' } }, FraudDetector: { @@ -1429,6 +1477,12 @@ var calls = { }, generateCredentialReport: { override: true + }, + listSAMLProviders: { + property: 'SAMLProviderList' + }, + listOpenIDConnectProviders: { + property: 'OpenIDConnectProviderList' } }, IoTSiteWise: { @@ -1457,6 +1511,19 @@ var calls = { paginate: 'NextToken', } }, + Macie2: { + getAutomatedDiscoveryConfiguration: {}, + }, + M2: { + listApplications: { + property: 'applications', + paginate: 'nextToken' + }, + listEnvironments: { + property: 'environments', + paginate: 'nextToken' + } + }, Kendra: { listIndices: { property: 'IndexConfigurationSummaryItems', @@ -1532,6 +1599,10 @@ var calls = { describeClusters: { property:'Clusters', paginate:'NextToken' + }, + describeSnapshots: { + property: 'Snapshots', + paginate: 'NextToken' } }, ManagedBlockchain: { @@ -1560,6 +1631,10 @@ var calls = { describeDBInstances: { property: 'DBInstances', paginate: 'Marker' + }, + describeDBClusterSnapshots: { + property: 'DBClusterSnapshots', + paginate: 'Marker' } }, Organizations: { @@ -1580,6 +1655,12 @@ var calls = { paginate: 'nextToken' } }, + Personalize: { + listSolutions: { + property: 'solutions', + paginate: 'nextToken' + } + }, RDS: { describeDBInstances: { property: 'DBInstances', @@ -1751,6 +1832,26 @@ var calls = { State: 'Active' } }, + listDocuments: { + property: 'DocumentIdentifiers', + paginate: 'NextToken', + params: { + Filters: [ + { + Key: 'Owner', + Values: [ + 'Self' + ] + } + ] + } + }, + }, + StorageGateway: { + listGateways: { + property: 'Gateways', + paginate: 'Marker' + } }, STS: { getCallerIdentity: { @@ -1788,6 +1889,20 @@ var calls = { listTextTranslationJobs: { property: 'TextTranslationJobPropertiesList', paginate: 'NextToken' + }, + listTerminologies: { + property: 'TerminologyPropertiesList', + paginate: 'NextToken' + } + }, + TranscribeService: { + listTranscriptionJobs: { + property: 'TranscriptionJobSummaries', + paginate: 'NextToken' + }, + listMedicalTranscriptionJobs: { + property: 'MedicalTranscriptionJobSummaries', + paginate: 'NextToken' } }, VoiceID: { @@ -1887,6 +2002,11 @@ var postcalls = [ filterKey: 'domain', filterValue: 'name' }, + getRepositoryPermissionsPolicy: { + reliesOnService: 'codeartifact', + reliesOnCall: 'listRepositories', + override: true + }, sendIntegration: serviceMap['CodeArtifact'] }, ComputeOptimizer: { @@ -1902,8 +2022,69 @@ var postcalls = [ sendIntegration: serviceMap['Kinesis Video Streams'] }, SSM : { + describeDocumentPermission: { + reliesOnService: 'ssm', + reliesOnCall: 'listDocuments', + override: true + }, sendIntegration: serviceMap['SSM'] }, + StorageGateway: { + // Must stay first: the describe*FileShares calls below read its output + listFileShares: { + reliesOnService: 'storagegateway', + reliesOnCall: 'listGateways', + override: true + }, + describeNFSFileShares: { + reliesOnService: 'storagegateway', + reliesOnCall: 'listFileShares', + override: true + }, + describeSMBFileShares: { + reliesOnService: 'storagegateway', + reliesOnCall: 'listFileShares', + override: true + } + }, + CodeCommit: { + getRepository: { + reliesOnService: 'codecommit', + reliesOnCall: 'listRepositories', + filterKey: 'repositoryName', + filterValue: 'repositoryName' + } + }, + Personalize: { + describeSolution: { + reliesOnService: 'personalize', + reliesOnCall: 'listSolutions', + filterKey: 'solutionArn', + filterValue: 'solutionArn' + } + }, + M2: { + getApplication: { + reliesOnService: 'm2', + reliesOnCall: 'listApplications', + filterKey: 'applicationId', + filterValue: 'applicationId' + }, + getEnvironment: { + reliesOnService: 'm2', + reliesOnCall: 'listEnvironments', + filterKey: 'environmentId', + filterValue: 'environmentId' + } + }, + Amp: { + describeWorkspace: { + reliesOnService: 'amp', + reliesOnCall: 'listWorkspaces', + filterKey: 'workspaceId', + filterValue: 'workspaceId' + } + }, Organizations:{ sendIntegration: serviceMap['Organizations'] }, @@ -2247,6 +2428,11 @@ var postcalls = [ filterKey: 'resourceArn', filterValue: 'arn' }, + batchGetBuilds: { + reliesOnService: 'codebuild', + reliesOnCall: 'listBuilds', + override: true + }, sendIntegration: serviceMap['CodeBuild'] }, CodePipeline: { @@ -2646,6 +2832,12 @@ var postcalls = [ filterKey: 'DatasetArn', filterValue: 'DatasetArn' }, + describePredictor: { + reliesOnService: 'forecastservice', + reliesOnCall: 'listPredictors', + filterKey: 'PredictorArn', + filterValue: 'PredictorArn' + }, sendIntegration: serviceMap['AI & ML'][2] }, Glacier: { @@ -2664,6 +2856,18 @@ var postcalls = [ filterKey: 'GroupName', filterValue: 'GroupName' }, + getSAMLProvider: { + reliesOnService: 'iam', + reliesOnCall: 'listSAMLProviders', + filterKey: 'SAMLProviderArn', + filterValue: 'Arn' + }, + getOpenIDConnectProvider: { + reliesOnService: 'iam', + reliesOnCall: 'listOpenIDConnectProviders', + filterKey: 'OpenIDConnectProviderArn', + filterValue: 'Arn' + }, listAttachedUserPolicies: { reliesOnService: 'iam', reliesOnCall: 'listUsers', diff --git a/helpers/aws/api_multipart.js b/helpers/aws/api_multipart.js index b4576bf397..dfe06e3bca 100644 --- a/helpers/aws/api_multipart.js +++ b/helpers/aws/api_multipart.js @@ -66,6 +66,12 @@ var calls = [ paginate: 'NextToken' } }, + Amp: { + listWorkspaces: { + property: 'workspaces', + paginate: 'nextToken' + } + }, Appflow: { listFlows: { property: 'flows', @@ -199,6 +205,10 @@ var calls = [ listDomains: { property: 'domains', paginate: 'nextToken' + }, + listRepositories: { + property: 'repositories', + paginate: 'nextToken' } }, CodeStar: { @@ -211,6 +221,16 @@ var calls = [ listProjects: { property: 'projects', paginate: 'nextToken' + }, + listBuilds: { + property: 'ids', + paginate: 'nextToken' + } + }, + CodeCommit: { + listRepositories: { + property: 'repositories', + paginate: 'nextToken' } }, CodePipeline: { @@ -304,6 +324,9 @@ var calls = [ listNotificationChannels: { property: 'Channels', paginate: 'NextToken' + }, + describeServiceIntegration: { + property: 'ServiceIntegration' } }, DirectConnect: { @@ -329,6 +352,16 @@ var calls = [ describeReplicationInstances: { property: 'ReplicationInstances', paginate: 'Marker' + }, + describeEndpoints: { + property: 'Endpoints', + paginate: 'Marker' + } + }, + Drs: { + describeReplicationConfigurationTemplates: { + property: 'items', + paginate: 'nextToken' } }, DocDB: { @@ -345,6 +378,10 @@ var calls = [ } ] } + }, + describeDBClusterSnapshots: { + property: 'DBClusterSnapshots', + paginate: 'Marker' } }, DynamoDB: { @@ -375,7 +412,11 @@ var calls = [ paginate: 'NextToken' }, describeAddresses: { - property: 'Addresses' + property: 'Addresses', + override: true + }, + describeRegions: { + property: 'Regions' }, describeVolumes: { property: 'Volumes' @@ -527,6 +568,10 @@ var calls = [ describeReservedCacheNodes: { property: 'ReservedCacheNodes', paginate: 'Marker' + }, + describeSnapshots: { + property: 'Snapshots', + paginate: 'Marker' } }, ECR: { @@ -623,12 +668,20 @@ var calls = [ listForecastExportJobs: { property: 'ForecastExportJobs', paginate: 'NextToken' + }, + listPredictors: { + property: 'Predictors', + paginate: 'NextToken' } }, FSx: { describeFileSystems: { property: 'FileSystems', paginate: 'NextToken' + }, + describeBackups: { + property: 'Backups', + paginate: 'NextToken' } }, FraudDetector: { @@ -703,6 +756,12 @@ var calls = [ }, generateCredentialReport: { override: true + }, + listSAMLProviders: { + property: 'SAMLProviderList' + }, + listOpenIDConnectProviders: { + property: 'OpenIDConnectProviderList' } }, IoTSiteWise: { @@ -806,6 +865,20 @@ var calls = [ describeClusters: { property:'Clusters', paginate:'NextToken' + }, + describeSnapshots: { + property: 'Snapshots', + paginate: 'NextToken' + } + }, + M2: { + listApplications: { + property: 'applications', + paginate: 'nextToken' + }, + listEnvironments: { + property: 'environments', + paginate: 'nextToken' } }, ManagedBlockchain: { @@ -834,6 +907,10 @@ var calls = [ describeDBInstances: { property: 'DBInstances', paginate: 'Marker' + }, + describeDBClusterSnapshots: { + property: 'DBClusterSnapshots', + paginate: 'Marker' } }, Organizations: { @@ -854,6 +931,12 @@ var calls = [ paginate: 'nextToken' } }, + Personalize: { + listSolutions: { + property: 'solutions', + paginate: 'nextToken' + } + }, RDS: { describeDBInstances: { property: 'DBInstances', @@ -1014,6 +1097,26 @@ var calls = [ State: 'Active' } }, + listDocuments: { + property: 'DocumentIdentifiers', + paginate: 'NextToken', + params: { + Filters: [ + { + Key: 'Owner', + Values: [ + 'Self' + ] + } + ] + } + }, + }, + StorageGateway: { + listGateways: { + property: 'Gateways', + paginate: 'Marker' + } }, STS: { getCallerIdentity: { @@ -1066,6 +1169,20 @@ var calls = [ listTextTranslationJobs: { property: 'TextTranslationJobPropertiesList', paginate: 'NextToken' + }, + listTerminologies: { + property: 'TerminologyPropertiesList', + paginate: 'NextToken' + } + }, + TranscribeService: { + listTranscriptionJobs: { + property: 'TranscriptionJobSummaries', + paginate: 'NextToken' + }, + listMedicalTranscriptionJobs: { + property: 'MedicalTranscriptionJobSummaries', + paginate: 'NextToken' } }, VoiceID: { @@ -1136,11 +1253,6 @@ var calls = [ property: 'TargetGroups', paginate: 'NextMarker', paginateReqProp: 'Marker' - }, - describeTargetHealth: { - property: 'TargetGroups', - paginate: 'NextMarker', - paginateReqProp: 'Marker' } }, Imagebuilder: { @@ -1386,6 +1498,26 @@ var postcalls = [ reliesOnService: 'codebuild', reliesOnCall: 'listProjects', override: true + }, + batchGetBuilds: { + reliesOnService: 'codebuild', + reliesOnCall: 'listBuilds', + override: true + } + }, + CodeArtifact: { + getRepositoryPermissionsPolicy: { + reliesOnService: 'codeartifact', + reliesOnCall: 'listRepositories', + override: true + } + }, + CodeCommit: { + getRepository: { + reliesOnService: 'codecommit', + reliesOnCall: 'listRepositories', + filterKey: 'repositoryName', + filterValue: 'repositoryName' } }, CodePipeline: { @@ -1706,6 +1838,12 @@ var postcalls = [ reliesOnCall: 'listDatasets', filterKey: 'DatasetArn', filterValue: 'DatasetArn' + }, + describePredictor: { + reliesOnService: 'forecastservice', + reliesOnCall: 'listPredictors', + filterKey: 'PredictorArn', + filterValue: 'PredictorArn' } }, Glacier: { @@ -1869,6 +2007,20 @@ var postcalls = [ filterValue: 'GroupName', rateLimit: 200 }, + getSAMLProvider: { + reliesOnService: 'iam', + reliesOnCall: 'listSAMLProviders', + filterKey: 'SAMLProviderArn', + filterValue: 'Arn', + rateLimit: 200 + }, + getOpenIDConnectProvider: { + reliesOnService: 'iam', + reliesOnCall: 'listOpenIDConnectProviders', + filterKey: 'OpenIDConnectProviderArn', + filterValue: 'Arn', + rateLimit: 200 + }, listAttachedUserPolicies: { reliesOnService: 'iam', reliesOnCall: 'listUsers', @@ -2253,6 +2405,61 @@ var postcalls = [ enabled: true } }, + SSM: { + describeDocumentPermission: { + reliesOnService: 'ssm', + reliesOnCall: 'listDocuments', + override: true + } + }, + StorageGateway: { + // Must stay first: the describe*FileShares calls below read its output + listFileShares: { + reliesOnService: 'storagegateway', + reliesOnCall: 'listGateways', + override: true + }, + describeNFSFileShares: { + reliesOnService: 'storagegateway', + reliesOnCall: 'listFileShares', + override: true + }, + describeSMBFileShares: { + reliesOnService: 'storagegateway', + reliesOnCall: 'listFileShares', + override: true + } + }, + Personalize: { + describeSolution: { + reliesOnService: 'personalize', + reliesOnCall: 'listSolutions', + filterKey: 'solutionArn', + filterValue: 'solutionArn' + } + }, + M2: { + getApplication: { + reliesOnService: 'm2', + reliesOnCall: 'listApplications', + filterKey: 'applicationId', + filterValue: 'applicationId' + }, + getEnvironment: { + reliesOnService: 'm2', + reliesOnCall: 'listEnvironments', + filterKey: 'environmentId', + filterValue: 'environmentId' + } + }, + Amp: { + describeWorkspace: { + reliesOnService: 'amp', + reliesOnCall: 'listWorkspaces', + filterKey: 'workspaceId', + filterValue: 'workspaceId' + } + }, }, { IAM: { diff --git a/helpers/aws/functions.js b/helpers/aws/functions.js index 4824e94f8e..2ae5d8f480 100644 --- a/helpers/aws/functions.js +++ b/helpers/aws/functions.js @@ -1024,7 +1024,32 @@ var isRateError = function(err) { return isError; }; -function makeCustomCollectorCall(executor, callKey, params, retries, apiRetryAttempts=2, apiRetryCap=1000, apiRetryBackoff=500, callback) { +function makeCustomCollectorCall(executor, callKey, params, retries, apiRetryAttempts, apiRetryCap, apiRetryBackoff, settings, scanAWSConfig, localAWSConfig, callback) { + if (apiRetryAttempts == null) apiRetryAttempts = 2; + if (apiRetryCap == null) apiRetryCap = 1000; + if (apiRetryBackoff == null) apiRetryBackoff = 500; + + var execRef = { current: executor }; + function runOnce(cb) { + execRef.current[callKey](params, function(err, data) { + if (!settings || !scanAWSConfig || !localAWSConfig) { + return cb(err, data); + } + refreshCredentialsIfTokenExpired(err, settings, scanAWSConfig, localAWSConfig, function(refreshErr, newCreds) { + if (!newCreds) { + if (refreshErr) console.log('[WARN] Token refresh failed'); + return cb(err, data); + } + try { + execRef.current = new execRef.current.constructor(localAWSConfig); + } catch (e) { + return cb(err, data); + } + execRef.current[callKey](params, cb); + }); + }); + } + async.retry({ times: apiRetryAttempts, interval: function(retryCount){ @@ -1042,14 +1067,49 @@ function makeCustomCollectorCall(executor, callKey, params, retries, apiRetryAtt return isRateError(err); } }, function(cb) { - executor[callKey](params, function(err, data) { - return cb(err, data); + runOnce(cb); + }, function(err, result) { + callback(err, result); + }); +} + +function buildV3ClientConfig(AWSConfig) { + return { + region: AWSConfig.region, + credentials: AWSConfig + }; +} + +function makeCustomCollectorCallV3(client, Command, params, retries, apiRetryAttempts=2, apiRetryCap=1000, apiRetryBackoff=500, callback) { + async.retry({ + times: apiRetryAttempts, + interval: function(retryCount){ + let retryExponential = 3; + let retryLeveler = 3; + let timestamp = parseInt(((new Date()).getTime()).toString().slice(-1)); + let retry_temp = Math.min(apiRetryCap, (apiRetryBackoff * (retryExponential + timestamp) ** retryCount)); + let retry_seconds = Math.round(retry_temp/retryLeveler + Math.random(0, retry_temp) * 5000); + + console.log(`Trying ${Command.name} again in: ${retry_seconds/1000} seconds`); + retries.push({seconds: Math.round(retry_seconds/1000)}); + return retry_seconds; + }, + errorFilter: function(err) { + return isRateError(err); + } + }, function(cb) { + var command = new Command(params); + client.send(command).then(function(data) { + return cb(null, data); + }).catch(function(err) { + return cb(err, null); }); }, function(err, result) { callback(err, result); }); } + var debugApiCalls = function(call, service, debugMode, finished) { if (!debugMode) return; finished ? console.log(`[INFO] ${service}:${call} returned`) : console.log(`[INFO] ${service}:${call} invoked`); @@ -1119,6 +1179,68 @@ var collectRateError = function(err, rateError) { return isError; }; + +function isTokenExpiredError(err) { + if (!err) return false; + var code = (err.code || err.name || '').toString(); + var msg = (err.message || '').toString().toLowerCase(); + if (code === 'ExpiredToken' || code === 'RequestExpired' || code === 'ExpiredTokenException') return true; + return msg.indexOf('the security token included in the request is expired') > -1 || + msg.indexOf('the security token included in the request is invalid') > -1 || + msg.indexOf('the provided token has expired') > -1 || + msg.indexOf('the security token isn\'t valid') > -1 || + msg.indexOf('the security token is not valid') > -1 || + msg.indexOf('security token has expired') > -1 || + msg.indexOf('security token is expired') > -1 || + msg.indexOf('token has expired') > -1 || + msg.indexOf('token is invalid') > -1; +} +function assumeRoleForRefresh(roleArn, externalId, callback) { + if (!roleArn || !externalId) return callback(new Error('role_arn and external_id required to refresh credentials')); + var sts = new AWS.STS(); + sts.assumeRole({ + RoleArn: roleArn, + RoleSessionName: 'cloudsploit_scan', + DurationSeconds: 1800, + ExternalId: externalId + }, function(err, data) { + if (err || !data || !data.Credentials) return callback(err || new Error('No credentials returned')); + callback(null, { + accessKeyId: data.Credentials.AccessKeyId, + secretAccessKey: data.Credentials.SecretAccessKey, + sessionToken: data.Credentials.SessionToken + }); + }); +} + +function refreshCredentialsIfTokenExpired(err, settings, AWSConfig, LocalAWSConfig, cb) { + if (!err || !isTokenExpiredError(err) || !settings.role_arn || !settings.external_id) { + return cb(null, null); + } + if (settings._lastTokenRefresh && (Date.now() - settings._lastTokenRefresh < 60000)) { + console.log(`[INFO] Assigning new creds ${settings.role_arn} : ${Date.now()}`); + LocalAWSConfig.accessKeyId = AWSConfig.accessKeyId; + LocalAWSConfig.secretAccessKey = AWSConfig.secretAccessKey; + LocalAWSConfig.sessionToken = AWSConfig.sessionToken; + return cb(null, AWSConfig); + } + return assumeRoleForRefresh(settings.role_arn, settings.external_id, function(refreshErr, newCreds) { + if (refreshErr) { + console.log('[WARN] Token refresh failed'); + return cb(refreshErr, null); + } + settings._lastTokenRefresh = Date.now(); + console.log(`[INFO] Refresh succeeded, got new creds for role: ${settings.role_arn} : ${settings._lastTokenRefresh}`); + AWSConfig.accessKeyId = newCreds.accessKeyId; + AWSConfig.secretAccessKey = newCreds.secretAccessKey; + AWSConfig.sessionToken = newCreds.sessionToken; + LocalAWSConfig.accessKeyId = newCreds.accessKeyId; + LocalAWSConfig.secretAccessKey = newCreds.secretAccessKey; + LocalAWSConfig.sessionToken = newCreds.sessionToken; + return cb(null, newCreds); + }); +} + function processFieldSelectors(fieldSelectors,buckets ,startsWithBuckets,notEndsWithBuckets,endsWithBuckets, notStartsWithBuckets) { fieldSelectors.forEach(f => { if (f.Field === 'resources.ARN') { @@ -1644,9 +1766,14 @@ module.exports = { getPrivateSubnets: getPrivateSubnets, getSubnetRTMap: getSubnetRTMap, makeCustomCollectorCall: makeCustomCollectorCall, + makeCustomCollectorCallV3: makeCustomCollectorCallV3, + buildV3ClientConfig: buildV3ClientConfig, debugApiCalls: debugApiCalls, logError: logError, collectRateError: collectRateError, + isTokenExpiredError: isTokenExpiredError, + assumeRoleForRefresh: assumeRoleForRefresh, + refreshCredentialsIfTokenExpired: refreshCredentialsIfTokenExpired, checkTags: checkTags, checkConditions: checkConditions, processFieldSelectors: processFieldSelectors, diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index a7bf758558..3d7465b0ce 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -123,6 +123,7 @@ module.exports = { waf: ['us-east-1'], organizations: ['us-east-1'], guardduty: [...regions, ...newRegionsUpdate], + macie2: [...regions, ...newRegionsUpdate], workspaces: ['us-east-1', 'us-west-2', 'ca-central-1', 'sa-east-1', 'ap-south-1', 'eu-west-1', 'eu-central-1', 'eu-west-2', 'ap-southeast-1', 'ap-northeast-1', 'ap-southeast-2', 'ap-northeast-2', 'af-south-1', 'il-central-1'], @@ -211,6 +212,22 @@ module.exports = { appconfig: [...regions, ...newRegionsUpdate], opensearch: [...regions, ...newRegionsUpdate], opensearchserverless: ['us-east-2', 'us-east-1', 'us-west-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', - 'eu-central-1', 'eu-west-1'] + 'eu-central-1', 'eu-west-1'], + storagegateway: [...regions, ...newRegionsUpdate], + codecommit: regions, + personalize: ['us-east-1', 'us-east-2', 'us-west-2', 'ap-northeast-1', 'ap-northeast-2', 'ap-south-1', + 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2'], + drs: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'af-south-1', 'ap-east-1', 'ap-south-1', + 'ap-northeast-1', 'ap-northeast-2', 'ap-northeast-3', 'ap-southeast-1', 'ap-southeast-2', 'ap-southeast-3', + 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'eu-south-1', + 'me-south-1', 'me-central-1', 'sa-east-1'], + m2: ['us-east-1', 'us-east-2', 'us-west-2', 'ap-northeast-1', 'ap-southeast-1', 'ap-southeast-2', + 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'sa-east-1'], + transcribeservice: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'af-south-1', 'ap-east-1', 'ap-south-1', + 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'eu-central-1', + 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'me-south-1', 'sa-east-1'], + amp: ['us-east-1', 'us-east-2', 'us-west-2', 'ap-northeast-1', 'ap-northeast-2', 'ap-south-1', + 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'eu-central-1', 'eu-north-1', 'eu-west-1', + 'eu-west-2', 'eu-west-3', 'sa-east-1'] }; diff --git a/helpers/aws/regions_china.js b/helpers/aws/regions_china.js index 5a7e38a712..5b0a06eaa7 100644 --- a/helpers/aws/regions_china.js +++ b/helpers/aws/regions_china.js @@ -75,6 +75,7 @@ module.exports = { directoryservice: [], organizations: ['cn-north-1'], guardduty: [], + macie2: [], wafregional: [], wafv2: [], waf: regions, @@ -124,5 +125,13 @@ module.exports = { appconfig: regions, opensearch:regions, opensearchserverless: regions, - securityhub: regions + securityhub: regions, + storagegateway: regions, + // Not offered in the China partition + codecommit: [], + personalize: [], + drs: [], + m2: [], + transcribeservice: [], + amp: [] }; diff --git a/helpers/aws/regions_gov.js b/helpers/aws/regions_gov.js index df2b454615..9da91bd928 100644 --- a/helpers/aws/regions_gov.js +++ b/helpers/aws/regions_gov.js @@ -77,6 +77,7 @@ module.exports = { directoryservice: [], organizations: regions, guardduty: regions, + macie2: regions, wafregional: [], wafv2: regions, waf: regions, @@ -124,5 +125,13 @@ module.exports = { appconfig: regions, opensearch:regions, opensearchserverless: regions, - securityhub: regions + securityhub: regions, + storagegateway: regions, + codecommit: regions, + transcribeservice: regions, + drs: regions, + // Not offered in GovCloud + personalize: [], + m2: [], + amp: [] }; diff --git a/helpers/aws/regions_gov_fedramp_east_1.js b/helpers/aws/regions_gov_fedramp_east_1.js index 84ca9e0673..4b471831f4 100644 --- a/helpers/aws/regions_gov_fedramp_east_1.js +++ b/helpers/aws/regions_gov_fedramp_east_1.js @@ -73,6 +73,7 @@ module.exports = { directoryservice: [], organizations: regions, guardduty: regions, + macie2: regions, wafregional: [], wafv2: regions, waf: regions, @@ -119,5 +120,13 @@ module.exports = { computeoptimizer: regions, appconfig: regions, opensearch:regions, - opensearchserverless: regions + opensearchserverless: regions, + storagegateway: regions, + codecommit: regions, + transcribeservice: regions, + drs: regions, + // Not offered in GovCloud + personalize: [], + m2: [], + amp: [] }; diff --git a/helpers/aws/regions_gov_fedramp_west_1.js b/helpers/aws/regions_gov_fedramp_west_1.js index b4793ef189..6075cb9b5d 100644 --- a/helpers/aws/regions_gov_fedramp_west_1.js +++ b/helpers/aws/regions_gov_fedramp_west_1.js @@ -73,6 +73,7 @@ module.exports = { directoryservice: [], organizations: regions, guardduty: regions, + macie2: regions, wafregional: [], wafv2: regions, waf: regions, @@ -119,5 +120,13 @@ module.exports = { computeoptimizer: regions, appconfig: regions, opensearch:regions, - opensearchserverless: regions + opensearchserverless: regions, + storagegateway: regions, + codecommit: regions, + transcribeservice: regions, + drs: regions, + // Not offered in GovCloud + personalize: [], + m2: [], + amp: [] }; diff --git a/helpers/aws/resources.js b/helpers/aws/resources.js index e853f19aef..563328db58 100644 --- a/helpers/aws/resources.js +++ b/helpers/aws/resources.js @@ -84,10 +84,18 @@ module.exports = { }, codeartifact: { listDomains: 'arn', + listRepositories: 'arn', + getRepositoryPermissionsPolicy: '' }, codebuild: { listProjects: '', batchGetProjects: 'arn', + listBuilds: '', + batchGetBuilds: 'arn', + }, + codecommit: { + listRepositories: 'repositoryName', + getRepository: 'repositoryMetadata.Arn' }, codepipeline: { listPipelines: 'arn:aws:codepipeline:{region}:{cloudAccount}:{name}', @@ -135,12 +143,18 @@ module.exports = { }, dms: { describeReplicationInstances: 'ReplicationInstanceArn', + describeEndpoints: 'EndpointArn' }, docdb: { - describeDBClusters: 'DBClusterArn' + describeDBClusters: 'DBClusterArn', + describeDBClusterSnapshots: 'DBClusterSnapshotArn' + }, + drs: { + describeReplicationConfigurationTemplates: 'arn' }, devopsguru: { - listNotificationChannels: 'Id' + listNotificationChannels: 'Id', + describeServiceIntegration: '' }, dax: { describeClusters: 'ClusterArn' @@ -204,6 +218,7 @@ module.exports = { describeCacheClusters: 'ARN', describeReplicationGroups: 'ReplicationGroupId', describeReservedCacheNodes: 'ReservationARN', + describeSnapshots: 'ARN', }, elb: { describeLoadBalancerAttributes: '', @@ -251,14 +266,17 @@ module.exports = { forecastservice: { listForecastExportJobs: 'ForecastExportJobArn', listDatasets: 'DatasetArn', - describeDataset: 'DatasetArn' + describeDataset: 'DatasetArn', + listPredictors: 'PredictorArn', + describePredictor: 'PredictorArn' }, frauddetector: { getDetectors: 'arn', getKMSEncryptionKey: 'kmsEncryptionKeyArn', }, fsx: { - describeFileSystems: 'ResourceARN' + describeFileSystems: 'ResourceARN', + describeBackups: 'ResourceARN' }, glue: { getDataCatalogEncryptionSettings: '', @@ -306,8 +324,12 @@ module.exports = { listGroupsForUser: '', getGroupPolicy: '', getRolePolicy: '', - getPolicy: 'Policy.Arn', - getUser: 'Arn' + getPolicy: 'Policy.Arn', + getUser: 'Arn', + listSAMLProviders: 'Arn', + getSAMLProvider: '', + listOpenIDConnectProviders: 'Arn', + getOpenIDConnectProvider: '' }, imagebuilder: { listContainerRecipes: 'arn', @@ -374,6 +396,9 @@ module.exports = { listModels: 'ModelArn', describeModel: 'ModelDescription.ModelArn' }, + macie2: { + getAutomatedDiscoveryConfiguration: '', + }, managedblockchain: { listMembers: 'Arn', listNetworks: 'Arn', @@ -381,6 +406,13 @@ module.exports = { }, memorydb: { describeClusters: 'ARN', + describeSnapshots: 'ARN', + }, + m2: { + listApplications: 'applicationArn', + getApplication: 'applicationArn', + listEnvironments: 'environmentArn', + getEnvironment: 'environmentArn' }, mq: { listBrokers: 'BrokerArn', @@ -395,7 +427,7 @@ module.exports = { }, neptune: { describeDBClusters: 'DBClusterArn', - + describeDBClusterSnapshots: 'DBClusterSnapshotArn' }, organizations: { describeOrganization: 'MasterAccountArn', @@ -471,7 +503,9 @@ module.exports = { describeParameters: 'Name', listAssociations: 'AssociationId', getServiceSetting: 'ARN', - describeSessions: 'arn:aws:ec2:{region}:{cloudAccount}:/instance/{Target}' + describeSessions: 'arn:aws:ec2:{region}:{cloudAccount}:/instance/{Target}', + listDocuments: 'Name', + describeDocumentPermission: '' }, sagemaker: { describeNotebookInstance: 'NotebookInstanceArn', @@ -490,7 +524,26 @@ module.exports = { listDatabases: 'Arn', }, translate: { - listTextTranslationJobs: 'arn:aws:translate:{region}:{cloudAccount}:job/{JobName}' + listTextTranslationJobs: 'arn:aws:translate:{region}:{cloudAccount}:job/{JobName}', + listTerminologies: 'Arn' + }, + transcribeservice: { + listTranscriptionJobs: 'TranscriptionJobName', + listMedicalTranscriptionJobs: 'MedicalTranscriptionJobName' + }, + storagegateway: { + listGateways: 'GatewayARN', + listFileShares: 'FileShareARN', + describeNFSFileShares: 'FileShareARN', + describeSMBFileShares: 'FileShareARN' + }, + personalize: { + listSolutions: 'solutionArn', + describeSolution: 'solution.solutionArn' + }, + amp: { + listWorkspaces: 'arn', + describeWorkspace: 'workspace.arn' }, transfer: { listServers: 'Arn' diff --git a/helpers/azure/api.js b/helpers/azure/api.js index c55ad527fd..4682c1e2d1 100644 --- a/helpers/azure/api.js +++ b/helpers/azure/api.js @@ -199,12 +199,12 @@ var serviceMap = { }, 'Virtual Machines': { - enabled: true, isSingleSource: true, InvAsset: 'vm_scaleset', InvService: 'virtualmachines', - InvResourceCategory: 'cloud_resources', InvResourceType: 'VM_ScaleSet', BridgeServiceName: 'virtualmachinescalesets', - BridgePluginCategoryName: 'Virtual Machines', BridgeProvider: 'Azure', BridgeCall: 'listAll', - BridgeArnIdentifier: '', BridgeIdTemplate: '', BridgeResourceType: 'virtualMachineScaleSets', + enabled: true, isSingleSource: true, InvAsset: 'vm_scaleset_vm', InvService: 'virtualmachines', + InvResourceCategory: 'cloud_resources', InvResourceType: 'VM_ScaleSet_VM', BridgeServiceName: 'virtualmachinescalesetvms', + BridgePluginCategoryName: 'Virtual Machines', BridgeProvider: 'Azure', BridgeCall: 'list', + BridgeArnIdentifier: '', BridgeIdTemplate: '', BridgeResourceType: 'virtualMachines', BridgeResourceNameIdentifier: 'name', BridgeExecutionService: 'Virtual Machines', - BridgeCollectionService: 'virtualmachinescalesets', DataIdentifier: 'data', + BridgeCollectionService: 'virtualmachinescalesetvms', DataIdentifier: 'data', }, 'Event Grid': { @@ -545,8 +545,7 @@ var calls = { virtualMachineScaleSets: { listAll: { url: 'https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Compute/virtualMachineScaleSets?api-version=2023-07-01' - }, - sendIntegration: serviceMap['Virtual Machines'] + } }, bastionHosts: { listAll: { @@ -909,8 +908,9 @@ var postcalls = { list: { reliesOnPath: 'virtualMachineScaleSets.listAll', properties: ['id'], - url: 'https://management.azure.com/{id}/virtualMachines?api-version=2020-12-01' - } + url: 'https://management.azure.com/{id}/virtualMachines?api-version=2025-11-01' + }, + sendIntegration: serviceMap['Virtual Machines'] }, virtualNetworkGateways: { listByResourceGroup: { diff --git a/helpers/azure/functions.js b/helpers/azure/functions.js index 988611788b..9ad724b644 100644 --- a/helpers/azure/functions.js +++ b/helpers/azure/functions.js @@ -35,7 +35,7 @@ function addResult(results, status, message, region, resource, custom) { overrideMsg = 'Aqua does not have permission to list storage account keys. For help fixing this error, see: https://bit.ly/2AhlVP0'; skipStatusChange = true; } else if (message.indexOf('list permission on key vault') > -1) { - overrideMsg = 'Aqua does not have permission to list objects in this Key Vault. For help fixing this error, see: https://bit.ly/3cbpFyL'; + overrideMsg = 'Aqua does not have permission to list objects in this Key Vault. For help fixing this error, see: https://docs.aquasec.com/saas/cspm/plugins/troubleshooting-azure-key-vault-permission-errors/'; skipStatusChange = true; } diff --git a/helpers/google/index.js b/helpers/google/index.js index f8e2837e8d..32679d6f71 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -414,6 +414,7 @@ var isQuotaError = function(err) { function makeApiCall(client, originalUrl, callCb, nextToken, config) { let retries = []; var apiRetryAttempts = 3; + var quotaRetryAttempts = 6; // only for quota/access limit errors var apiRetryBackoff = 500; var apiRetryCap = 1000; var quotaRetryDelay = 60000; // 60 seconds (1 minute) for quota limit errors @@ -430,9 +431,10 @@ function makeApiCall(client, originalUrl, callCb, nextToken, config) { // Track the last error to determine retry strategy let lastError = null; + let failureCount = 0; async.retry({ - times: apiRetryAttempts, + times: Math.max(apiRetryAttempts, quotaRetryAttempts) + 1, interval: function(retryCount){ // Check if last error was a quota error - apply 1 minute delay for all quota errors if (lastError && isQuotaError(lastError)) { @@ -454,8 +456,9 @@ function makeApiCall(client, originalUrl, callCb, nextToken, config) { }, errorFilter: function(err) { lastError = err; - // Retry on rate errors or quota errors (for all API calls) - return isRateError(err) || isQuotaError(err); + failureCount++; + var maxRetries = isQuotaError(err) ? quotaRetryAttempts : (isRateError(err) ? apiRetryAttempts : 0); + return failureCount <= maxRetries; } }, function(cb) { diff --git a/helpers/oracle/regions.js b/helpers/oracle/regions.js index d36ef93060..8af1defa8b 100644 --- a/helpers/oracle/regions.js +++ b/helpers/oracle/regions.js @@ -23,14 +23,28 @@ var regions = [ 'me-jeddah-1', 'ap-chuncheon-1', 'me-dubai-1', + 'me-abudhabi-1', 'uk-cardiff-1', 'us-sanjose-1', 'mx-queretaro-1', 'eu-marseille-1', 'eu-milan-1', 'ap-singapore-1', + 'ap-singapore-2', 'af-johannesburg-1', - 'eu-stockholm-1' + 'af-casablanca-1', + 'eu-stockholm-1', + 'eu-paris-1', + 'eu-madrid-1', + 'eu-madrid-3', + 'eu-turin-1', + 'ap-batam-1', + 'ap-kulai-2', + 'me-riyadh-1', + 'mx-monterrey-1', + 'sa-bogota-1', + 'sa-valparaiso-1', + 'us-chicago-1' ]; module.exports = { diff --git a/plugins/aws/cloudformation/cloudformationAdminPriviliges.js b/plugins/aws/cloudformation/cloudformationAdminPriviliges.js index b778b56e7b..7d7c0d14b9 100644 --- a/plugins/aws/cloudformation/cloudformationAdminPriviliges.js +++ b/plugins/aws/cloudformation/cloudformationAdminPriviliges.js @@ -62,9 +62,9 @@ module.exports = { return cb(); } - var roleName = describeStacks.data.Stacks[0].RoleARN.split('/')[1] ? - describeStacks.data.Stacks[0].RoleARN.split('/')[1] : describeStacks.data.Stacks[0].RoleARN; - var adminPrivileged; + var roleNameArr = describeStacks.data.Stacks[0].RoleARN.split('/'); + var roleName = roleNameArr[roleNameArr.length - 1]; + var adminPrivileged = false; var listAttachedRolePolicies = helpers.addSource(cache, source, ['iam', 'listAttachedRolePolicies', defaultRegion, roleName]); @@ -75,24 +75,45 @@ module.exports = { var getRolePolicy = helpers.addSource(cache, source, ['iam', 'getRolePolicy', defaultRegion, roleName]); - if (!listAttachedRolePolicies || - listAttachedRolePolicies.err || - !listAttachedRolePolicies.data || - !listAttachedRolePolicies.data.AttachedPolicies) { + if (!listAttachedRolePolicies || !listRolePolicies) { + helpers.addResult(results, 0, + 'No IAM Attached Role Found', + region, resource); + return cb(); + } + + if (listAttachedRolePolicies.err || !listAttachedRolePolicies.data) { helpers.addResult(results, 3, `Unable to query for IAM attached policy for role "${roleName}": ${helpers.addError(listAttachedRolePolicies)}`, region, resource); return cb(); } - if (!listRolePolicies || listRolePolicies.err || !listRolePolicies.data || !listRolePolicies.data.PolicyNames) { + if (listRolePolicies.err || !listRolePolicies.data) { helpers.addResult(results, 3, - `Unable to query for IAM role policy for role "${roleName}": ${helpers.addError(listRolePolicies)}`, + `Unable to query for IAM role policy for role "${roleName}": ${helpers.addError(listRolePolicies)}`, region, resource); return cb(); } - for (var policy of listAttachedRolePolicies.data.AttachedPolicies) { + var listRoles = helpers.addSource(cache, source, ['iam', 'listRoles', defaultRegion]); + var enrichedRole = null; + if (listRoles && listRoles.data && Array.isArray(listRoles.data)) { + enrichedRole = listRoles.data.find(r => r.RoleName === roleName); + } + + var hasAttachedPolicies = listAttachedRolePolicies.data.AttachedPolicies && listAttachedRolePolicies.data.AttachedPolicies.length; + var hasInlinePolicies = listRolePolicies.data.PolicyNames && listRolePolicies.data.PolicyNames.length; + + var attachedPolicies = hasAttachedPolicies + ? listAttachedRolePolicies.data.AttachedPolicies + : (enrichedRole && enrichedRole.attachedPolicies && Array.isArray(enrichedRole.attachedPolicies) && enrichedRole.attachedPolicies.length ? enrichedRole.attachedPolicies : []); + + var inlinePolicyNames = hasInlinePolicies + ? listRolePolicies.data.PolicyNames + : (enrichedRole && enrichedRole.inlinePolicies && Array.isArray(enrichedRole.inlinePolicies) && enrichedRole.inlinePolicies.length ? enrichedRole.inlinePolicies : []); + + for (var policy of attachedPolicies) { if (!policy.PolicyArn) continue; if (policy.PolicyArn === managedAdminPolicy) { @@ -134,13 +155,13 @@ module.exports = { if (adminPrivileged) break; } - for (var policyName of listRolePolicies.data.PolicyNames) { + for (var policyName of inlinePolicyNames) { if (getRolePolicy && getRolePolicy[policyName] && getRolePolicy[policyName].data && getRolePolicy[policyName].data.PolicyDocument) { - let statements = getRolePolicy[policyName].data.PolicyDocument; - if (!statements) break; + let statements = helpers.normalizePolicyDocument(getRolePolicy[policyName].data.PolicyDocument); + if (!statements) continue; // Loop through statements to see if admin privileges for (let statement of statements) { diff --git a/plugins/aws/ec2/appTierInstanceIamRole.js b/plugins/aws/ec2/appTierInstanceIamRole.js index 2088e85081..b7be76475f 100644 --- a/plugins/aws/ec2/appTierInstanceIamRole.js +++ b/plugins/aws/ec2/appTierInstanceIamRole.js @@ -16,7 +16,7 @@ module.exports = { ec2_app_tier_tag_key: { name: 'EC2 App-Tier Tag Key', description: 'Tag key to indicate App-Tier EC2 instances', - regex: '^.*$s', + regex: '^.*$', default: '' }, }, diff --git a/plugins/aws/ec2/vpcPeeringLeastAccessRoutes.js b/plugins/aws/ec2/vpcPeeringLeastAccessRoutes.js index 7dc24214c7..097765b6cc 100644 --- a/plugins/aws/ec2/vpcPeeringLeastAccessRoutes.js +++ b/plugins/aws/ec2/vpcPeeringLeastAccessRoutes.js @@ -65,14 +65,14 @@ module.exports = { destinations.forEach(function(destination) { if (peerCidrs.indexOf(destination.toLowerCase()) > -1) { - violations.push(`${destination} via ${peeringId}: routes full peer VPC CIDR`); + violations.push(`${destination} via ${peeringId}`); } }); }); if (violations.length) { helpers.addResult(results, 2, - `Route table "${routeTable.RouteTableId}" has non-compliant VPC peering routes: ${violations.join('; ')}`, + `Route table "${routeTable.RouteTableId}" routes full peer VPC CIDR via VPC peering: ${violations.join(', ')}`, region, resource); } else { helpers.addResult(results, 0, diff --git a/plugins/aws/ec2/webTierInstanceIamRole.js b/plugins/aws/ec2/webTierInstanceIamRole.js index 42b03a5e0b..a695150386 100644 --- a/plugins/aws/ec2/webTierInstanceIamRole.js +++ b/plugins/aws/ec2/webTierInstanceIamRole.js @@ -16,7 +16,7 @@ module.exports = { ec2_web_tier_tag_key: { name: 'EC2 Web-Tier Tag Key', description: 'Tag key to indicate Web-Tier EC2 instances', - regex: '^.*$s', + regex: '^.*$', default: '' }, }, diff --git a/plugins/aws/ecr/ecrRepositoryTagImmutability.js b/plugins/aws/ecr/ecrRepositoryTagImmutability.js index 9aade5142c..3cf11deb6d 100644 --- a/plugins/aws/ecr/ecrRepositoryTagImmutability.js +++ b/plugins/aws/ecr/ecrRepositoryTagImmutability.js @@ -41,13 +41,17 @@ module.exports = { var arn = repository.repositoryArn; var immutability = repository.imageTagMutability; - if (immutability == 'IMMUTABLE') { + if (immutability === 'IMMUTABLE') { helpers.addResult(results, 0, 'ECR repository mutability setting is set to IMMUTABLE', region, arn); + } else if (immutability === 'IMMUTABLE_WITH_EXCLUSION') { + helpers.addResult(results, 0, + 'ECR repository mutability setting is set to IMMUTABLE_WITH_EXCLUSION', + region, arn); } else { helpers.addResult(results, 2, - 'ECR repository mutability setting is set to MUTABLE', + 'ECR repository mutability setting is set to ' + immutability, region, arn); } } diff --git a/plugins/aws/ecr/ecrRepositoryTagImmutability.spec.js b/plugins/aws/ecr/ecrRepositoryTagImmutability.spec.js index 34c1e8015d..a17487d36c 100644 --- a/plugins/aws/ecr/ecrRepositoryTagImmutability.spec.js +++ b/plugins/aws/ecr/ecrRepositoryTagImmutability.spec.js @@ -30,6 +30,40 @@ const describeRepositories = [ "encryptionType": "AES256" } }, + { + "repositoryArn": "arn:aws:ecr:us-east-1:111111111111:repository/test", + "registryId": "111111111111", + "repositoryName": "test", + "repositoryUri": "111111111111.dkr.ecr.us-east-1.amazonaws.com/test", + "createdAt": "2021-07-24T12:20:58.000Z", + "imageTagMutability": "IMMUTABLE_WITH_EXCLUSION", + "imageTagMutabilityExclusionFilters": [ + { "filterType": "WILDCARD", "filter": "latest*" } + ], + "imageScanningConfiguration": { + "scanOnPush": false + }, + "encryptionConfiguration": { + "encryptionType": "AES256" + } + }, + { + "repositoryArn": "arn:aws:ecr:us-east-1:111111111111:repository/test", + "registryId": "111111111111", + "repositoryName": "test", + "repositoryUri": "111111111111.dkr.ecr.us-east-1.amazonaws.com/test", + "createdAt": "2021-07-24T12:20:58.000Z", + "imageTagMutability": "MUTABLE_WITH_EXCLUSION", + "imageTagMutabilityExclusionFilters": [ + { "filterType": "WILDCARD", "filter": "prod*" } + ], + "imageScanningConfiguration": { + "scanOnPush": false + }, + "encryptionConfiguration": { + "encryptionType": "AES256" + } + }, ] const createCache = (ecrRepository) => { @@ -82,6 +116,22 @@ describe('ecrRepositoryTagImmutability', () => { }) }); + it('should PASS if repository is immutable with exclusion filters', () => { + const cache = createCache([describeRepositories[2]]); + ecrRepositoryTagImmutability.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + }) + }); + + it('should FAIL if repository is mutable with exclusion filters', () => { + const cache = createCache([describeRepositories[3]]); + ecrRepositoryTagImmutability.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + }) + }); + it('should UNKNOWN if unable to get repository policy', () => { const cache = repositoryErrorCache(); ecrRepositoryTagImmutability.run(cache,{}, (err, results) => { diff --git a/plugins/aws/eks/eksKubernetesVersion.js b/plugins/aws/eks/eksKubernetesVersion.js index 26d362c82b..81b000a8d6 100644 --- a/plugins/aws/eks/eksKubernetesVersion.js +++ b/plugins/aws/eks/eksKubernetesVersion.js @@ -45,7 +45,10 @@ module.exports = { '1.29': '2025-03-23', '1.30': '2025-07-23', '1.31': '2025-11-26', - '1.32': '2026-03-23' + '1.32': '2026-03-23', + '1.33': '2026-06-29', + '1.34': '2026-12-02', + '1.35': '2027-03-27' }; var outdatedVersions = { diff --git a/plugins/aws/eks/eksKubernetesVersion.spec.js b/plugins/aws/eks/eksKubernetesVersion.spec.js index da6e641bb6..2b01ccbf93 100644 --- a/plugins/aws/eks/eksKubernetesVersion.spec.js +++ b/plugins/aws/eks/eksKubernetesVersion.spec.js @@ -82,7 +82,7 @@ describe('eksKubernetesVersion', function () { "cluster": { "name": "mycluster", "arn": "arn:aws:eks:us-east-1:012345678911:cluster/mycluster", - "version": "1.33", + "version": "1.35", } } ); diff --git a/plugins/aws/iam/accessKeysLastUsed.spec.js b/plugins/aws/iam/accessKeysLastUsed.spec.js index 4da05c61dc..581ebfc269 100644 --- a/plugins/aws/iam/accessKeysLastUsed.spec.js +++ b/plugins/aws/iam/accessKeysLastUsed.spec.js @@ -4,7 +4,7 @@ const accessKeysLastUsed = require('./accessKeysLastUsed'); var warnDate = new Date(); warnDate.setMonth(warnDate.getMonth() - 4); var passDate = new Date(); -passDate.setMonth(passDate.getMonth() - 1); +passDate.setDate(passDate.getDate() - 15); var failDate = new Date(); failDate.setMonth(failDate.getMonth() - 7); diff --git a/plugins/aws/iam/iamPoliciesPresent.js b/plugins/aws/iam/iamPoliciesPresent.js index 5d35354e32..279c2bb844 100644 --- a/plugins/aws/iam/iamPoliciesPresent.js +++ b/plugins/aws/iam/iamPoliciesPresent.js @@ -86,8 +86,20 @@ module.exports = { } } + if (role.attachedPolicies && Array.isArray(role.attachedPolicies) && role.attachedPolicies.length) { + for (let policy of role.attachedPolicies) { + if (!attachedPolicies.includes(policy.PolicyName)) attachedPolicies.push(policy.PolicyName); + } + } + if (listRolePolicies.data && listRolePolicies.data.PolicyNames) attachedPolicies = attachedPolicies.concat(listRolePolicies.data.PolicyNames); + if (role.inlinePolicies && Array.isArray(role.inlinePolicies) && role.inlinePolicies.length) { + for (let policy of role.inlinePolicies) { + if (!attachedPolicies.includes(policy)) attachedPolicies.push(policy); + } + } + for (let policy of config.iam_required_policy_names) { if (!attachedPolicies.includes(policy)) difference.push(policy); } diff --git a/plugins/aws/iam/iamRolePolicies.js b/plugins/aws/iam/iamRolePolicies.js index 9180eeb59d..bcecc7dbf1 100644 --- a/plugins/aws/iam/iamRolePolicies.js +++ b/plugins/aws/iam/iamRolePolicies.js @@ -252,8 +252,54 @@ module.exports = { } } + if (role.attachedPolicies && Array.isArray(role.attachedPolicies) && role.attachedPolicies.length) { + for (var enrichedPolicy of role.attachedPolicies) { + if (enrichedPolicy.PolicyArn === managedAdminPolicy) { + if (config.iam_policy_message_format) { + roleFailures.admin = 'managedAdminPolicy'; + } else { + roleFailures.push('Role has managed AdministratorAccess policy'); + } + break; + } + + if (config.ignore_aws_managed_iam_policies && new RegExp(`^arn:${awsOrGov}:iam::aws:.*`).test(enrichedPolicy.PolicyArn)) continue; + + if (config.ignore_customer_managed_iam_policies && new RegExp(`^arn:${awsOrGov}:iam::[0-9]{12}:.*`).test(enrichedPolicy.PolicyArn)) continue; + + var enrichedGetPolicy = helpers.addSource(cache, source, + ['iam', 'getPolicy', region, enrichedPolicy.PolicyArn]); + + if (enrichedGetPolicy && + enrichedGetPolicy.data && + enrichedGetPolicy.data.Policy && + enrichedGetPolicy.data.Policy.DefaultVersionId) { + var enrichedGetPolicyVersion = helpers.addSource(cache, source, + ['iam', 'getPolicyVersion', region, enrichedPolicy.PolicyArn]); + + if (enrichedGetPolicyVersion && + enrichedGetPolicyVersion.data && + enrichedGetPolicyVersion.data.PolicyVersion && + enrichedGetPolicyVersion.data.PolicyVersion.Document) { + let enrichedStatements = helpers.normalizePolicyDocument( + enrichedGetPolicyVersion.data.PolicyVersion.Document); + if (!enrichedStatements) break; + + if (config.iam_policy_message_format) { + addRoleFailuresPolicyName(roleFailures, enrichedStatements, 'managed', enrichedPolicy.PolicyName, config.ignore_service_specific_wildcards, allowedRegex, config.ignore_iam_policy_resource_wildcards); + } else { + addRoleFailures(roleFailures, enrichedStatements, 'managed', config.ignore_service_specific_wildcards, allowedRegex, config.ignore_iam_policy_resource_wildcards); + } + } + } + } + } + + var processedInlinePolicies = new Set(); + if (listRolePolicies.data && - listRolePolicies.data.PolicyNames) { + listRolePolicies.data.PolicyNames && + listRolePolicies.data.PolicyNames.length) { for (var p in listRolePolicies.data.PolicyNames) { var policyName = listRolePolicies.data.PolicyNames[p]; @@ -263,8 +309,10 @@ module.exports = { getRolePolicy[policyName].data && getRolePolicy[policyName].data.PolicyDocument) { - var statements = getRolePolicy[policyName].data.PolicyDocument; - if (!statements) break; + processedInlinePolicies.add(policyName); + var policyDoc = getRolePolicy[policyName].data.PolicyDocument; + var statements = Array.isArray(policyDoc) ? policyDoc : helpers.normalizePolicyDocument(policyDoc); + if (!statements) continue; if (config.iam_policy_message_format) { addRoleFailuresPolicyName(roleFailures, statements, 'inline', policyName, config.ignore_service_specific_wildcards, allowedRegex, config.ignore_iam_policy_resource_wildcards); } else { @@ -274,13 +322,30 @@ module.exports = { } } + if (role.inlinePolicies && Array.isArray(role.inlinePolicies) && role.inlinePolicies.length) { + for (var enrichedInlinePolicy of role.inlinePolicies) { + if (!enrichedInlinePolicy || !enrichedInlinePolicy.PolicyDocument) continue; + + var enrichedPolicyName = enrichedInlinePolicy.PolicyName; + if (processedInlinePolicies.has(enrichedPolicyName)) continue; + + var enrichedPolicyDoc = enrichedInlinePolicy.PolicyDocument; + var enrichedStatementsInline = Array.isArray(enrichedPolicyDoc) ? enrichedPolicyDoc : helpers.normalizePolicyDocument(enrichedPolicyDoc); + if (!enrichedStatementsInline) continue; + if (config.iam_policy_message_format) { + addRoleFailuresPolicyName(roleFailures, enrichedStatementsInline, 'inline', enrichedPolicyName, config.ignore_service_specific_wildcards, allowedRegex, config.ignore_iam_policy_resource_wildcards); + } else { + addRoleFailures(roleFailures, enrichedStatementsInline, 'inline', config.ignore_service_specific_wildcards, allowedRegex, config.ignore_iam_policy_resource_wildcards); + } + } + } + if (config.iam_policy_message_format) { compileFormattedResults(roleFailures, role, results, custom); } else { compileSimpleResults(roleFailures, role, results, custom); } - cb(); }, function(){ callback(null, results, source); @@ -407,7 +472,7 @@ function hasFailures(roleFailures) { if (roleFailures.managed.allActionsSelectedResources.length) return true; if (roleFailures.managed.actionsAllResources.length) return true; if (Object.keys(roleFailures.managed.wildcardActions).length) return true; - if (roleFailures.managed.regexMismatch.length) return true; + if (Object.keys(roleFailures.managed.regexMismatch).length) return true; } if (roleFailures.inline) { @@ -415,7 +480,7 @@ function hasFailures(roleFailures) { if (roleFailures.inline.allActionsSelectedResources.length) return true; if (roleFailures.inline.actionsAllResources.length) return true; if (Object.keys(roleFailures.inline.wildcardActions).length) return true; - if (roleFailures.inline.regexMismatch.length) return true; + if (Object.keys(roleFailures.inline.regexMismatch).length) return true; } return false; diff --git a/plugins/aws/iam/iamUserAdmins.js b/plugins/aws/iam/iamUserAdmins.js index 27b154a0d7..5c8da755fb 100644 --- a/plugins/aws/iam/iamUserAdmins.js +++ b/plugins/aws/iam/iamUserAdmins.js @@ -119,8 +119,50 @@ module.exports = { if (listAttachedUserPolicies.data && listAttachedUserPolicies.data.AttachedPolicies) { for (var a in listAttachedUserPolicies.data.AttachedPolicies) { - var policy = listAttachedUserPolicies.data.AttachedPolicies[a]; + var attachedPolicy = listAttachedUserPolicies.data.AttachedPolicies[a]; + if (!attachedPolicy.PolicyArn) continue; + + if (attachedPolicy.PolicyArn === managedAdminPolicy) { + userAdmins.push({name: user.UserName, arn: user.Arn}); + return cb(); + } + + var managedGetPolicy = helpers.addSource(cache, source, + ['iam', 'getPolicy', region, attachedPolicy.PolicyArn]); + + if (managedGetPolicy && + managedGetPolicy.data && + managedGetPolicy.data.Policy && + managedGetPolicy.data.Policy.DefaultVersionId) { + var managedGetPolicyVersion = helpers.addSource(cache, source, + ['iam', 'getPolicyVersion', region, attachedPolicy.PolicyArn]); + + if (managedGetPolicyVersion && + managedGetPolicyVersion.data && + managedGetPolicyVersion.data.PolicyVersion && + managedGetPolicyVersion.data.PolicyVersion.Document) { + let managedStatements = helpers.normalizePolicyDocument( + managedGetPolicyVersion.data.PolicyVersion.Document); + if (!managedStatements) break; + + // Loop through statements to see if admin privileges + for (let managedStmt of managedStatements) { + if (managedStmt.Effect && managedStmt.Effect.toUpperCase() === 'ALLOW' && + managedStmt.Action && managedStmt.Action.indexOf('*') > -1 && + managedStmt.Resource && managedStmt.Resource.indexOf('*') > -1) { + userAdmins.push({name: user.UserName, arn: user.Arn}); + return cb(); + } + } + } + } + } + } + + // See if user has admin managed policy (enriched) + if (user.attachedPolicies && Array.isArray(user.attachedPolicies) && user.attachedPolicies.length) { + for (var policy of user.attachedPolicies) { if (!policy.PolicyArn) continue; if (policy.PolicyArn === managedAdminPolicy) { @@ -146,7 +188,6 @@ module.exports = { getPolicyVersion.data.PolicyVersion.Document); if (!statements) break; - // Loop through statements to see if admin privileges for (let statement of statements) { if (statement.Effect && statement.Effect.toUpperCase() === 'ALLOW' && statement.Action && statement.Action.indexOf('*') > -1 && @@ -165,8 +206,36 @@ module.exports = { listUserPolicies.data.PolicyNames) { for (var p in listUserPolicies.data.PolicyNames) { - var policyName = listUserPolicies.data.PolicyNames[p]; + var userPolicyName = listUserPolicies.data.PolicyNames[p]; + if (getUserPolicy && + getUserPolicy[userPolicyName] && + getUserPolicy[userPolicyName].data && + getUserPolicy[userPolicyName].data.PolicyDocument) { + + var userPolicyStatements = helpers.normalizePolicyDocument( + getUserPolicy[userPolicyName].data.PolicyDocument); + if (!userPolicyStatements) break; + + // Loop through statements to see if admin privileges + for (var sp in userPolicyStatements) { + var userStmt = userPolicyStatements[sp]; + + if (userStmt.Effect === 'Allow' && + userStmt.Action.indexOf('*') > -1 && + userStmt.Resource && + userStmt.Resource.indexOf('*') > -1) { + userAdmins.push({name: user.UserName, arn: user.Arn}); + return cb(); + } + } + } + } + } + + // See if user has admin inline policy (enriched) + if (user.inlinePolicies && Array.isArray(user.inlinePolicies) && user.inlinePolicies.length) { + for (var policyName of user.inlinePolicies) { if (getUserPolicy && getUserPolicy[policyName] && getUserPolicy[policyName].data && @@ -176,7 +245,6 @@ module.exports = { getUserPolicy[policyName].data.PolicyDocument); if (!statements) break; - // Loop through statements to see if admin privileges for (var s in statements) { var statement = statements[s]; @@ -210,6 +278,12 @@ module.exports = { var getGroupPolicy = helpers.addSource(cache, source, ['iam', 'getGroupPolicy', region, group.GroupName]); + var listGroups = helpers.addSource(cache, source, ['iam', 'listGroups', region]); + var enrichedGroup = null; + if (listGroups && listGroups.data && Array.isArray(listGroups.data)) { + enrichedGroup = listGroups.data.find(g => g.GroupName === group.GroupName); + } + // See if group has admin managed policy if (listAttachedGroupPolicies && listAttachedGroupPolicies.data && @@ -225,6 +299,16 @@ module.exports = { } } + // See if group has admin managed policy (enriched) + if (enrichedGroup && enrichedGroup.attachedPolicies && Array.isArray(enrichedGroup.attachedPolicies) && enrichedGroup.attachedPolicies.length) { + for (var enrichedPolicy of enrichedGroup.attachedPolicies) { + if (enrichedPolicy.PolicyArn === managedAdminPolicy) { + userAdmins.push({name: user.UserName, arn: user.Arn}); + return cb(); + } + } + } + // See if group has admin inline policy if (listGroupPolicies && listGroupPolicies.data && @@ -238,11 +322,37 @@ module.exports = { getGroupPolicy[policyGroupName].data && getGroupPolicy[policyGroupName].data.PolicyDocument) { - var statementsGroup = helpers.normalizePolicyDocument( + var groupPolicyStatements = helpers.normalizePolicyDocument( getGroupPolicy[policyGroupName].data.PolicyDocument); - if (!statementsGroup) break; + if (!groupPolicyStatements) break; // Loop through statements to see if admin privileges + for (var sg in groupPolicyStatements) { + var groupStmt = groupPolicyStatements[sg]; + + if (groupStmt.Effect === 'Allow' && + groupStmt.Action.indexOf('*') > -1 && + groupStmt.Resource.indexOf('*') > -1) { + userAdmins.push({name: user.UserName, arn: user.Arn}); + return cb(); + } + } + } + } + } + + // See if group has admin inline policy (enriched) + if (enrichedGroup && enrichedGroup.inlinePolicies && Array.isArray(enrichedGroup.inlinePolicies) && enrichedGroup.inlinePolicies.length) { + for (var enrichedPolicyName of enrichedGroup.inlinePolicies) { + if (getGroupPolicy && + getGroupPolicy[enrichedPolicyName] && + getGroupPolicy[enrichedPolicyName].data && + getGroupPolicy[enrichedPolicyName].data.PolicyDocument) { + + var statementsGroup = helpers.normalizePolicyDocument( + getGroupPolicy[enrichedPolicyName].data.PolicyDocument); + if (!statementsGroup) break; + for (s in statementsGroup) { var statementGroup = statementsGroup[s]; diff --git a/plugins/aws/iam/iamUserUnauthorizedToEdit.js b/plugins/aws/iam/iamUserUnauthorizedToEdit.js index 27cb90f765..7a242d2cc7 100644 --- a/plugins/aws/iam/iamUserUnauthorizedToEdit.js +++ b/plugins/aws/iam/iamUserUnauthorizedToEdit.js @@ -125,6 +125,16 @@ module.exports = { } } + // See if user has administrator access or IAM full access (enriched) + if (user.attachedPolicies && Array.isArray(user.attachedPolicies) && user.attachedPolicies.length) { + for (var policy of user.attachedPolicies) { + if (policy.PolicyArn === adminAccessArn || + policy.PolicyArn === iamFullAccessArn) { + addPolicyToUserObj(restrictedUser, user, policy.PolicyName); + } + } + } + // See if user has IAM full access inline policy if (listUserPolicies.data && listUserPolicies.data.PolicyNames) { for (var up in listUserPolicies.data.PolicyNames) { @@ -140,6 +150,29 @@ module.exports = { if (!statements) break; // Loop through statements to see if admin privileges + for (var si in statements) { + let statement = statements[si]; + + if (helpers.userGlobalAccess(statement, iamEditAccessPermissions)) { + addPolicyToUserObj(restrictedUser, user, policyName); + } + } + } + } + } + + // See if user has IAM full access inline policy (enriched) + if (user.inlinePolicies && Array.isArray(user.inlinePolicies) && user.inlinePolicies.length) { + for (var policyName of user.inlinePolicies) { + if (getUserPolicy && + getUserPolicy[policyName] && + getUserPolicy[policyName].data && + getUserPolicy[policyName].data.PolicyDocument) { + + let statements = helpers.normalizePolicyDocument( + getUserPolicy[policyName].data.PolicyDocument); + if (!statements) break; + for (var s in statements) { let statement = statements[s]; @@ -169,6 +202,12 @@ module.exports = { var getGroupPolicy = helpers.addSource(cache, source, ['iam', 'getGroupPolicy', region, group.GroupName]); + var listGroups = helpers.addSource(cache, source, ['iam', 'listGroups', region]); + var enrichedGroup = null; + if (listGroups && listGroups.data && Array.isArray(listGroups.data)) { + enrichedGroup = listGroups.data.find(g => g.GroupName === group.GroupName); + } + // See if group has admin managed policy if (listAttachedGroupPolicies && listAttachedGroupPolicies.data && @@ -183,6 +222,16 @@ module.exports = { } } + // See if group has admin managed policy (enriched) + if (enrichedGroup && enrichedGroup.attachedPolicies && Array.isArray(enrichedGroup.attachedPolicies) && enrichedGroup.attachedPolicies.length) { + for (var enrichedPolicy of enrichedGroup.attachedPolicies) { + if (enrichedPolicy.PolicyArn === adminAccessArn || + enrichedPolicy.PolicyArn === iamFullAccessArn) { + addPolicyToUserObj(restrictedUser, user, enrichedPolicy.PolicyName); + } + } + } + // See if group has admin inline policy if (listGroupPolicies && listGroupPolicies.data && @@ -195,16 +244,38 @@ module.exports = { getGroupPolicy[policyGroupName] && getGroupPolicy[policyGroupName].data && getGroupPolicy[policyGroupName].data.PolicyDocument) { - var statementsGroup = helpers.normalizePolicyDocument( + var groupPolicyStatements = helpers.normalizePolicyDocument( getGroupPolicy[policyGroupName].data.PolicyDocument); - if (!statementsGroup) break; + if (!groupPolicyStatements) break; // Loop through statements to see if admin privileges + for (var sgi in groupPolicyStatements) { + let statementGroup = groupPolicyStatements[sgi]; + + if (helpers.userGlobalAccess(statementGroup, iamEditAccessPermissions)) { + addPolicyToUserObj(restrictedUser, user, policyGroupName); + } + } + } + } + } + // See if group has admin inline policy (enriched) + if (enrichedGroup && enrichedGroup.inlinePolicies && Array.isArray(enrichedGroup.inlinePolicies) && enrichedGroup.inlinePolicies.length) { + for (var enrichedPolicyName of enrichedGroup.inlinePolicies) { + if (getGroupPolicy && + getGroupPolicy[enrichedPolicyName] && + getGroupPolicy[enrichedPolicyName].data && + getGroupPolicy[enrichedPolicyName].data.PolicyDocument) { + + var statementsGroup = helpers.normalizePolicyDocument( + getGroupPolicy[enrichedPolicyName].data.PolicyDocument); + if (!statementsGroup) break; + for (s in statementsGroup) { let statementGroup = statementsGroup[s]; if (helpers.userGlobalAccess(statementGroup, iamEditAccessPermissions)) { - addPolicyToUserObj(restrictedUser, user, policyGroupName); + addPolicyToUserObj(restrictedUser, user, enrichedPolicyName); } } } diff --git a/plugins/aws/iam/iamUserWithoutPermissions.js b/plugins/aws/iam/iamUserWithoutPermissions.js index 37a940c548..6ebe4dc09c 100644 --- a/plugins/aws/iam/iamUserWithoutPermissions.js +++ b/plugins/aws/iam/iamUserWithoutPermissions.js @@ -72,7 +72,10 @@ module.exports = { } var listGroupPolicies, listAttachedGroupPolicies; + var hasGroupPermissions = false; if (listGroupsForUser.data && listGroupsForUser.data.Groups){ + var listGroups = helpers.addSource(cache, source, ['iam', 'listGroups', region]); + for (let group of listGroupsForUser.data.Groups){ listGroupPolicies = helpers.addSource(cache, source, ['iam', 'listGroupPolicies', region, group.GroupName]); @@ -92,19 +95,41 @@ module.exports = { return cb(); } - if ((listGroupPolicies.data.PolicyNames && listGroupPolicies.data.PolicyNames.length) || - (listAttachedGroupPolicies.data.AttachedPolicies && listAttachedGroupPolicies.data.AttachedPolicies.length)){ + var hasInlineGroupPolicies = listGroupPolicies.data.PolicyNames && listGroupPolicies.data.PolicyNames.length; + var hasAttachedGroupPolicies = listAttachedGroupPolicies.data.AttachedPolicies && listAttachedGroupPolicies.data.AttachedPolicies.length; + + var enrichedGroup = null; + if ((!hasAttachedGroupPolicies || !hasInlineGroupPolicies) && listGroups && listGroups.data && Array.isArray(listGroups.data)) { + enrichedGroup = listGroups.data.find(g => g.GroupName === group.GroupName); + } + + if (!hasAttachedGroupPolicies && enrichedGroup && enrichedGroup.attachedPolicies && Array.isArray(enrichedGroup.attachedPolicies) && enrichedGroup.attachedPolicies.length) { + hasAttachedGroupPolicies = true; + } + + if (!hasInlineGroupPolicies && enrichedGroup && enrichedGroup.inlinePolicies && Array.isArray(enrichedGroup.inlinePolicies) && enrichedGroup.inlinePolicies.length) { + hasInlineGroupPolicies = true; + } + + if (hasInlineGroupPolicies || hasAttachedGroupPolicies){ + hasGroupPermissions = true; break; } } } - if ((listAttachedUserPolicies.data.AttachedPolicies && - listAttachedUserPolicies.data.AttachedPolicies.length) || - (listUserPolicies.data.PolicyNames && - listUserPolicies.data.PolicyNames.length) || (listAttachedGroupPolicies && listAttachedGroupPolicies.data.AttachedPolicies && - listAttachedGroupPolicies.data.AttachedPolicies.length) || - (listGroupPolicies && listGroupPolicies.data.PolicyNames && listGroupPolicies.data.PolicyNames.length)) { + var hasAttachedUserPolicies = listAttachedUserPolicies.data.AttachedPolicies && listAttachedUserPolicies.data.AttachedPolicies.length; + var hasInlineUserPolicies = listUserPolicies.data.PolicyNames && listUserPolicies.data.PolicyNames.length; + + if (!hasAttachedUserPolicies && user.attachedPolicies && Array.isArray(user.attachedPolicies) && user.attachedPolicies.length) { + hasAttachedUserPolicies = true; + } + + if (!hasInlineUserPolicies && user.inlinePolicies && Array.isArray(user.inlinePolicies) && user.inlinePolicies.length) { + hasInlineUserPolicies = true; + } + + if (hasAttachedUserPolicies || hasInlineUserPolicies || hasGroupPermissions) { helpers.addResult(results, 0, 'IAM user has permissions', 'global', user.Arn); } else { helpers.addResult(results, 2, 'IAM user does not have any permissions', 'global', user.Arn); diff --git a/plugins/aws/iam/rolePolicyUnusedServices.js b/plugins/aws/iam/rolePolicyUnusedServices.js index bfca0f39c2..8babf58611 100644 --- a/plugins/aws/iam/rolePolicyUnusedServices.js +++ b/plugins/aws/iam/rolePolicyUnusedServices.js @@ -334,7 +334,62 @@ module.exports = { if (listAttachedRolePolicies.data && listAttachedRolePolicies.data.AttachedPolicies) { - for (var policy of listAttachedRolePolicies.data.AttachedPolicies) { + for (var attachedPolicy of listAttachedRolePolicies.data.AttachedPolicies) { + if (attachedPolicy.PolicyArn === managedAdminPolicy) { + roleFailures.push('Role has managed AdministratorAccess policy'); + break; + } + + if (config.ignore_aws_managed_iam_policies && new RegExp(`^arn:${awsOrGov}:iam::aws:.*`).test(attachedPolicy.PolicyArn)) continue; + + if (config.ignore_customer_managed_iam_policies && new RegExp(`^arn:${awsOrGov}:iam::[0-9]{12}:.*`).test(attachedPolicy.PolicyArn)) continue; + + var managedGetPolicy = helpers.addSource(cache, source, + ['iam', 'getPolicy', iamRegion, attachedPolicy.PolicyArn]); + + if (managedGetPolicy && + managedGetPolicy.data && + managedGetPolicy.data.Policy && + managedGetPolicy.data.Policy.DefaultVersionId) { + var managedGetPolicyVersion = helpers.addSource(cache, source, + ['iam', 'getPolicyVersion', iamRegion, attachedPolicy.PolicyArn]); + + if (managedGetPolicyVersion && + managedGetPolicyVersion.data && + managedGetPolicyVersion.data.PolicyVersion && + managedGetPolicyVersion.data.PolicyVersion.Document) { + let managedStatements = helpers.normalizePolicyDocument( + managedGetPolicyVersion.data.PolicyVersion.Document); + if (!managedStatements) break; + for (let statement of managedStatements) { + if (statement.Action && statement.Action.length) { + + for (let action of statement.Action) { + if (config.whitelist_unused_actions_for_resources.includes(action.toLowerCase())) continue; + let service = action.split(':')[0] ? action.split(':')[0].toLowerCase() : ''; + let resourceAction = action.split(':')[1] ? action.split(':')[1].toLowerCase() : ''; + + if (allServices[service] && !config.whitelist_unused_services.includes(service)) { + for (let supportedResource of allServices[service]) { + if (resourceAction.includes(supportedResource)) { + if (!allResources[service] || !allResources[service].includes(supportedResource)) { + if (policyFailures.indexOf(action) === -1) policyFailures.push(action); + } + } + } + } + } + } + } + + addRoleFailures(roleFailures, managedStatements, 'managed', config.ignore_service_specific_wildcards, allowedRegex, config.ignore_iam_policy_resource_wildcards); + } + } + } + } + + if (role.attachedPolicies && Array.isArray(role.attachedPolicies) && role.attachedPolicies.length) { + for (var policy of role.attachedPolicies) { if (policy.PolicyArn === managedAdminPolicy) { roleFailures.push('Role has managed AdministratorAccess policy'); break; @@ -391,8 +446,52 @@ module.exports = { if (listRolePolicies.data && listRolePolicies.data.PolicyNames) { for (var p in listRolePolicies.data.PolicyNames) { - var policyName = listRolePolicies.data.PolicyNames[p]; + var rolePolicyName = listRolePolicies.data.PolicyNames[p]; + if (getRolePolicy && + getRolePolicy[rolePolicyName] && + getRolePolicy[rolePolicyName].data && + getRolePolicy[rolePolicyName].data.PolicyDocument) { + var inlinePolicyStatements = getRolePolicy[rolePolicyName].data.PolicyDocument; + + if (!inlinePolicyStatements) break; + + for (let statement of inlinePolicyStatements) { + if ((statement.Action && statement.Action.length && statement.Action[0] === '*') || + (statement.Resource && statement.Resource.length && statement.Resource[0] === '*')) { + continue; + } + + if (statement.Action && statement.Action.length && + statement.Resource && statement.Resource.length) { + let service = statement.Resource[0].includes('arn') ? statement.Resource[0].split(':')[2].toLowerCase() : + statement.Action[0].split(':')[1].toLowerCase(); + if (statement.Action.length > 1 || statement.Action[0] !== '*') { + for (let action of statement.Action) { + if (config.whitelist_unused_actions_for_resources.includes(action)) continue; + let resourceAction = action.split(':')[1].toLowerCase(); + + if (allServices[service] && !config.whitelist_unused_services.includes(service)) { + for (let supportedResource of allServices[service]) { + if (resourceAction.includes(supportedResource)) { + if (!allResources[service] || !allResources[service].includes(supportedResource)) { + if (policyFailures.indexOf(action) === -1) policyFailures.push(action); + } + } + } + } + } + } + } + } + + addRoleFailures(roleFailures, inlinePolicyStatements, 'inline', config.ignore_service_specific_wildcards, allowedRegex, config.ignore_iam_policy_resource_wildcards); + } + } + } + + if (role.inlinePolicies && Array.isArray(role.inlinePolicies) && role.inlinePolicies.length) { + for (var policyName of role.inlinePolicies) { if (getRolePolicy && getRolePolicy[policyName] && getRolePolicy[policyName].data && @@ -446,6 +545,7 @@ module.exports = { } cb(); + }, function() { callback(null, results, source); }); diff --git a/plugins/aws/imagebuilder/imageRecipeVolumeEncrypted.js b/plugins/aws/imagebuilder/imageRecipeVolumeEncrypted.js index 6f93d806ad..20b50012d0 100644 --- a/plugins/aws/imagebuilder/imageRecipeVolumeEncrypted.js +++ b/plugins/aws/imagebuilder/imageRecipeVolumeEncrypted.js @@ -89,9 +89,19 @@ module.exports = { `Unable to get image Recipe description: ${helpers.addError(getImageRecipe)}`, region, resource); continue; - } + } + + let blockDeviceMappings = getImageRecipe.data.imageRecipe.blockDeviceMappings; + + if (!blockDeviceMappings || !blockDeviceMappings.length) { + helpers.addResult(results, 0, + 'Image recipe does not have any block device mappings', + region, resource); + continue; + } + let poorlyEncrypted = []; - for (let mapping of getImageRecipe.data.imageRecipe.blockDeviceMappings){ + for (let mapping of blockDeviceMappings){ if (mapping.ebs && !mapping.ebs.encrypted){ poorlyEncrypted.push(mapping.ebs); continue; diff --git a/plugins/aws/lambda/lambdaAdminPrivileges.js b/plugins/aws/lambda/lambdaAdminPrivileges.js index 5c08a4263a..c034aa8267 100644 --- a/plugins/aws/lambda/lambdaAdminPrivileges.js +++ b/plugins/aws/lambda/lambdaAdminPrivileges.js @@ -13,7 +13,7 @@ module.exports = { apis: ['Lambda:listFunctions', 'IAM:listRoles', 'IAM:listAttachedRolePolicies', 'IAM:listRolePolicies', 'IAM:listPolicies', 'IAM:getPolicy', 'IAM:getPolicyVersion', 'IAM:getRolePolicy'], realtime_triggers: ['lambda:CreateFunction','lambda:UpdateFunctionConfiguration', 'lambda:DeleteFunction'], - + run: function(cache, settings, callback) { var results = []; var source = {}; @@ -28,7 +28,6 @@ module.exports = { ['lambda', 'listFunctions', region]); if (!listFunctions) return rcb(); - if (listFunctions.err || !listFunctions.data) { helpers.addResult(results, 3, `Unable to query for Lambda functions: ${helpers.addError(listFunctions)}`, region); @@ -62,91 +61,92 @@ module.exports = { var getRolePolicy = helpers.addSource(cache, source, ['iam', 'getRolePolicy', defaultRegion, roleName]); - if (!listAttachedRolePolicies || !listRolePolicies ) { + if (!listAttachedRolePolicies || !listRolePolicies) { helpers.addResult(results, 0, 'No IAM Attached Role Found', region, resource); return fcb(); } - if (listAttachedRolePolicies.err || - !listAttachedRolePolicies.data || - !listAttachedRolePolicies.data.AttachedPolicies) { + if (listAttachedRolePolicies.err || !listAttachedRolePolicies.data) { helpers.addResult(results, 3, `Unable to query for IAM attached policy for role "${roleName}": ${helpers.addError(listAttachedRolePolicies)}`, region, resource); return fcb(); } - if (listRolePolicies.err || !listRolePolicies.data || !listRolePolicies.data.PolicyNames) { + if (listRolePolicies.err || !listRolePolicies.data) { helpers.addResult(results, 3, - `Unable to query for IAM role policy for role "${roleName}": ${helpers.addError(listRolePolicies)}`, + `Unable to query for IAM role policy for role "${roleName}": ${helpers.addError(listRolePolicies)}`, region, resource); return fcb(); } - for (var policy of listAttachedRolePolicies.data.AttachedPolicies) { - if (!policy.PolicyArn) continue; + var listRoles = helpers.addSource(cache, source, ['iam', 'listRoles', defaultRegion]); + var enrichedRole = null; + if (listRoles && listRoles.data && Array.isArray(listRoles.data)) { + enrichedRole = listRoles.data.find(r => r.RoleName === roleName); + } + + var hasAttachedPolicies = listAttachedRolePolicies.data.AttachedPolicies && listAttachedRolePolicies.data.AttachedPolicies.length; + var hasInlinePolicies = listRolePolicies.data.PolicyNames && listRolePolicies.data.PolicyNames.length; + var attachedPolicies = hasAttachedPolicies + ? listAttachedRolePolicies.data.AttachedPolicies + : (enrichedRole && enrichedRole.attachedPolicies && Array.isArray(enrichedRole.attachedPolicies) && enrichedRole.attachedPolicies.length + ? enrichedRole.attachedPolicies : []); + + var inlinePolicyNames = hasInlinePolicies + ? listRolePolicies.data.PolicyNames + : (enrichedRole && enrichedRole.inlinePolicies && Array.isArray(enrichedRole.inlinePolicies) && enrichedRole.inlinePolicies.length + ? enrichedRole.inlinePolicies : []); + + // check attached managed policies + for (var policy of attachedPolicies) { + if (!policy.PolicyArn) continue; if (policy.PolicyArn === managedAdminPolicy) { - helpers.addResult(results, 2, - 'Function has admin privileges', region, resource); - return fcb(); + adminPrivileged = true; + break; } var getPolicy = helpers.addSource(cache, source, ['iam', 'getPolicy', defaultRegion, policy.PolicyArn]); - - if (getPolicy && - getPolicy.data && - getPolicy.data.Policy && - getPolicy.data.Policy.DefaultVersionId) { + if (getPolicy && getPolicy.data && getPolicy.data.Policy && getPolicy.data.Policy.DefaultVersionId) { var getPolicyVersion = helpers.addSource(cache, source, ['iam', 'getPolicyVersion', defaultRegion, policy.PolicyArn]); + if (getPolicyVersion && getPolicyVersion.data && getPolicyVersion.data.PolicyVersion && getPolicyVersion.data.PolicyVersion.Document) { + let statements = helpers.normalizePolicyDocument(getPolicyVersion.data.PolicyVersion.Document); + if (!statements) continue; - if (getPolicyVersion && - getPolicyVersion.data && - getPolicyVersion.data.PolicyVersion && - getPolicyVersion.data.PolicyVersion.Document) { - let statements = helpers.normalizePolicyDocument( - getPolicyVersion.data.PolicyVersion.Document); - if (!statements) break; - - // Loop through statements to see if admin privileges for (let statement of statements) { if (statement.Effect && statement.Effect.toUpperCase() === 'ALLOW' && - statement.Action && statement.Action.indexOf('*') > -1 && - statement.Resource && statement.Resource.indexOf('*') > -1) { + statement.Action && statement.Action.indexOf('*') > -1 && + statement.Resource && statement.Resource.indexOf('*') > -1) { adminPrivileged = true; break; } } } } - if (adminPrivileged) break; } - - for (var policyName of listRolePolicies.data.PolicyNames) { - if (getRolePolicy && - getRolePolicy[policyName] && - getRolePolicy[policyName].data && - getRolePolicy[policyName].data.PolicyDocument) { - let statements = getRolePolicy[policyName].data.PolicyDocument; - if (!statements) break; - - // Loop through statements to see if admin privileges + for (var policyName of inlinePolicyNames) { + if (getRolePolicy && getRolePolicy[policyName] && getRolePolicy[policyName].data && getRolePolicy[policyName].data.PolicyDocument) { + let statements = helpers.normalizePolicyDocument(getRolePolicy[policyName].data.PolicyDocument); + if (!statements) continue; for (let statement of statements) { if (statement.Effect && statement.Effect.toUpperCase() === 'ALLOW' && - statement.Action && statement.Action.indexOf('*') > -1 && - statement.Resource && statement.Resource.indexOf('*') > -1) { + statement.Action && statement.Action.indexOf('*') > -1 && + statement.Resource && statement.Resource.indexOf('*') > -1) { adminPrivileged = true; break; } } } + if (adminPrivileged) break; } + // final decision if (!adminPrivileged) { helpers.addResult(results, 0, 'Function does not have admin privileges', region, resource); @@ -163,4 +163,4 @@ module.exports = { callback(null, results, source); }); } -}; +}; \ No newline at end of file diff --git a/plugins/aws/lambda/lambdaEnhancedMonitoring.js b/plugins/aws/lambda/lambdaEnhancedMonitoring.js index c13b64d5d0..604dc4ae43 100644 --- a/plugins/aws/lambda/lambdaEnhancedMonitoring.js +++ b/plugins/aws/lambda/lambdaEnhancedMonitoring.js @@ -49,11 +49,12 @@ module.exports = { continue; } - if (functionInfo.data && - functionInfo.data.Configuration && - functionInfo.data.Configuration.Layers && - functionInfo.data.Configuration.Layers[0] && - functionInfo.data.Configuration.Layers[0].Arn) { + var layers = functionInfo.data && functionInfo.data.Configuration && functionInfo.data.Configuration.Layers; + var hasInsightsLayer = layers && layers.some(function(layer) { + return layer.Arn && layer.Arn.includes('LambdaInsightsExtension'); + }); + + if (hasInsightsLayer) { helpers.addResult(results, 0, 'Lambda function has enhanced monitoring enabled', region, resource); } else { helpers.addResult(results, 2, 'Lambda function does not have enhanced monitoring enabled', region, resource); diff --git a/plugins/aws/lambda/lambdaEnhancedMonitoring.spec.js b/plugins/aws/lambda/lambdaEnhancedMonitoring.spec.js index c6273116ff..d4f1ca4954 100644 --- a/plugins/aws/lambda/lambdaEnhancedMonitoring.spec.js +++ b/plugins/aws/lambda/lambdaEnhancedMonitoring.spec.js @@ -84,6 +84,44 @@ describe('Lambda Enhanced Monitoring Enabled', function () { lambdaEnableEnhancedMonitoring.run(cache, {}, callback); }); + it('should return failing result if lambda function has only unrelated layers', function (done) { + const lambdaData = [ + { + "FunctionName": "test-lambda", + "FunctionArn": "arn:aws:lambda:us-east-1:000011112222:function:test-lambda" + } + ]; + + const functionInfoData = { + "us-east-1": { + "test-lambda": { + "err": null, + "data": { + "Configuration": { + "Layers": [ + { + "Arn": "arn:aws:lambda:us-east-1:336392948345:layer:AWSSDKPandas-Python39:6" + } + ] + } + } + } + } + }; + + const callback = (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('Lambda function does not have enhanced monitoring enabled'); + done(); + }; + + const cache = createCache(lambdaData, functionInfoData); + + lambdaEnableEnhancedMonitoring.run(cache, {}, callback); + }); + it('should return failing result if lambda function does not have enhanced monitoring enabled', function (done) { const lambdaData = [ { diff --git a/plugins/aws/mwaa/environmentAdminPrivileges.js b/plugins/aws/mwaa/environmentAdminPrivileges.js index 36c20010e9..2a6ada3c41 100644 --- a/plugins/aws/mwaa/environmentAdminPrivileges.js +++ b/plugins/aws/mwaa/environmentAdminPrivileges.js @@ -71,24 +71,40 @@ module.exports = { var getRolePolicy = helpers.addSource(cache, source, ['iam', 'getRolePolicy', defaultRegion, roleName]); - if (!listAttachedRolePolicies || - listAttachedRolePolicies.err || - !listAttachedRolePolicies.data || - !listAttachedRolePolicies.data.AttachedPolicies) { + if (!listAttachedRolePolicies || listAttachedRolePolicies.err || !listAttachedRolePolicies.data) { helpers.addResult(results, 3, `Unable to query for IAM attached policy for role "${roleName}": ${helpers.addError(listAttachedRolePolicies)}`, region, resource); return cb(); } - if (!listRolePolicies || listRolePolicies.err || !listRolePolicies.data || !listRolePolicies.data.PolicyNames) { + if (!listRolePolicies || listRolePolicies.err || !listRolePolicies.data) { helpers.addResult(results, 3, `Unable to query for IAM role policy for role "${roleName}": ${helpers.addError(listRolePolicies)}`, region, resource); return cb(); } - for (var policy of listAttachedRolePolicies.data.AttachedPolicies) { + var listRoles = helpers.addSource(cache, source, ['iam', 'listRoles', defaultRegion]); + var enrichedRole = null; + if (listRoles && listRoles.data && Array.isArray(listRoles.data)) { + enrichedRole = listRoles.data.find(r => r.RoleName === roleName); + } + + var hasAttachedPolicies = listAttachedRolePolicies.data.AttachedPolicies && listAttachedRolePolicies.data.AttachedPolicies.length; + var hasInlinePolicies = listRolePolicies.data.PolicyNames && listRolePolicies.data.PolicyNames.length; + + var attachedPolicies = hasAttachedPolicies + ? listAttachedRolePolicies.data.AttachedPolicies + : (enrichedRole && enrichedRole.attachedPolicies && Array.isArray(enrichedRole.attachedPolicies) && enrichedRole.attachedPolicies.length + ? enrichedRole.attachedPolicies : []); + + var inlinePolicyNames = hasInlinePolicies + ? listRolePolicies.data.PolicyNames + : (enrichedRole && enrichedRole.inlinePolicies && Array.isArray(enrichedRole.inlinePolicies) && enrichedRole.inlinePolicies.length + ? enrichedRole.inlinePolicies : []); + + for (var policy of attachedPolicies) { if (!policy.PolicyArn) continue; if (policy.PolicyArn === managedAdminPolicy) { @@ -130,13 +146,13 @@ module.exports = { if (adminPrivileged) break; } - for (var policyName of listRolePolicies.data.PolicyNames) { + for (var policyName of inlinePolicyNames) { if (getRolePolicy && getRolePolicy[policyName] && getRolePolicy[policyName].data && getRolePolicy[policyName].data.PolicyDocument) { - let statements = getRolePolicy[policyName].data.PolicyDocument; - if (!statements) break; + let statements = helpers.normalizePolicyDocument(getRolePolicy[policyName].data.PolicyDocument); + if (!statements) continue; // Loop through statements to see if admin privileges for (let statement of statements) { diff --git a/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js b/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js index 4e1ecf6a4f..22091079be 100644 --- a/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js +++ b/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js @@ -82,7 +82,6 @@ module.exports = { return; } - helpers.addResult(results, 2, 'Cosmos DB account allows public access', location, account.id); }); diff --git a/plugins/azure/keyvaults/keyVaultKeyExpiry.js b/plugins/azure/keyvaults/keyVaultKeyExpiry.js index 6ba32db018..681f25ed79 100644 --- a/plugins/azure/keyvaults/keyVaultKeyExpiry.js +++ b/plugins/azure/keyvaults/keyVaultKeyExpiry.js @@ -50,6 +50,14 @@ module.exports = { return; } + if (vault.publicNetworkAccess && + vault.publicNetworkAccess.toLowerCase() === 'disabled') { + helpers.addResult(results, 0, + 'Key Vault public network access is disabled; unable to query Key Vault keys', + location, vault.id); + return; + } + var keys = helpers.addSource(cache, source, ['vaults', 'getKeys', location, vault.id]); diff --git a/plugins/azure/keyvaults/keyVaultKeyExpiry.spec.js b/plugins/azure/keyvaults/keyVaultKeyExpiry.spec.js index 7aa4a804b9..942cccbd64 100644 --- a/plugins/azure/keyvaults/keyVaultKeyExpiry.spec.js +++ b/plugins/azure/keyvaults/keyVaultKeyExpiry.spec.js @@ -162,5 +162,18 @@ describe('keyVaultKeyExpiryRbac', function() { auth.run(createCache(null, [listKeyVaults[0]], [getKeys[2]]), { key_vault_key_expiry_fail: '40' }, callback); }); + + it('should give passing result if Key Vault public network access is disabled', function(done) { + const disabledVault = Object.assign({}, listKeyVaults[0], { publicNetworkAccess: 'Disabled' }); + const callback = (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Key Vault public network access is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [disabledVault], []), {}, callback); + }); }); }); diff --git a/plugins/azure/keyvaults/keyVaultKeyExpiryNonRbac.js b/plugins/azure/keyvaults/keyVaultKeyExpiryNonRbac.js index df9665a291..e4639dd4de 100644 --- a/plugins/azure/keyvaults/keyVaultKeyExpiryNonRbac.js +++ b/plugins/azure/keyvaults/keyVaultKeyExpiryNonRbac.js @@ -50,6 +50,14 @@ module.exports = { return; } + if (vault.publicNetworkAccess && + vault.publicNetworkAccess.toLowerCase() === 'disabled') { + helpers.addResult(results, 0, + 'Key Vault public network access is disabled; unable to query Key Vault keys', + location, vault.id); + return; + } + var keys = helpers.addSource(cache, source, ['vaults', 'getKeys', location, vault.id]); diff --git a/plugins/azure/keyvaults/keyVaultKeyExpiryNonRbac.spec.js b/plugins/azure/keyvaults/keyVaultKeyExpiryNonRbac.spec.js index 43ed0ab134..dd251b487d 100644 --- a/plugins/azure/keyvaults/keyVaultKeyExpiryNonRbac.spec.js +++ b/plugins/azure/keyvaults/keyVaultKeyExpiryNonRbac.spec.js @@ -171,5 +171,18 @@ describe('keyVaultKeyExpiryNonRbac', function() { auth.run(createCache(null, [listKeyVaults[0]], [getKeys[2]]), { key_vault_key_expiry_fail: '40' }, callback); }); + + it('should give passing result if Key Vault public network access is disabled', function(done) { + const disabledVault = Object.assign({}, listKeyVaults[0], { publicNetworkAccess: 'Disabled' }); + const callback = (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Key Vault public network access is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [disabledVault], []), {}, callback); + }); }); }); diff --git a/plugins/azure/keyvaults/keyVaultSecretExpiry.js b/plugins/azure/keyvaults/keyVaultSecretExpiry.js index 2dd31788d5..4808779bf5 100644 --- a/plugins/azure/keyvaults/keyVaultSecretExpiry.js +++ b/plugins/azure/keyvaults/keyVaultSecretExpiry.js @@ -51,6 +51,14 @@ module.exports = { return; } + if (vault.publicNetworkAccess && + vault.publicNetworkAccess.toLowerCase() === 'disabled') { + helpers.addResult(results, 0, + 'Key Vault public network access is disabled; unable to query Key Vault secrets', + location, vault.id); + return; + } + var secrets = helpers.addSource(cache, source, ['vaults', 'getSecrets', location, vault.id]); diff --git a/plugins/azure/keyvaults/keyVaultSecretExpiry.spec.js b/plugins/azure/keyvaults/keyVaultSecretExpiry.spec.js index 4bf693b9e5..49f648c75b 100644 --- a/plugins/azure/keyvaults/keyVaultSecretExpiry.spec.js +++ b/plugins/azure/keyvaults/keyVaultSecretExpiry.spec.js @@ -214,5 +214,18 @@ describe('keyVaultSecretExpiry', function() { auth.run(createCache(null, [listKeyVaults[0]], getSecrets[4]), {}, callback); }); + + it('should give passing result if Key Vault public network access is disabled', function(done) { + const disabledVault = Object.assign({}, listKeyVaults[0], { publicNetworkAccess: 'Disabled' }); + const callback = (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Key Vault public network access is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [disabledVault], {}), {}, callback); + }); }) }); diff --git a/plugins/azure/keyvaults/keyVaultSecretExpiryNonRbac.js b/plugins/azure/keyvaults/keyVaultSecretExpiryNonRbac.js index e2f8a15fd1..3ca75050a1 100644 --- a/plugins/azure/keyvaults/keyVaultSecretExpiryNonRbac.js +++ b/plugins/azure/keyvaults/keyVaultSecretExpiryNonRbac.js @@ -51,6 +51,14 @@ module.exports = { return; } + if (vault.publicNetworkAccess && + vault.publicNetworkAccess.toLowerCase() === 'disabled') { + helpers.addResult(results, 0, + 'Key Vault public network access is disabled; unable to query Key Vault secrets', + location, vault.id); + return; + } + var secrets = helpers.addSource(cache, source, ['vaults', 'getSecrets', location, vault.id]); diff --git a/plugins/azure/keyvaults/keyVaultSecretExpiryNonRbac.spec.js b/plugins/azure/keyvaults/keyVaultSecretExpiryNonRbac.spec.js index 2a64720d2e..db9229a896 100644 --- a/plugins/azure/keyvaults/keyVaultSecretExpiryNonRbac.spec.js +++ b/plugins/azure/keyvaults/keyVaultSecretExpiryNonRbac.spec.js @@ -217,5 +217,18 @@ describe('keyVaultSecretExpiryNonRbac', function() { auth.run(createCache(null, [listKeyVaults[0]], getSecrets[4]), {}, callback); }); + + it('should give passing result if Key Vault public network access is disabled', function(done) { + const disabledVault = Object.assign({}, listKeyVaults[0], { publicNetworkAccess: 'Disabled' }); + const callback = (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Key Vault public network access is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [disabledVault], {}), {}, callback); + }); }) }); diff --git a/plugins/azure/monitor/logProfileArchiveData.js b/plugins/azure/monitor/logProfileArchiveData.js index 35d5dd789b..c689d31100 100644 --- a/plugins/azure/monitor/logProfileArchiveData.js +++ b/plugins/azure/monitor/logProfileArchiveData.js @@ -6,11 +6,12 @@ module.exports = { category: 'Monitor', domain: 'Management and Governance', severity: 'Low', - description: 'Ensures the Log Profile is configured to export all activities from the control and management planes in all active locations', + description: 'Ensures the Log Profile is configured to export all activities a storage account', more_info: 'Exporting log activity for control plane activity allows for audited access to the Azure account with event data in the case of a security incident.', - recommended_action: 'Ensure that all activity is logged to the Event Hub or storage account for archiving.' , + recommended_action: 'Ensure that all activity is logged to a storage account for archiving.' , link: 'https://learn.microsoft.com/en-us/azure/azure-monitor/platform/archive-activity-log', - apis: ['logProfiles:list'], + apis: ['diagnosticSettingsOperations:list'], + realtime_triggers: ['microsoftinsights:diagnosticsettings:write', 'microsoftinsights:diagnosticsettings:delete'], compliance: { hipaa: 'HIPAA has clearly defined audit requirements for environments ' + 'containing sensitive data. Log Profiles are the recommended ' + @@ -25,61 +26,34 @@ module.exports = { const source = {}; const locations = helpers.locations(settings.govcloud); - async.each(locations.logProfiles, (location, rcb) => { - const logProfiles = helpers.addSource(cache, source, - ['logProfiles', 'list', location]); + async.each(locations.diagnosticSettingsOperations, (location, rcb) => { + const diagnosticSettings = helpers.addSource(cache, source, + ['diagnosticSettingsOperations', 'list', location]); - if (!logProfiles) return rcb(); + if (!diagnosticSettings) return rcb(); - if (logProfiles.err || !logProfiles.data) { + if (diagnosticSettings.err || !diagnosticSettings.data) { helpers.addResult(results, 3, - 'Unable to query for Log Profiles: ' + helpers.addError(logProfiles), location); + 'Unable to query for Diagnostic Settings: ' + helpers.addError(diagnosticSettings), location); return rcb(); } - if (!logProfiles.data.length) { - helpers.addResult(results, 2, 'No existing Log Profiles found', location); + if (!diagnosticSettings.data.length) { + helpers.addResult(results, 2, 'No existing Diagnostic Settings found', location); return rcb(); } - logProfiles.data.forEach(function(logProfile){ - var issues = []; - if (logProfile.locations && logProfile.locations.length) { - var unmatchedRegions = []; - locations.all.forEach(function(region){ - if (region !== 'global' && logProfile.locations.indexOf(region) === -1) { - unmatchedRegions.push(region); - } - }); - if (unmatchedRegions.length) { - issues.push('the following regions are not being monitored: ' + unmatchedRegions.join(', ')); - } - } else { - issues.push('no regions are being monitored'); - } + const archivingSetting = diagnosticSettings.data.find(s => + s.storageAccountId && s.storageAccountId.length && + s.logs && s.logs.some(log => log.enabled)); - if (logProfile.categories && logProfile.categories.length) { - var unmatchedCats = []; - ['Write', 'Delete', 'Action'].forEach(function(cat){ - if (logProfile.categories.indexOf(cat) === -1) { - unmatchedCats.push(cat); - } - }); - if (unmatchedCats.length) { - issues.push('the following categories are not being monitored: ' + unmatchedCats.join(', ')); - } - } else { - issues.push('no log categories are being monitored'); - } - - if (issues.length) { - helpers.addResult(results, 2, - 'Log Profile has the following issues: ' + issues.join('; '), location, logProfile.id); - } else { - helpers.addResult(results, 0, - 'Log Profile is archiving all activities in all regions.', location, logProfile.id); - } - }); + if (archivingSetting) { + helpers.addResult(results, 0, + 'Diagnostic Setting is archiving Activity Logs to a storage account.', location, archivingSetting.id); + } else { + helpers.addResult(results, 2, + 'No Diagnostic Setting is archiving Activity Logs to a storage account.', location); + } rcb(); }, function() { diff --git a/plugins/azure/monitor/logProfileArchiveData.spec.js b/plugins/azure/monitor/logProfileArchiveData.spec.js index e3cc5158aa..7d4549584a 100644 --- a/plugins/azure/monitor/logProfileArchiveData.spec.js +++ b/plugins/azure/monitor/logProfileArchiveData.spec.js @@ -1,107 +1,50 @@ var expect = require('chai').expect; var logProfileArchiveData = require('./logProfileArchiveData'); -const logProfile = [ +const diagnosticSettings = [ { - "id": "/subscriptions/1234/providers/microsoft.insights/logprofiles/test", - "type": null, - "name": "default", - "location": null, - "kind": null, - "tags": null, - "identity": null, - "storageAccountId": "/subscriptions/1234/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.Storage/storageAccounts/devstoragetwo", - "serviceBusRuleId": null, - "locations": [ - "australiacentral", - "australiacentral2", - "australiaeast", - "australiasoutheast", - "brazilsouth", - "canadacentral", - "canadaeast", - "centralindia", - "centralus", - "eastasia", - "eastus", - "eastus2", - "francecentral", - "francesouth", - "japaneast", - "japanwest", - "koreacentral", - "koreasouth", - "northcentralus", - "northeurope", - "southafricanorth", - "southafricawest", - "southcentralus", - "southindia", - "southeastasia", - "uaecentral", - "uaenorth", - "uksouth", - "ukwest", - "westcentralus", - "westeurope", - "westindia", - "westus", - "westus2", - "westus3", - "eastus2euap", - "centraluseuap", - "jioindiawest", - "jioindiacentral", - "swedencentral", - "germanywestcentral", - "germanycentral", - "germanynortheast", - "germanynorth", - "norwayeast", - "switzerlandnorth", - "norwaywest", - "switzerlandwest", - "brazilsoutheast", - "global", - "qatarcentral", - "polandcentral", - "italynorth", - "israelcentral" - ], - "categories": [ - "Write", - "Delete", - "Action" - ], - "retentionPolicy": { - "enabled": true, - "days": 82 - } + 'id': '/subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting', + 'type': 'Microsoft.Insights/diagnosticSettings', + 'name': 'test-setting', + 'location': 'global', + 'storageAccountId': '/subscriptions/123/resourceGroups/devresourcegroup/providers/Microsoft.Storage/storageAccounts/test-storage-account', + 'logs': [ + { 'category': 'Administrative', 'enabled': true }, + { 'category': 'Security', 'enabled': true } + ] }, { - "id": "/subscriptions/1234/providers/microsoft.insights/logprofiles/default", - "type": null, - "name": "default", - "location": null, - "kind": null, - "tags": null, - "identity": null, - "storageAccountId": "/subscriptions/1234/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.Storage/storageAccounts/devstoragetwo", - "serviceBusRuleId": null, - "retentionPolicy": { - "enabled": true, - "days": 82 - } + 'id': '/subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting-eventhub', + 'type': 'Microsoft.Insights/diagnosticSettings', + 'name': 'test-setting-eventhub', + 'location': 'global', + 'eventHubAuthorizationRuleId': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.EventHub/namespaces/test-setting/authorizationrules/RootManageSharedAccessKey', + 'eventHubName': '', + 'logs': [ + { 'category': 'Administrative', 'enabled': true }, + { 'category': 'Security', 'enabled': true } + ] + }, + { + 'id': '/subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting-disabled', + 'type': 'Microsoft.Insights/diagnosticSettings', + 'name': 'test-setting-disabled', + 'location': 'global', + 'storageAccountId': '/subscriptions/123/resourceGroups/devresourcegroup/providers/Microsoft.Storage/storageAccounts/test-storage-account', + 'logs': [ + { 'category': 'Administrative', 'enabled': false }, + { 'category': 'Security', 'enabled': false } + ] } ]; -const createCache = (logProfile) => { +const createCache = (diagnosticSettings) => { let settings = {}; - if (logProfile) { - settings['data'] = logProfile; + if (diagnosticSettings) { + settings['data'] = diagnosticSettings; } return { - logProfiles: { + diagnosticSettingsOperations: { list: { 'global': settings } @@ -111,45 +54,56 @@ const createCache = (logProfile) => { describe('logProfileArchiveData', function() { describe('run', function() { - it('should give passing result if No existing Log Profiles found', function(done) { + it('should give failing result if no diagnostic settings found', function(done) { const cache = createCache([]); logProfileArchiveData.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('No existing Log Profiles found'); + expect(results[0].message).to.include('No existing Diagnostic Settings found'); expect(results[0].region).to.equal('global'); done(); }); }); - it('should give unknown result if Unable to query for Log Profiles', function(done) { + it('should give unknown result if unable to query for diagnostic settings', function(done) { const cache = createCache(); logProfileArchiveData.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(3); - expect(results[0].message).to.include('Unable to query for Log Profiles'); + expect(results[0].message).to.include('Unable to query for Diagnostic Settings'); expect(results[0].region).to.equal('global'); done(); }); }); - it('should give passing result if Log Profile is archiving all activities in all regions', function(done) { - const cache = createCache([logProfile[0]]); + it('should give passing result if a diagnostic setting archives activity logs to a storage account', function(done) { + const cache = createCache([diagnosticSettings[0]]); logProfileArchiveData.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('Log Profile is archiving all activities in all regions'); + expect(results[0].message).to.include('Diagnostic Setting is archiving Activity Logs to a storage account'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give failing result if no diagnostic setting archives activity logs to a storage account', function(done) { + const cache = createCache([diagnosticSettings[1]]); + logProfileArchiveData.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('No Diagnostic Setting is archiving Activity Logs to a storage account'); expect(results[0].region).to.equal('global'); done(); }); }); - it('should give failing result if Log Profile has the following issues', function(done) { - const cache = createCache([logProfile[1]]); + it('should give failing result if diagnostic setting has a storage account but no enabled logs', function(done) { + const cache = createCache([diagnosticSettings[2]]); logProfileArchiveData.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('Log Profile has the following issues'); + expect(results[0].message).to.include('No Diagnostic Setting is archiving Activity Logs to a storage account'); expect(results[0].region).to.equal('global'); done(); }); diff --git a/plugins/azure/monitor/monitorResourceSku.js b/plugins/azure/monitor/monitorResourceSku.js index 7cbf7fe898..2c64a734d2 100644 --- a/plugins/azure/monitor/monitorResourceSku.js +++ b/plugins/azure/monitor/monitorResourceSku.js @@ -36,7 +36,10 @@ module.exports = { for (let resource of resources.data) { if (!resource.id || !resource.sku) continue; - + + if (resource.type && + resource.type.toLowerCase() === 'microsoft.machinelearningservices/workspaces') continue; + if (resource.sku && resource.sku.name && (resource.sku.name.toLowerCase() === 'basic' ||resource.sku.name.toLowerCase() === 'consumption')){ helpers.addResult(results, 2, `Resource is using ${resource.sku.name} SKU`, location, resource.id); } else { diff --git a/plugins/azure/monitor/monitorResourceSku.spec.js b/plugins/azure/monitor/monitorResourceSku.spec.js index 5f1fffe5d1..bbcfa61441 100644 --- a/plugins/azure/monitor/monitorResourceSku.spec.js +++ b/plugins/azure/monitor/monitorResourceSku.spec.js @@ -18,6 +18,13 @@ const resources = [ kind: 'StorageV2', location: 'eastus', }, + { + id: '/subscriptions/123/resourceGroups/devresourcegroup/providers/Microsoft.MachineLearningServices/workspaces/test-ml-workspace', + name: 'test-ml-workspace', + type: 'Microsoft.MachineLearningServices/workspaces', + sku: { name: 'Basic', tier: 'Basic' }, + location: 'eastus', + }, ]; const createCache = (resource) => { @@ -76,5 +83,13 @@ describe('resourceAppropriateSKU', function() { done(); }); }); + + it('should skip Machine Learning workspaces that only support Basic SKU', function(done) { + const cache = createCache([resources[2]]); + resourceAppropriateSKU.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); }); }); diff --git a/plugins/azure/openai/accountCMKEncrypted.js b/plugins/azure/openai/accountCMKEncrypted.js index 82e68a978d..858576bb2b 100644 --- a/plugins/azure/openai/accountCMKEncrypted.js +++ b/plugins/azure/openai/accountCMKEncrypted.js @@ -37,9 +37,13 @@ module.exports = { for (let account of accounts.data) { - if (account.properties && account.properties.encryption && - account.properties.encryption.keySource && - account.properties.encryption.keySource.toLowerCase() == 'microsoft.keyvault') { + if (!account.id) continue; + + if (!account.kind || account.kind.toLowerCase() !== 'openai') continue; + + if (account.encryption && + account.encryption.keySource && + account.encryption.keySource.toLowerCase() == 'microsoft.keyvault') { helpers.addResult(results, 0, 'OpenAI Account is encrypted using CMK', location, account.id); } else { diff --git a/plugins/azure/openai/accountCMKEncrypted.spec.js b/plugins/azure/openai/accountCMKEncrypted.spec.js index 954c7f4432..d4fa76922a 100644 --- a/plugins/azure/openai/accountCMKEncrypted.spec.js +++ b/plugins/azure/openai/accountCMKEncrypted.spec.js @@ -5,17 +5,17 @@ const accounts = [ { "id": "/subscriptions/12424/resourceGroups/bvttest/providers/Microsoft.CognitiveServices/accounts/acc1", "name": "acc1", + "kind": "OpenAI", "type": "Microsoft.CognitiveServices/accounts", "location": "eastus", - "properties": { - "encryption": { - 'keySource': 'Microsoft.Keyvault' - } + "encryption": { + 'keySource': 'Microsoft.Keyvault' } }, { "id": "/subscriptions/12424/resourceGroups/bvttest/providers/Microsoft.CognitiveServices/accounts/acc2", "name": "acc2", + "kind": "OpenAI", "type": "Microsoft.CognitiveServices/accounts", "location": "eastus" }, @@ -56,6 +56,7 @@ describe('accountCMKEncrypted', function() { expect(results[0].region).to.equal('eastus'); done(); }); + }); it('should give unknown result if unable to query for openai accounts', function(done) { diff --git a/plugins/azure/openai/accountDiagnosticLogging.js b/plugins/azure/openai/accountDiagnosticLogging.js index d6667f3d04..d461327cbc 100644 --- a/plugins/azure/openai/accountDiagnosticLogging.js +++ b/plugins/azure/openai/accountDiagnosticLogging.js @@ -37,6 +37,9 @@ module.exports = { for (let account of accounts.data) { if (!account.id) continue; + + if (!account.kind || account.kind.toLowerCase() !== 'openai') continue; + var diagnosticSettings = helpers.addSource(cache, source, ['diagnosticSettings', 'listByOpenAIAccounts', location, account.id]); diff --git a/plugins/azure/openai/accountDiagnosticLogging.spec.js b/plugins/azure/openai/accountDiagnosticLogging.spec.js index e0b826c759..16961e464f 100644 --- a/plugins/azure/openai/accountDiagnosticLogging.spec.js +++ b/plugins/azure/openai/accountDiagnosticLogging.spec.js @@ -5,17 +5,17 @@ const accounts = [ { "id": "/subscriptions/12424/resourceGroups/bvttest/providers/Microsoft.CognitiveServices/accounts/acc1", "name": "acc1", + "kind": "OpenAI", "type": "Microsoft.CognitiveServices/accounts", "location": "eastus", - "properties": { - "encryption": { - 'keySource': 'Microsoft.Keyvault' - } + "encryption": { + 'keySource': 'Microsoft.Keyvault' } }, { "id": "/subscriptions/12424/resourceGroups/bvttest/providers/Microsoft.CognitiveServices/accounts/acc2", "name": "acc2", + "kind": "OpenAI", "type": "Microsoft.CognitiveServices/accounts", "location": "eastus" }, diff --git a/plugins/azure/openai/accountHasTags.js b/plugins/azure/openai/accountHasTags.js index fd989a37da..97a085c0ca 100644 --- a/plugins/azure/openai/accountHasTags.js +++ b/plugins/azure/openai/accountHasTags.js @@ -37,6 +37,10 @@ module.exports = { for (let account of accounts.data) { + if (!account.id) continue; + + if (!account.kind || account.kind.toLowerCase() !== 'openai') continue; + if (account.tags && Object.entries(account.tags).length > 0) { helpers.addResult(results, 0, 'OpenAI Account has tags associated', location, account.id); diff --git a/plugins/azure/openai/accountHasTags.spec.js b/plugins/azure/openai/accountHasTags.spec.js index 5d0327f0d0..31940c80a4 100644 --- a/plugins/azure/openai/accountHasTags.spec.js +++ b/plugins/azure/openai/accountHasTags.spec.js @@ -5,6 +5,7 @@ const accounts = [ { "id": "/subscriptions/12424/resourceGroups/bvttest/providers/Microsoft.CognitiveServices/accounts/acc1", "name": "acc1", + "kind": "OpenAI", "type": "Microsoft.CognitiveServices/accounts", "location": "eastus", "tags": { @@ -14,6 +15,7 @@ const accounts = [ { "id": "/subscriptions/12424/resourceGroups/bvttest/providers/Microsoft.CognitiveServices/accounts/acc2", "name": "acc2", + "kind": "OpenAI", "type": "Microsoft.CognitiveServices/accounts", "location": "eastus" }, diff --git a/plugins/azure/openai/accountManagedIdentity.js b/plugins/azure/openai/accountManagedIdentity.js index a1c4ca4189..32e9799546 100644 --- a/plugins/azure/openai/accountManagedIdentity.js +++ b/plugins/azure/openai/accountManagedIdentity.js @@ -37,6 +37,10 @@ module.exports = { for (let account of accounts.data) { + if (!account.id) continue; + + if (!account.kind || account.kind.toLowerCase() !== 'openai') continue; + if (account.identity && account.identity.type && (account.identity.type.toLowerCase() === 'systemassigned' || account.identity.type.toLowerCase() === 'userassigned')) { helpers.addResult(results, 0, diff --git a/plugins/azure/openai/accountManagedIdentity.spec.js b/plugins/azure/openai/accountManagedIdentity.spec.js index 84640d92a0..7e02196f6d 100644 --- a/plugins/azure/openai/accountManagedIdentity.spec.js +++ b/plugins/azure/openai/accountManagedIdentity.spec.js @@ -5,6 +5,7 @@ const accounts = [ { "id": "/subscriptions/12424/resourceGroups/bvttest/providers/Microsoft.CognitiveServices/accounts/acc1", "name": "acc1", + "kind": "OpenAI", "type": "Microsoft.CognitiveServices/accounts", "location": "eastus", "identity": { @@ -16,6 +17,7 @@ const accounts = [ { "id": "/subscriptions/12424/resourceGroups/bvttest/providers/Microsoft.CognitiveServices/accounts/acc2", "name": "acc2", + "kind": "OpenAI", "type": "Microsoft.CognitiveServices/accounts", "location": "eastus" }, diff --git a/plugins/azure/openai/accountPublicAccessDisabled.js b/plugins/azure/openai/accountPublicAccessDisabled.js index f050f6fca8..b7f66e2352 100644 --- a/plugins/azure/openai/accountPublicAccessDisabled.js +++ b/plugins/azure/openai/accountPublicAccessDisabled.js @@ -39,6 +39,8 @@ module.exports = { if (!account.id) continue; + if (!account.kind || account.kind.toLowerCase() !== 'openai') continue; + const publicAccess = account.publicNetworkAccess && account.publicNetworkAccess.toLowerCase(); if (publicAccess === 'disabled') { diff --git a/plugins/azure/openai/accountPublicAccessDisabled.spec.js b/plugins/azure/openai/accountPublicAccessDisabled.spec.js index 1c580dd606..2629bb485a 100644 --- a/plugins/azure/openai/accountPublicAccessDisabled.spec.js +++ b/plugins/azure/openai/accountPublicAccessDisabled.spec.js @@ -5,6 +5,7 @@ const accounts = [ { "id": "/subscriptions/12424/resourceGroups/bvttest/providers/Microsoft.CognitiveServices/accounts/acc1", "name": "acc1", + "kind": "OpenAI", "type": "Microsoft.CognitiveServices/accounts", "location": "eastus", "publicNetworkAccess": 'Disabled' @@ -12,6 +13,7 @@ const accounts = [ { "id": "/subscriptions/12424/resourceGroups/bvttest/providers/Microsoft.CognitiveServices/accounts/acc2", "name": "acc2", + "kind": "OpenAI", "type": "Microsoft.CognitiveServices/accounts", "location": "eastus", "publicNetworkAccess": 'Enabled' @@ -19,6 +21,7 @@ const accounts = [ { "id": "/subscriptions/12424/resourceGroups/bvttest/providers/Microsoft.CognitiveServices/accounts/acc4", "name": "acc4", + "kind": "OpenAI", "type": "Microsoft.CognitiveServices/accounts", "location": "eastus", "publicNetworkAccess": 'Enabled', @@ -30,6 +33,7 @@ const accounts = [ { "id": "/subscriptions/12424/resourceGroups/bvttest/providers/Microsoft.CognitiveServices/accounts/acc5", "name": "acc5", + "kind": "OpenAI", "type": "Microsoft.CognitiveServices/accounts", "location": "eastus", "publicNetworkAccess": 'Enabled', diff --git a/plugins/azure/queueservice/queueServiceAllAccessAcl.js b/plugins/azure/queueservice/queueServiceAllAccessAcl.js index cd47a4258b..afb69359e7 100755 --- a/plugins/azure/queueservice/queueServiceAllAccessAcl.js +++ b/plugins/azure/queueservice/queueServiceAllAccessAcl.js @@ -42,6 +42,14 @@ module.exports = { } storageAccounts.data.forEach(function(storageAccount) { + if (storageAccount.publicNetworkAccess && + storageAccount.publicNetworkAccess.toLowerCase() === 'disabled') { + helpers.addResult(results, 0, + 'Storage account public network access is disabled; Queue Service is not accessible', + location, storageAccount.id); + return; + } + // Attempt to list keys to see if future calls will succeed var listKeys = helpers.addSource(cache, source, ['storageAccounts', 'listKeys', location, storageAccount.id]); diff --git a/plugins/azure/queueservice/queueServiceAllAccessAcl.spec.js b/plugins/azure/queueservice/queueServiceAllAccessAcl.spec.js index a5aed8a83d..dcbd735708 100644 --- a/plugins/azure/queueservice/queueServiceAllAccessAcl.spec.js +++ b/plugins/azure/queueservice/queueServiceAllAccessAcl.spec.js @@ -81,9 +81,7 @@ const createCache = (list, listKeys, segments, acl, keysErr) => { queueService: { listQueuesSegmented: { 'eastus': { - [id]: { - data: segments - } + [id]: { data: segments } } }, getQueueAcl: { @@ -200,6 +198,16 @@ describe('queueServiceAllAccessAcl', function () { done(); }); }); + + it('should PASS if storage account public network access is disabled', function (done) { + const disabledAccount = Object.assign({}, storageAccounts[0], { publicNetworkAccess: 'Disabled' }); + const cache = createCache([disabledAccount], listKeys); + queueServiceAllAccessAcl.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); }); }); diff --git a/plugins/azure/storageaccounts/storageAccountPublicNetworkAccess.js b/plugins/azure/storageaccounts/storageAccountPublicNetworkAccess.js index 5770073488..a37da632af 100644 --- a/plugins/azure/storageaccounts/storageAccountPublicNetworkAccess.js +++ b/plugins/azure/storageaccounts/storageAccountPublicNetworkAccess.js @@ -55,9 +55,13 @@ module.exports = { } const restricted = account.networkAcls && account.networkAcls.defaultAction && account.networkAcls.defaultAction.toLowerCase() === 'deny'; + + const hasVirtualNetworks = account.networkAcls && account.networkAcls.virtualNetworkRules && account.networkAcls.virtualNetworkRules.length > 0; if ( restricted && !hasOpenCidr) { helpers.addResult(results, 0, 'Storage account has public network access disabled', location, account.id); + } else if (hasVirtualNetworks) { + helpers.addResult(results, 0, 'Storage account has public network access disabled', location, account.id); } else { helpers.addResult(results, 2, 'Storage account has public network access enabled for all networks', location, account.id); } diff --git a/plugins/azure/tableservice/tableServiceAllAccessAcl.js b/plugins/azure/tableservice/tableServiceAllAccessAcl.js index 7a3116f46f..8dabc57799 100644 --- a/plugins/azure/tableservice/tableServiceAllAccessAcl.js +++ b/plugins/azure/tableservice/tableServiceAllAccessAcl.js @@ -42,6 +42,14 @@ module.exports = { } storageAccounts.data.forEach(function(storageAccount) { + if (storageAccount.publicNetworkAccess && + storageAccount.publicNetworkAccess.toLowerCase() === 'disabled') { + helpers.addResult(results, 0, + 'Storage account public network access is disabled; Table Service is not accessible', + location, storageAccount.id); + return; + } + // Attempt to list keys to see if future calls will succeed var listKeys = helpers.addSource(cache, source, ['storageAccounts', 'listKeys', location, storageAccount.id]); diff --git a/plugins/azure/tableservice/tableServiceAllAccessAcl.spec.js b/plugins/azure/tableservice/tableServiceAllAccessAcl.spec.js index 367abc072b..f20c47948e 100644 --- a/plugins/azure/tableservice/tableServiceAllAccessAcl.spec.js +++ b/plugins/azure/tableservice/tableServiceAllAccessAcl.spec.js @@ -81,9 +81,7 @@ const createCache = (list, listKeys, segments, acl, keysErr) => { tableService: { listTablesSegmented: { 'eastus': { - [id]: { - data: segments - } + [id]: { data: segments } } }, getTableAcl: { @@ -200,5 +198,15 @@ describe('tableServiceAllAccessAcl', function () { done(); }); }); + + it('should PASS if storage account public network access is disabled', function (done) { + const disabledAccount = Object.assign({}, storageAccounts[0], { publicNetworkAccess: 'Disabled' }); + const cache = createCache([disabledAccount], listKeys); + tableServiceAllAccessAcl.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); }); }); \ No newline at end of file From c8b1d97b185e57e140a5de0d51f18e3f8430dfed Mon Sep 17 00:00:00 2001 From: fatimaaqua Date: Mon, 31 Aug 2026 10:10:43 +0000 Subject: [PATCH 2/3] added missing package --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 741c0ba80f..3ef70b837f 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ }, "dependencies": { "@alicloud/pop-core": "^1.7.10", + "@aws-sdk/client-ec2": "^3.876.0", "@azure/data-tables": "^13.2.2", "@azure/storage-file-share": "^12.14.0", "@azure/storage-queue": "^12.13.0", From 47e0c7ab21f58d59ff30c8697979554f10c80563 Mon Sep 17 00:00:00 2001 From: fatimaaqua Date: Mon, 31 Aug 2026 10:18:48 +0000 Subject: [PATCH 3/3] added missing package --- .github/workflows/scans_ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/scans_ci.yml b/.github/workflows/scans_ci.yml index 52815e2347..b6a49d6366 100644 --- a/.github/workflows/scans_ci.yml +++ b/.github/workflows/scans_ci.yml @@ -8,9 +8,9 @@ jobs: steps: - uses: actions/checkout@v2 - name: Use Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v4 with: - node-version: '12.x' + node-version: '20.x' - uses: codespell-project/actions-codespell@master with: check_filenames: true