From 6014298d30319ca19d055e30669eaddd8a21a7fb Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Wed, 12 Jun 2024 21:42:19 +0500 Subject: [PATCH 01/91] Plugin Batch Account Managed Identity --- exports.js | 1 + .../batchAccountsManagedIdentity.js | 52 ++++++++++ .../batchAccountsManagedIdentity.spec.js | 98 +++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 plugins/azure/batchAccounts/batchAccountsManagedIdentity.js create mode 100644 plugins/azure/batchAccounts/batchAccountsManagedIdentity.spec.js diff --git a/exports.js b/exports.js index 9ca097916d..11a34840ec 100644 --- a/exports.js +++ b/exports.js @@ -1181,6 +1181,7 @@ module.exports = { 'batchAccountCmkEncrypted' : require(__dirname + '/plugins/azure/batchAccounts/batchAccountCmkEncrypted.js'), 'batchAccountDiagnosticLogs' : require(__dirname + '/plugins/azure/batchAccounts/batchAccountDiagnosticLogs.js'), + 'batchAccountsManagedIdentity' : require(__dirname + '/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js'), 'accountCMKEncrypted' : require(__dirname + '/plugins/azure/openai/accountCMKEncrypted.js'), 'accountManagedIdentity' : require(__dirname + '/plugins/azure/openai/accountManagedIdentity.js'), diff --git a/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js b/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js new file mode 100644 index 0000000000..d479729f4b --- /dev/null +++ b/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js @@ -0,0 +1,52 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure/'); + +module.exports = { + title: 'Batch Account Managed Identity', + category: 'Batch', + domain: 'Compute', + severity: 'Medium', + description: 'Ensures that Batch account have managed identity enabled.', + more_info: 'Enabling managed identities eliminate the need for developers having to manage credentials by providing an identity for the Azure resource in Azure AD and using it to obtain Azure Active Directory (Azure AD) tokens.', + recommended_action: 'Modify Batch Account and enable managed identity.', + link: 'https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools', + apis: ['batchAccounts:list'], + realtime_triggers: ['microsoftbatch:batchaccounts:write','microsoftbatch:batchaccounts:delete'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.batchAccounts, function(location, rcb){ + + var batchAccounts = helpers.addSource(cache, source, + ['batchAccounts', 'list', location]); + + if (!batchAccounts) return rcb(); + + if (batchAccounts.err || !batchAccounts.data) { + helpers.addResult(results, 3, 'Unable to query for Batch accounts: ' + helpers.addError(batchAccounts), location); + return rcb(); + } + if (!batchAccounts.data.length) { + helpers.addResult(results, 0, 'No existing Batch accounts found', location); + return rcb(); + } + + for (let batchAccount of batchAccounts.data) { + if (!batchAccount.id) continue; + + if (batchAccount.identity) { + helpers.addResult(results, 0, 'Batch account has managed identity enabled', location, batchAccount.id); + } else { + helpers.addResult(results, 2, 'Batch account does not have managed identity enabled', location, batchAccount.id); + } + } + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/batchAccounts/batchAccountsManagedIdentity.spec.js b/plugins/azure/batchAccounts/batchAccountsManagedIdentity.spec.js new file mode 100644 index 0000000000..a3770ee089 --- /dev/null +++ b/plugins/azure/batchAccounts/batchAccountsManagedIdentity.spec.js @@ -0,0 +1,98 @@ + +var expect = require('chai').expect; +var batchAccountsManagedIdentity = require('./batchAccountsManagedIdentity'); + +const batchAccounts = [ + { + "id": "/subscriptions/1234566/resourceGroups/dummy/providers/Microsoft.Batch/batchAccounts/test", + "name": "test", + "type": "Microsoft.Batch/batchAccounts", + "location": "eastus", + "accountEndpoint": "test.eastus.batch.azure.com", + "nodeManagementEndpoint": "123456789.eastus.service.batch.azure.com", + "identity": { + "principalId": "6bb43e0b-f260-4a69-ba3b-853b14451327", + "tenantId": "d207c7bd-fcb1-4dd3-855a-cfd2f9b651e8", + "type": "SystemAssigned", + } + }, + { + "id": "/subscriptions/1234566/resourceGroups/dummy/providers/Microsoft.Batch/batchAccounts/test", + "name": "test", + "type": "Microsoft.Batch/batchAccounts", + "location": "eastus", + "accountEndpoint": "test.eastus.batch.azure.com", + "nodeManagementEndpoint": "123456789.eastus.service.batch.azure.com", + }, +]; + +const createCache = (batchAccounts) => { + return { + batchAccounts: { + list: { + 'eastus': { + data: batchAccounts + } + } + } + } +}; + +const createErrorCache = () => { + return { + batchAccounts: { + list: { + 'eastus': {} + } + } + }; +}; + +describe('batchAccountsManagedIdentity', function () { + describe('run', function () { + + it('should give unknown result if unable to query for Batch accounts:', function (done) { + const cache = createCache(null); + batchAccountsManagedIdentity.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 Batch accounts:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if no Batch account exist', function (done) { + const cache = createCache([]); + batchAccountsManagedIdentity.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No existing Batch accounts found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if Batch account has managed identity enabled', function (done) { + const cache = createCache([batchAccounts[0]]); + batchAccountsManagedIdentity.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Batch account has managed identity enabled'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if Batch account does not have managed identity enabled', function (done) { + const cache = createCache([batchAccounts[1]]); + batchAccountsManagedIdentity.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Batch account does not have managed identity enabled'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file From b279957f4b0745504ec3b39122dd98560170b737 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 13 Jun 2024 03:02:11 +0500 Subject: [PATCH 02/91] DocDB Cluster Instance Certificate Rotated --- exports.js | 1 + .../aws/documentDB/docdbCertificateRotated.js | 77 ++++++++++++ .../docdbCertificateRotated.spec.js | 112 ++++++++++++++++++ 3 files changed, 190 insertions(+) create mode 100644 plugins/aws/documentDB/docdbCertificateRotated.js create mode 100644 plugins/aws/documentDB/docdbCertificateRotated.spec.js diff --git a/exports.js b/exports.js index 9ca097916d..f92c69e977 100644 --- a/exports.js +++ b/exports.js @@ -635,6 +635,7 @@ module.exports = { 'docDbHasTags' : require(__dirname + '/plugins/aws/documentDB/docDbHasTags.js'), 'docdbDeletionProtectionEnabled': require(__dirname + '/plugins/aws/documentDB/docdbDeletionProtectionEnabled.js'), 'docdbClusterBackupRetention' : require(__dirname + '/plugins/aws/documentDB/docdbClusterBackupRetention.js'), + 'docdbCertificateRotated' : require(__dirname + '/plugins/aws/documentDB/docdbCertificateRotated.js'), 'instanceMediaStreamsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceMediaStreamsEncrypted.js'), 'instanceTranscriptsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceTranscriptsEncrypted.js'), diff --git a/plugins/aws/documentDB/docdbCertificateRotated.js b/plugins/aws/documentDB/docdbCertificateRotated.js new file mode 100644 index 0000000000..9f32c14406 --- /dev/null +++ b/plugins/aws/documentDB/docdbCertificateRotated.js @@ -0,0 +1,77 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'DocumentDB Cluster Instance Certificate Rotation', + category: 'DocumentDB', + domain: 'Databases', + severity: 'High', + description: 'Ensure that AWS DocumentDB cluster instance certificates are rotated.', + more_info: 'Enabling the AWS DocumentDB cluster certificate rotation ensures that your cluster\'s TLS certificates are automatically rotated to maintain security and compliance standards. This feature helps in seamlessly updating certificates without downtime, ensuring continuous protection for data in transit within the DocumentDB cluster.', + recommended_action: 'Modify DocumentDB cluster instance and rotate the old server certificate.', + link: 'https://docs.aws.amazon.com/documentdb/latest/developerguide/ca_cert_rotation.html', + apis: ['RDS:describeDBInstances'], + settings: { + docdb_certificate_rotation_limit: { + name: 'Certificate Rotation Limit', + description: 'Number of days before expiration date when certificate should be rotated', + regex: '^[0-9]*$', + default: '30', + } + }, + realtime_triggers: ['docdb:CreateDBInstance','docdb:DeleteDBInstance', 'docdb:ModifyDBInstance'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + var docdb_certificate_rotation_limit = parseInt(settings.docdb_certificate_rotation_limit || this.settings.docdb_certificate_rotation_limit.default); + + async.each(regions.rds, function(region, rcb){ + var describeDBInstances = helpers.addSource(cache, source, + ['rds', 'describeDBInstances', region]); + + if (!describeDBInstances) return rcb(); + + if (describeDBInstances.err || !describeDBInstances.data) { + helpers.addResult(results, 3, + `Unable to list DocumentDB cluster instances: ${helpers.addError(describeDBInstances)}`, region); + return rcb(); + } + + if (!describeDBInstances.data.length) { + helpers.addResult(results, 0, + 'No DocumentDB cluster instances found', region); + return rcb(); + } + + for (let instance of describeDBInstances.data) { + if (!instance.DBInstanceArn) continue; + + if (!instance.Engine || instance.Engine.toLowerCase() != 'docdb') continue; + + let resource = instance.DBInstanceArn; + + if (instance.CertificateDetails && + instance.CertificateDetails.ValidTill) { + var then = new Date(instance.CertificateDetails.ValidTill); + var difference = Math.round((new Date(then).getTime() - new Date().getTime())/(24*60*60*1000)); + + if (difference > docdb_certificate_rotation_limit) { + helpers.addResult(results, 0, `DocumentDB cluster instance does not need certificate rotation as it expires in ${difference} days ` + + `of ${docdb_certificate_rotation_limit} days limit`, region, resource); + } else { + helpers.addResult(results, 2, `DocumentDB cluster instance needs certificate rotation as it expires in ${difference} days ` + + `of ${docdb_certificate_rotation_limit} days limit`, region, resource); + } + } + + } + + rcb(); + + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/aws/documentDB/docdbCertificateRotated.spec.js b/plugins/aws/documentDB/docdbCertificateRotated.spec.js new file mode 100644 index 0000000000..e0cc22eb15 --- /dev/null +++ b/plugins/aws/documentDB/docdbCertificateRotated.spec.js @@ -0,0 +1,112 @@ +var expect = require('chai').expect; +var docdbInstanceCertificateRotated = require('./docdbCertificateRotated'); + + +const describeDBInstances = [ + { + DBInstanceIdentifier: "docdb-2024-06-12-19-45-21", + Engine: "docdb", + DBInstanceStatus: "available", + BackupRetentionPeriod: 1, + MultiAZ: false, + EngineVersion: "5.0.0", + AutoMinorVersionUpgrade: true, + ReadReplicaDBInstanceIdentifiers: [ + ], + ReadReplicaDBClusterIdentifiers: [ + ], + LicenseModel: "na", + OptionGroupMemberships: [ + { + OptionGroupName: "default:docdb-5-0", + Status: "in-sync", + }, + ], + PubliclyAccessible: false, + StatusInfos: [ + ], + StorageType: "standard", + DbInstancePort: 0, + DBClusterIdentifier: "docdb-2024-06-12-19-45-21", + StorageEncrypted: false, + DbiResourceId: "db-QNKFC3466G5XP6NLPXHSZDY5ZQ", + CACertificateIdentifier: "rds-ca-2019", + DomainMemberships: [ + ], + CopyTagsToSnapshot: false, + MonitoringInterval: 0, + PromotionTier: 1, + DBInstanceArn: "arn:aws:rds:us-east-1:1234123412:db:docdb-2024-06-12-19-45-21", + IAMDatabaseAuthenticationEnabled: false, + CertificateDetails: { + CAIdentifier: "rds-ca-2019", + ValidTill: "2024-07-13T17:08:50.000Z", + }, + DedicatedLogVolume: false, + } +]; + + +const createCache = (instances, instancesErr) => { + return { + rds: { + describeDBInstances: { + 'us-east-1': { + err: instancesErr, + data: instances + }, + }, + }, + }; +}; + + + +describe('docdbInstanceCertificateRotated', function () { + describe('run', function () { + it('should PASS if DocumentDB cluster instance does not need certificate rotation', function (done) { + const cache = createCache(describeDBInstances); + docdbInstanceCertificateRotated.run(cache, { docdb_certificate_rotation_limit: 30 }, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('DocumentDB cluster instance does not need certificate rotation as it expires in 31 days of 30 days limit'); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + + + it('should FAIL if DocumentDB cluster instance does not need certificate rotation', function (done) { + const cache = createCache(describeDBInstances); + docdbInstanceCertificateRotated.run(cache, { docdb_certificate_rotation_limit: 40 }, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('DocumentDB cluster instance needs certificate rotation as it expires in 31 days of 40 days limit'); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + + + it('should PASS if no DocumentDB Clusters Instance found', function (done) { + const cache = createCache([]); + docdbInstanceCertificateRotated.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No DocumentDB cluster instances found'); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + + it('should UNKNOWN if unable to list DocumentDB Clusters Instances', function (done) { + const cache = createCache(null, null, null, { message: "Unable to list DocumentDB Clusters Instances" }); + docdbInstanceCertificateRotated.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + }); +}); From 72e3ab71d51862c3d434a9e9b8c88c3e403457be Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 14 Jun 2024 14:30:16 +0500 Subject: [PATCH 03/91] update --- plugins/aws/documentDB/docdbCertificateRotated.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/aws/documentDB/docdbCertificateRotated.js b/plugins/aws/documentDB/docdbCertificateRotated.js index 9f32c14406..bd564cb5f0 100644 --- a/plugins/aws/documentDB/docdbCertificateRotated.js +++ b/plugins/aws/documentDB/docdbCertificateRotated.js @@ -69,7 +69,6 @@ module.exports = { } rcb(); - }, function(){ callback(null, results, source); }); From b3c25321fd66052f733e97df4a1c2d5a726c7093 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 14 Jun 2024 14:37:21 +0500 Subject: [PATCH 04/91] update --- plugins/aws/documentDB/docdbCertificateRotated.spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/aws/documentDB/docdbCertificateRotated.spec.js b/plugins/aws/documentDB/docdbCertificateRotated.spec.js index e0cc22eb15..fbdf8ea41b 100644 --- a/plugins/aws/documentDB/docdbCertificateRotated.spec.js +++ b/plugins/aws/documentDB/docdbCertificateRotated.spec.js @@ -66,10 +66,10 @@ describe('docdbInstanceCertificateRotated', function () { describe('run', function () { it('should PASS if DocumentDB cluster instance does not need certificate rotation', function (done) { const cache = createCache(describeDBInstances); - docdbInstanceCertificateRotated.run(cache, { docdb_certificate_rotation_limit: 30 }, (err, results) => { + docdbInstanceCertificateRotated.run(cache, { docdb_certificate_rotation_limit: 20 }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('DocumentDB cluster instance does not need certificate rotation as it expires in 31 days of 30 days limit'); + expect(results[0].message).to.include('DocumentDB cluster instance does not need certificate rotation as it expires in 29 days of 20 days limit'); expect(results[0].region).to.equal('us-east-1'); done(); }); @@ -81,7 +81,7 @@ describe('docdbInstanceCertificateRotated', function () { docdbInstanceCertificateRotated.run(cache, { docdb_certificate_rotation_limit: 40 }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('DocumentDB cluster instance needs certificate rotation as it expires in 31 days of 40 days limit'); + expect(results[0].message).to.include('DocumentDB cluster instance needs certificate rotation as it expires in 29 days of 40 days limit'); expect(results[0].region).to.equal('us-east-1'); done(); }); From f77043aa9e058e2acbf52d22a638ba9cac7fa040 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Fri, 14 Jun 2024 15:18:17 +0500 Subject: [PATCH 05/91] Apply suggestions from code review --- plugins/azure/batchAccounts/batchAccountsManagedIdentity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js b/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js index d479729f4b..1452fec4e6 100644 --- a/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js +++ b/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js @@ -6,7 +6,7 @@ module.exports = { category: 'Batch', domain: 'Compute', severity: 'Medium', - description: 'Ensures that Batch account have managed identity enabled.', + description: 'Ensures that Batch accounts have managed identity enabled.', more_info: 'Enabling managed identities eliminate the need for developers having to manage credentials by providing an identity for the Azure resource in Azure AD and using it to obtain Azure Active Directory (Azure AD) tokens.', recommended_action: 'Modify Batch Account and enable managed identity.', link: 'https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools', From a2300dbbf6964dd3e96ec40ee4f841a93fd8a696 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Fri, 14 Jun 2024 15:18:33 +0500 Subject: [PATCH 06/91] Update plugins/azure/batchAccounts/batchAccountsManagedIdentity.js --- plugins/azure/batchAccounts/batchAccountsManagedIdentity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js b/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js index 1452fec4e6..efdf5d885a 100644 --- a/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js +++ b/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js @@ -37,7 +37,7 @@ module.exports = { for (let batchAccount of batchAccounts.data) { if (!batchAccount.id) continue; - if (batchAccount.identity) { + if (batchAccount.identity && batchAccount.identity.type) { helpers.addResult(results, 0, 'Batch account has managed identity enabled', location, batchAccount.id); } else { helpers.addResult(results, 2, 'Batch account does not have managed identity enabled', location, batchAccount.id); From 8411f256c4a65331c683253445800abf1559753f Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 17 Jun 2024 00:06:45 +0500 Subject: [PATCH 07/91] M/Aws/Api-gateway-v2-authorizer --- exports.js | 1 + helpers/aws/api.js | 14 ++ helpers/aws/regions.js | 1 + helpers/aws/regions_gov.js | 1 + .../apigateway/apigatewayV2Authorization.js | 73 ++++++++ .../apigatewayV2Authorization.spec.js | 157 ++++++++++++++++++ 6 files changed, 247 insertions(+) create mode 100644 plugins/aws/apigateway/apigatewayV2Authorization.js create mode 100644 plugins/aws/apigateway/apigatewayV2Authorization.spec.js diff --git a/exports.js b/exports.js index 9ca097916d..2f37757420 100644 --- a/exports.js +++ b/exports.js @@ -25,6 +25,7 @@ module.exports = { 'customDomainTlsVersion' : require(__dirname + '/plugins/aws/apigateway/customDomainTlsVersion.js'), 'apigatewayDefaultEndpointDisabled' : require(__dirname + '/plugins/aws/apigateway/apigatewayDefaultEndpointDisabled.js'), 'apigatewayAuthorization' : require(__dirname + '/plugins/aws/apigateway/apigatewayAuthorization.js'), + 'apigatewayV2Authorization' : require(__dirname + '/plugins/aws/apigateway/apigatewayV2Authorization.js'), 'restrictExternalTraffic' : require(__dirname + '/plugins/aws/appmesh/restrictExternalTraffic.js'), 'appmeshTLSRequired' : require(__dirname + '/plugins/aws/appmesh/appmeshTLSRequired.js'), diff --git a/helpers/aws/api.js b/helpers/aws/api.js index b28dff1cbd..342eb14f72 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -594,6 +594,12 @@ var calls = { paginate: 'NextToken' } }, + ApiGatewayV2: { + getApis: { + property: 'Items', + paginate: 'NextToken' + }, + }, AppConfig: { listApplications: { property: 'Items', @@ -1844,6 +1850,14 @@ var postcalls = [ filterValue: 'id' } }, + ApiGatewayV2: { + getAuthorizers: { + reliesOnService: 'apigatewayv2', + reliesOnCall: 'getApis', + filterKey: 'ApiId', + filterValue: 'ApiId' + } + }, AppConfig: { listConfigurationProfiles: { reliesOnService: 'appconfig', diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index 075f1d8a3e..a1590babab 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -42,6 +42,7 @@ module.exports = { accessanalyzer: [...regions, ...newRegionsUpdate], acm: [...regions, ...newRegionsUpdate], apigateway: [...regions, ...newRegionsUpdate], + apigatewayv2: [...regions, ...newRegionsUpdate], athena:[...regions, ...newRegionsUpdate], bedrock: ['us-east-1', 'us-west-2', 'ap-south-1','ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'eu-central-1', 'eu-west-1', 'eu-west-3'], cloudfront: ['us-east-1'], // CloudFront uses the default global region diff --git a/helpers/aws/regions_gov.js b/helpers/aws/regions_gov.js index 856fb5109b..df2b454615 100644 --- a/helpers/aws/regions_gov.js +++ b/helpers/aws/regions_gov.js @@ -12,6 +12,7 @@ module.exports = { accessanalyzer: regions, acm: regions, apigateway: regions, + apigatewayv2: regions, athena: regions, backup: regions, bedrock: ['us-gov-west-1'], diff --git a/plugins/aws/apigateway/apigatewayV2Authorization.js b/plugins/aws/apigateway/apigatewayV2Authorization.js new file mode 100644 index 0000000000..2c46931e05 --- /dev/null +++ b/plugins/aws/apigateway/apigatewayV2Authorization.js @@ -0,0 +1,73 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'API Gateway V2 Authorization', + category: 'API Gateway', + domain: 'Availability', + severity: 'High', + description: 'Ensures that Amazon API Gateway V2 APIs are using authorizer.', + more_info: 'API Gateway V2 APIs should be configured to use authorizer to enforce security measures and restrict access to API to only authorized users or processess.', + recommended_action: 'Modify API Gateway V2 configuration and ensure that appropriate authorizers are set up for each API.', + link: 'https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html', + apis: ['ApiGatewayV2:getApis','ApiGatewayV2:getAuthorizers'], + realtime_triggers: ['ApiGatewayV2:createApi','ApiGatewayV2:deleteApi','ApiGatewayV2:importApi','ApiGatewayV2:createAuthorizer','ApiGatewayV2:deleteAuthorizer'], + + run: function(cache, settings, callback) { + console.log('here'); + var results = []; + var source = {}; + var regions = helpers.regions(settings); + var awsOrGov = helpers.defaultPartition(settings); + + async.each(regions.apigatewayv2, function(region, rcb){ + var getApis = helpers.addSource(cache, source, + ['apigatewayv2', 'getApis', region]); + + if (!getApis) return rcb(); + + if (getApis.err || !getApis.data) { + helpers.addResult(results, 3, + `Unable to query for API Gateway V2 APIs: ${helpers.addError(getApis)}`, region); + return rcb(); + } + + if (!getApis.data.length) { + helpers.addResult(results, 0, 'No API Gateway V2 APIs found', region); + return rcb(); + } + + getApis.data.forEach(api => { + if (!api.ApiId) return; + + var apiArn = `arn:${awsOrGov}:apigateway:${region}::/apis/${api.ApiId}`; + + var getAuthorizers = helpers.addSource(cache, source, + ['apigatewayv2', 'getAuthorizers', region, api.ApiId]); + + if (!getAuthorizers || getAuthorizers.err || !getAuthorizers.data || !getAuthorizers.data.Items) { + helpers.addResult(results, 3, + `Unable to query for API Gateway V2 authorizers: ${helpers.addError(getAuthorizers)}`, + region, apiArn); + return; + } + + if (!getAuthorizers.data.Items.length) { + helpers.addResult(results, 2, + 'No authorizers found for API Gateway V2 API', + region, apiArn ); + } else { + helpers.addResult(results, 0, + 'Authorizers found for API Gateway V2 API', + region, apiArn); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; + + \ No newline at end of file diff --git a/plugins/aws/apigateway/apigatewayV2Authorization.spec.js b/plugins/aws/apigateway/apigatewayV2Authorization.spec.js new file mode 100644 index 0000000000..0762e9fac4 --- /dev/null +++ b/plugins/aws/apigateway/apigatewayV2Authorization.spec.js @@ -0,0 +1,157 @@ +var expect = require('chai').expect; +var apigatewayV2Authorization = require('./apigatewayV2Authorization'); + +const createCache = (getApis, getAuthorizersData) => { + if (getApis && getApis.length && getApis[0].ApiId) var restApiId = getApis[0].ApiId; + return { + apigatewayv2: { + getApis: { + 'us-east-1': { + data: getApis + } + }, + getAuthorizers: { + 'us-east-1': { + [restApiId]: { + data: { + Items: getAuthorizersData + } + } + } + } + } + }; +}; + +const createErrorCache = () => { + return { + apigatewayv2: { + getApis: { + 'us-east-1': { + err: { + message: 'error fetching API Gateway v2 APIs' + }, + }, + }, + getAuthorizers: { + 'us-east-1': { + err: { + message: 'error fetching API Gateway v2 Authorizers' + }, + }, + } + + }, + }; +}; + +const createNullCache = () => { + return { + apigatewayv2: { + getApis: { + 'us-east-1': null + }, + getAuthorizers: { + 'us-east-1': null + } + } + }; +}; + +describe('apigatewayV2Authorization', function () { + describe('run', function () { + it('should return UNKNOWN if unable to query for API Gateway v2 APIs', function (done) { + const cache = createErrorCache(); + apigatewayV2Authorization.run(cache, {} , (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + expect(results[0].region).to.equal('us-east-1'); + expect (results[0].message).to.include('Unable to query for API Gateway V2 APIs:'); + done(); + }); + }); + + it('should return PASS if no API Gateway Rest APIs found', function (done) { + const cache = createCache([]); + apigatewayV2Authorization.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('us-east-1'); + expect (results[0].message).to.include('No API Gateway V2 APIs found'); + done(); + }); + }); + + it('should return FAIL if no authorizers exist for API Gateway Rest API', function (done) { + const getApis = [ + { + ApiId: 'api-id', + name: 'TestAPI', + description: 'Test API', + createdDate: 1621916018, + apiKeySource: 'HEADER', + endpointConfiguration: { + types: ['REGIONAL'] + } + } + ]; + const getAuthorizersData = []; + const cache = createCache(getApis, getAuthorizersData); + apigatewayV2Authorization.run(cache,{}, (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('No authorizers found for API Gateway V2 API'); + done(); + }); + }); + + it('should return PASS if authorizers exist for API Gateway V2 API', function (done) { + const getApis = [ + { + ApiId: 'api-id', + name: 'TestAPI', + description: 'Test API', + createdDate: 1621916018, + apiKeySource: 'HEADER', + endpointConfiguration: { + types: ['REGIONAL'] + } + } + ]; + const getAuthorizersData = [ + { + name: 'authorizer1', + type: 'REQUEST', + authType: 'custom', + authorizerUri: 'arn:aws:lambda:us-east-1:123456789012:function:authorizer1', + identitySource: 'method.request.header.Authorization', + authorizerResultTtlInSeconds: 300 + }, + { + name: 'authorizer2', + type: 'REQUEST', + authType: 'custom', + authorizerUri: 'arn:aws:lambda:us-east-1:123456789012:function:authorizer2', + identitySource: 'method.request.header.Authorization', + authorizerResultTtlInSeconds: 300 + } + ]; + const cache = createCache(getApis, getAuthorizersData); + apigatewayV2Authorization.run(cache,{}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('Authorizers found for API Gateway V2 API') + done(); + }); + }); + it('should not return anything if get Rest APIs response is not found', function (done) { + const cache = createNullCache(); + apigatewayV2Authorization.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + }); +}); From dc8c7a2208b7f5aa2e34eeba314f3295197b6ad0 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 17 Jun 2024 00:42:44 +0500 Subject: [PATCH 08/91] M/Aws/Api-gateway-v2-access-logging --- exports.js | 1 + helpers/aws/api.js | 6 + .../apigateway/apigatewayV2AccessLogging.js | 85 +++++++ .../apigatewayV2AccessLogging.spec.js | 218 ++++++++++++++++++ 4 files changed, 310 insertions(+) create mode 100644 plugins/aws/apigateway/apigatewayV2AccessLogging.js create mode 100644 plugins/aws/apigateway/apigatewayV2AccessLogging.spec.js diff --git a/exports.js b/exports.js index 2f37757420..ecc8da4c92 100644 --- a/exports.js +++ b/exports.js @@ -26,6 +26,7 @@ module.exports = { 'apigatewayDefaultEndpointDisabled' : require(__dirname + '/plugins/aws/apigateway/apigatewayDefaultEndpointDisabled.js'), 'apigatewayAuthorization' : require(__dirname + '/plugins/aws/apigateway/apigatewayAuthorization.js'), 'apigatewayV2Authorization' : require(__dirname + '/plugins/aws/apigateway/apigatewayV2Authorization.js'), + 'apigatewayV2AccessLogging' : require(__dirname + '/plugins/aws/apigateway/apigatewayV2AccessLogging.js'), 'restrictExternalTraffic' : require(__dirname + '/plugins/aws/appmesh/restrictExternalTraffic.js'), 'appmeshTLSRequired' : require(__dirname + '/plugins/aws/appmesh/appmeshTLSRequired.js'), diff --git a/helpers/aws/api.js b/helpers/aws/api.js index 342eb14f72..ec81bc6bc3 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -1851,6 +1851,12 @@ var postcalls = [ } }, ApiGatewayV2: { + getStages: { + reliesOnService: 'apigatewayv2', + reliesOnCall: 'getApis', + filterKey: 'ApiId', + filterValue: 'ApiId' + }, getAuthorizers: { reliesOnService: 'apigatewayv2', reliesOnCall: 'getApis', diff --git a/plugins/aws/apigateway/apigatewayV2AccessLogging.js b/plugins/aws/apigateway/apigatewayV2AccessLogging.js new file mode 100644 index 0000000000..ab266f4561 --- /dev/null +++ b/plugins/aws/apigateway/apigatewayV2AccessLogging.js @@ -0,0 +1,85 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'API Gateway V2 Authorization', + category: 'API Gateway', + domain: 'Availability', + severity: 'High', + description: 'Ensures that Amazon API Gateway V2 APIs are using authorizer.', + more_info: 'API Gateway V2 APIs should be configured to use authorizer to enforce security measures and restrict access to API to only authorized users or processess.', + recommended_action: 'Modify API Gateway V2 configuration and ensure that appropriate authorizers are set up for each API.', + link: 'https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html', + apis: ['ApiGatewayV2:getApis','ApiGatewayV2:getStages'], + realtime_triggers: ['ApiGatewayV2:createApi','ApiGatewayV2:deleteApi','ApiGatewayV2:importApi','ApiGatewayv2:CreateStage','ApiGatewayv2:UpdateStage','ApiGatewayv2:DeleteStage'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + var awsOrGov = helpers.defaultPartition(settings); + + async.each(regions.apigatewayv2, function(region, rcb){ + var getApis = helpers.addSource(cache, source, + ['apigatewayv2', 'getApis', region]); + + if (!getApis) return rcb(); + + if (getApis.err || !getApis.data) { + helpers.addResult(results, 3, + `Unable to query for API Gateway V2 APIs: ${helpers.addError(getApis)}`, region); + return rcb(); + } + + if (!getApis.data.length) { + helpers.addResult(results, 0, 'No API Gateway V2 APIs found', region); + return rcb(); + } + + getApis.data.forEach(api => { + if (!api.ApiId) return; + + var apiArn = `arn:${awsOrGov}:apigateway:${region}::/apis/${api.ApiId}`; + + var getStages = helpers.addSource(cache, source, + ['apigatewayv2', 'getStages', region, api.ApiId]); + + if (!getStages || getStages.err || !getStages.data || !getStages.data.Items) { + helpers.addResult(results, 3, + `Unable to query for API Gateway V2 API Stages: ${helpers.addError(getStages)}`, + region, apiArn); + return; + } + + if (!getStages.data.Items.length) { + helpers.addResult(results, 0, + 'No API Gateway V2 API Stages found', + region, apiArn); + return; + } + + getStages.data.Items.forEach(stage => { + if (!stage.StageName) return; + + var stageArn = `arn:${awsOrGov}:apigateway:${region}::/apis/${api.ApiId}/stages/${stage.StageName}`; + if (stage.AccessLogSetting) { + helpers.addResult(results, 0, + 'API Gateway V2 API stage has access logging enabled', + region, stageArn); + } else { + helpers.addResult(results, 2, + 'API Gateway V2 API stage does not have access logging enabled', + region, stageArn); + } + }); + + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; + + \ No newline at end of file diff --git a/plugins/aws/apigateway/apigatewayV2AccessLogging.spec.js b/plugins/aws/apigateway/apigatewayV2AccessLogging.spec.js new file mode 100644 index 0000000000..f6dd1a6cc1 --- /dev/null +++ b/plugins/aws/apigateway/apigatewayV2AccessLogging.spec.js @@ -0,0 +1,218 @@ +var expect = require('chai').expect; +var apigatewayV2AccessLogging = require('./apigatewayV2AccessLogging'); + +const createCache = (getApis, getStages) => { + if (getApis && getApis.length && getApis[0].ApiId) var restApiId = getApis[0].ApiId; + return { + apigatewayv2: { + getApis: { + 'us-east-1': { + data: getApis + } + }, + getStages: { + 'us-east-1': { + [restApiId]: { + data: { + Items: getStages + } + } + } + } + } + }; +}; + +const createErrorCache = () => { + return { + apigatewayv2: { + getApis: { + 'us-east-1': { + err: { + message: 'error fetching API Gateway v2 APIs' + }, + }, + }, + getStages: { + 'us-east-1': { + err: { + message: 'error fetching API Gateway v2 stages' + }, + }, + } + + }, + }; +}; + +const createUnknownForStage = (api) => { + return { + apigatewayv2: { + getApis: { + 'us-east-1': { + data: api + } + }, + getStages: { + 'us-east-1': 'err' + } + } + }; +}; + +describe('apigatewayV2AccessLogging', function () { + describe('run', function () { + it('should return UNKNOWN if unable to query for API Gateway v2 APIs', function (done) { + const cache = createErrorCache(); + apigatewayV2AccessLogging.run(cache, {} , (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + expect(results[0].region).to.equal('us-east-1'); + expect (results[0].message).to.include('Unable to query for API Gateway V2 APIs:'); + done(); + }); + }); + + it('should return PASS if no API Gateway Rest APIs found', function (done) { + const cache = createCache([]); + apigatewayV2AccessLogging.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('us-east-1'); + expect (results[0].message).to.include('No API Gateway V2 APIs found'); + done(); + }); + }); + + it('should return PASS if no stages found', function (done) { + const getApis = [ + { + ApiId: 'api-id', + name: 'TestAPI', + description: 'Test API', + createdDate: 1621916018, + apiKeySource: 'HEADER', + endpointConfiguration: { + types: ['REGIONAL'] + } + } + ]; + const getStages = []; + const cache = createCache(getApis, getStages); + apigatewayV2AccessLogging.run(cache,{}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('us-east-1'); + expect (results[0].message).to.include('No API Gateway V2 API Stages found'); + done(); + }); + }); + + it('should return PASS if Api gateway v2 stage has access logging enabled', function (done) { + const getApis = [ + { + ApiId: 'api-id', + name: 'TestAPI', + description: 'Test API', + createdDate: 1621916018, + apiKeySource: 'HEADER', + endpointConfiguration: { + types: ['REGIONAL'] + } + } + ]; + const getStages = [ + { + "AutoDeploy": true, + "CreatedDate": "2023-12-11T20:07:28.000Z", + "DefaultRouteSettings": { + "DetailedMetricsEnabled": false + }, + "DeploymentId": "biw5qf", + "Description": "Created by AWS Lambda", + "LastDeploymentStatusMessage": "Successfully deployed stage with deployment ID 'biw5qf'", + "LastUpdatedDate": "2023-12-11T20:07:29.000Z", + "RouteSettings": {}, + "StageName": "default", + "StageVariables": {}, + "Tags": {}, + "AccessLogSetting": { + "LogArn": "arn:aws:1234:log" + } + } + ]; + const cache = createCache(getApis, getStages); + apigatewayV2AccessLogging.run(cache,{}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('API Gateway V2 API stage has access logging enabled') + done(); + }); + }); + + it('should return PASS if Api gateway v2 stage has access logging enabled', function (done) { + const getApis = [ + { + ApiId: 'api-id', + name: 'TestAPI', + description: 'Test API', + createdDate: 1621916018, + apiKeySource: 'HEADER', + endpointConfiguration: { + types: ['REGIONAL'] + } + } + ]; + const getStages = [ + { + "AutoDeploy": true, + "CreatedDate": "2023-12-11T20:07:28.000Z", + "DefaultRouteSettings": { + "DetailedMetricsEnabled": false + }, + "DeploymentId": "biw5qf", + "Description": "Created by AWS Lambda", + "LastDeploymentStatusMessage": "Successfully deployed stage with deployment ID 'biw5qf'", + "LastUpdatedDate": "2023-12-11T20:07:29.000Z", + "RouteSettings": {}, + "StageName": "default", + "StageVariables": {}, + "Tags": {}, + } + ]; + const cache = createCache(getApis, getStages); + apigatewayV2AccessLogging.run(cache,{}, (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('API Gateway V2 API stage does not have access logging enabled') + done(); + }); + }); + + it('should return UNKNOWN if unable to query for api stages', function (done) { + const getApis = [ + { + ApiId: 'api-id', + name: 'TestAPI', + description: 'Test API', + createdDate: 1621916018, + apiKeySource: 'HEADER', + endpointConfiguration: { + types: ['REGIONAL'] + } + } + ]; + + const cache = createUnknownForStage(getApis); + apigatewayV2AccessLogging.run(cache,{}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('Unable to query for API Gateway V2 API Stages:') + done(); + }); + }); + }); +}); From 167c1e3769d03df25fa1f30f0c192c5152084079 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 17 Jun 2024 01:00:27 +0500 Subject: [PATCH 09/91] plugins/aws/apigateway/apigatewayV2AccessLogging.js --- plugins/aws/apigateway/apigatewayV2AccessLogging.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/aws/apigateway/apigatewayV2AccessLogging.js b/plugins/aws/apigateway/apigatewayV2AccessLogging.js index ab266f4561..355a8999f6 100644 --- a/plugins/aws/apigateway/apigatewayV2AccessLogging.js +++ b/plugins/aws/apigateway/apigatewayV2AccessLogging.js @@ -2,17 +2,17 @@ var async = require('async'); var helpers = require('../../../helpers/aws'); module.exports = { - title: 'API Gateway V2 Authorization', + title: 'API Gateway V2 Access Logging', category: 'API Gateway', domain: 'Availability', severity: 'High', - description: 'Ensures that Amazon API Gateway V2 APIs are using authorizer.', - more_info: 'API Gateway V2 APIs should be configured to use authorizer to enforce security measures and restrict access to API to only authorized users or processess.', - recommended_action: 'Modify API Gateway V2 configuration and ensure that appropriate authorizers are set up for each API.', - link: 'https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html', + description: 'Ensures that Amazon API Gateway V2 APIs stages have access logging enabled.', + more_info: 'API Gateway V2 access logs provide detailed information about APIs and how the caller accessed the API. These logs are useful for applications for security and access audits which helps to analyze traffic patterns and to troubleshoot issues.', + recommended_action: 'Modify API Gateway V2 configuration and ensure that access logging is configured for each stage.', + link: 'https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-logging.html', apis: ['ApiGatewayV2:getApis','ApiGatewayV2:getStages'], realtime_triggers: ['ApiGatewayV2:createApi','ApiGatewayV2:deleteApi','ApiGatewayV2:importApi','ApiGatewayv2:CreateStage','ApiGatewayv2:UpdateStage','ApiGatewayv2:DeleteStage'], - + run: function(cache, settings, callback) { var results = []; var source = {}; From fbd754a34200d03aa430f9c1f256be4d8f2e839e Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Mon, 17 Jun 2024 01:01:38 +0500 Subject: [PATCH 10/91] Update plugins/aws/apigateway/apigatewayV2AccessLogging.js --- plugins/aws/apigateway/apigatewayV2AccessLogging.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/apigateway/apigatewayV2AccessLogging.js b/plugins/aws/apigateway/apigatewayV2AccessLogging.js index 355a8999f6..fbe471c135 100644 --- a/plugins/aws/apigateway/apigatewayV2AccessLogging.js +++ b/plugins/aws/apigateway/apigatewayV2AccessLogging.js @@ -5,7 +5,7 @@ module.exports = { title: 'API Gateway V2 Access Logging', category: 'API Gateway', domain: 'Availability', - severity: 'High', + severity: 'Medium', description: 'Ensures that Amazon API Gateway V2 APIs stages have access logging enabled.', more_info: 'API Gateway V2 access logs provide detailed information about APIs and how the caller accessed the API. These logs are useful for applications for security and access audits which helps to analyze traffic patterns and to troubleshoot issues.', recommended_action: 'Modify API Gateway V2 configuration and ensure that access logging is configured for each stage.', From 888962dde3e99e9a383c028b13656202691a7f6e Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Wed, 19 Jun 2024 23:27:20 +0500 Subject: [PATCH 11/91] Apply suggestions from code review --- plugins/aws/apigateway/apigatewayV2AccessLogging.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/aws/apigateway/apigatewayV2AccessLogging.js b/plugins/aws/apigateway/apigatewayV2AccessLogging.js index fbe471c135..bf5b107d83 100644 --- a/plugins/aws/apigateway/apigatewayV2AccessLogging.js +++ b/plugins/aws/apigateway/apigatewayV2AccessLogging.js @@ -6,8 +6,8 @@ module.exports = { category: 'API Gateway', domain: 'Availability', severity: 'Medium', - description: 'Ensures that Amazon API Gateway V2 APIs stages have access logging enabled.', - more_info: 'API Gateway V2 access logs provide detailed information about APIs and how the caller accessed the API. These logs are useful for applications for security and access audits which helps to analyze traffic patterns and to troubleshoot issues.', + description: 'Ensures that Amazon API Gateway V2 API stages have access logging enabled.', + more_info: 'API Gateway V2 access logs provide detailed information about APIs and how the caller accessed the API. These logs are useful for security and access audits which helps to analyze traffic patterns and troubleshoot issues.', recommended_action: 'Modify API Gateway V2 configuration and ensure that access logging is configured for each stage.', link: 'https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-logging.html', apis: ['ApiGatewayV2:getApis','ApiGatewayV2:getStages'], From 07b16e689a123c378454f6e2f5f9e497b3c65be3 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Wed, 19 Jun 2024 23:32:20 +0500 Subject: [PATCH 12/91] Update plugins/aws/apigateway/apigatewayV2Authorization.js --- plugins/aws/apigateway/apigatewayV2Authorization.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/apigateway/apigatewayV2Authorization.js b/plugins/aws/apigateway/apigatewayV2Authorization.js index 2c46931e05..eb3ca1f129 100644 --- a/plugins/aws/apigateway/apigatewayV2Authorization.js +++ b/plugins/aws/apigateway/apigatewayV2Authorization.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Availability', severity: 'High', description: 'Ensures that Amazon API Gateway V2 APIs are using authorizer.', - more_info: 'API Gateway V2 APIs should be configured to use authorizer to enforce security measures and restrict access to API to only authorized users or processess.', + more_info: 'API Gateway V2 APIs should be configured to use authorizer to enforce security measures and restrict access to API to only authorized users or processes.', recommended_action: 'Modify API Gateway V2 configuration and ensure that appropriate authorizers are set up for each API.', link: 'https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html', apis: ['ApiGatewayV2:getApis','ApiGatewayV2:getAuthorizers'], From 104233844a94ab194acf91da289dc193fa2e452d Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Wed, 19 Jun 2024 23:37:50 +0500 Subject: [PATCH 13/91] Added china regions --- helpers/aws/regions_china.js | 1 + 1 file changed, 1 insertion(+) diff --git a/helpers/aws/regions_china.js b/helpers/aws/regions_china.js index b3d5984374..5a7e38a712 100644 --- a/helpers/aws/regions_china.js +++ b/helpers/aws/regions_china.js @@ -13,6 +13,7 @@ module.exports = { cognitoidentityserviceprovider: regions, acm: [], apigateway: regions, + apigatewayv2: regions, athena: [], bedrock:[], cloudfront: [], From b1358163875e250d9811b2c2f53a92fc03cecaa8 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Wed, 19 Jun 2024 23:44:12 +0500 Subject: [PATCH 14/91] Added china region --- helpers/aws/regions_china.js | 1 + 1 file changed, 1 insertion(+) diff --git a/helpers/aws/regions_china.js b/helpers/aws/regions_china.js index b3d5984374..5a7e38a712 100644 --- a/helpers/aws/regions_china.js +++ b/helpers/aws/regions_china.js @@ -13,6 +13,7 @@ module.exports = { cognitoidentityserviceprovider: regions, acm: [], apigateway: regions, + apigatewayv2: regions, athena: [], bedrock:[], cloudfront: [], From ebe3fdcbe71fc06e8ddf9ac5e01c2a885e4c4f84 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Thu, 20 Jun 2024 13:06:58 +0500 Subject: [PATCH 15/91] Update plugins/aws/documentDB/docdbCertificateRotated.js --- plugins/aws/documentDB/docdbCertificateRotated.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/documentDB/docdbCertificateRotated.js b/plugins/aws/documentDB/docdbCertificateRotated.js index bd564cb5f0..9fe58a75ab 100644 --- a/plugins/aws/documentDB/docdbCertificateRotated.js +++ b/plugins/aws/documentDB/docdbCertificateRotated.js @@ -6,7 +6,7 @@ module.exports = { category: 'DocumentDB', domain: 'Databases', severity: 'High', - description: 'Ensure that AWS DocumentDB cluster instance certificates are rotated.', + description: 'Ensure that DocumentDB cluster instance certificates are rotated.', more_info: 'Enabling the AWS DocumentDB cluster certificate rotation ensures that your cluster\'s TLS certificates are automatically rotated to maintain security and compliance standards. This feature helps in seamlessly updating certificates without downtime, ensuring continuous protection for data in transit within the DocumentDB cluster.', recommended_action: 'Modify DocumentDB cluster instance and rotate the old server certificate.', link: 'https://docs.aws.amazon.com/documentdb/latest/developerguide/ca_cert_rotation.html', From 424237a095870cbadf8b9c2d35ea58de4f03fda8 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Thu, 20 Jun 2024 13:07:04 +0500 Subject: [PATCH 16/91] Update plugins/aws/documentDB/docdbCertificateRotated.js --- plugins/aws/documentDB/docdbCertificateRotated.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/documentDB/docdbCertificateRotated.js b/plugins/aws/documentDB/docdbCertificateRotated.js index 9fe58a75ab..17658505c7 100644 --- a/plugins/aws/documentDB/docdbCertificateRotated.js +++ b/plugins/aws/documentDB/docdbCertificateRotated.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Databases', severity: 'High', description: 'Ensure that DocumentDB cluster instance certificates are rotated.', - more_info: 'Enabling the AWS DocumentDB cluster certificate rotation ensures that your cluster\'s TLS certificates are automatically rotated to maintain security and compliance standards. This feature helps in seamlessly updating certificates without downtime, ensuring continuous protection for data in transit within the DocumentDB cluster.', + more_info: 'AWS DocumentDB cluster certificate rotation ensures that cluster\'s TLS certificates are automatically rotated to maintain security and compliance standards. This feature helps in seamlessly updating certificates without downtime, ensuring continuous protection for data in transit within the DocumentDB cluster.', recommended_action: 'Modify DocumentDB cluster instance and rotate the old server certificate.', link: 'https://docs.aws.amazon.com/documentdb/latest/developerguide/ca_cert_rotation.html', apis: ['RDS:describeDBInstances'], From 79f35d28d007f7045352ce12e573c5b8e9739173 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 20 Jun 2024 13:49:26 +0500 Subject: [PATCH 17/91] update file --- .../aws/documentDB/docdbCertificateRotated.js | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/plugins/aws/documentDB/docdbCertificateRotated.js b/plugins/aws/documentDB/docdbCertificateRotated.js index 17658505c7..a707060ca2 100644 --- a/plugins/aws/documentDB/docdbCertificateRotated.js +++ b/plugins/aws/documentDB/docdbCertificateRotated.js @@ -51,21 +51,24 @@ module.exports = { if (!instance.Engine || instance.Engine.toLowerCase() != 'docdb') continue; let resource = instance.DBInstanceArn; - - if (instance.CertificateDetails && - instance.CertificateDetails.ValidTill) { - var then = new Date(instance.CertificateDetails.ValidTill); - var difference = Math.round((new Date(then).getTime() - new Date().getTime())/(24*60*60*1000)); - if (difference > docdb_certificate_rotation_limit) { - helpers.addResult(results, 0, `DocumentDB cluster instance does not need certificate rotation as it expires in ${difference} days ` + - `of ${docdb_certificate_rotation_limit} days limit`, region, resource); - } else { - helpers.addResult(results, 2, `DocumentDB cluster instance needs certificate rotation as it expires in ${difference} days ` + - `of ${docdb_certificate_rotation_limit} days limit`, region, resource); - } + if (resource) { + if (instance.CertificateDetails && + instance.CertificateDetails.ValidTill) { + var then = new Date(instance.CertificateDetails.ValidTill); + var difference = Math.round((new Date(then).getTime() - new Date().getTime())/(24*60*60*1000)); + + if (difference > docdb_certificate_rotation_limit) { + helpers.addResult(results, 0, `DocumentDB cluster instance does not need certificate rotation as it expires in ${difference} days ` + + `of ${docdb_certificate_rotation_limit} days limit`, region, resource); + } else { + helpers.addResult(results, 2, `DocumentDB cluster instance needs certificate rotation as it expires in ${difference} days ` + + `of ${docdb_certificate_rotation_limit} days limit`, region, resource); + } + } + } else { + helpers.addResult(results, 0, 'No DocumentDB cluster instances found', region); } - } rcb(); From ad9220e182895bfdaa1f5da8dbf6c1208ad88b57 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 20 Jun 2024 14:05:44 +0500 Subject: [PATCH 18/91] update file --- .../aws/documentDB/docdbCertificateRotated.js | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/plugins/aws/documentDB/docdbCertificateRotated.js b/plugins/aws/documentDB/docdbCertificateRotated.js index a707060ca2..230b9bbe81 100644 --- a/plugins/aws/documentDB/docdbCertificateRotated.js +++ b/plugins/aws/documentDB/docdbCertificateRotated.js @@ -45,6 +45,8 @@ module.exports = { return rcb(); } + let docdbInstanceFound = false; + for (let instance of describeDBInstances.data) { if (!instance.DBInstanceArn) continue; @@ -52,24 +54,26 @@ module.exports = { let resource = instance.DBInstanceArn; - if (resource) { - if (instance.CertificateDetails && - instance.CertificateDetails.ValidTill) { - var then = new Date(instance.CertificateDetails.ValidTill); - var difference = Math.round((new Date(then).getTime() - new Date().getTime())/(24*60*60*1000)); + if (resource) docdbInstanceFound = true; + + if (instance.CertificateDetails && + instance.CertificateDetails.ValidTill) { + var then = new Date(instance.CertificateDetails.ValidTill); + var difference = Math.round((new Date(then).getTime() - new Date().getTime())/(24*60*60*1000)); - if (difference > docdb_certificate_rotation_limit) { - helpers.addResult(results, 0, `DocumentDB cluster instance does not need certificate rotation as it expires in ${difference} days ` + + if (difference > docdb_certificate_rotation_limit) { + helpers.addResult(results, 0, `DocumentDB cluster instance does not need certificate rotation as it expires in ${difference} days ` + `of ${docdb_certificate_rotation_limit} days limit`, region, resource); - } else { - helpers.addResult(results, 2, `DocumentDB cluster instance needs certificate rotation as it expires in ${difference} days ` + + } else { + helpers.addResult(results, 2, `DocumentDB cluster instance needs certificate rotation as it expires in ${difference} days ` + `of ${docdb_certificate_rotation_limit} days limit`, region, resource); - } - } - } else { - helpers.addResult(results, 0, 'No DocumentDB cluster instances found', region); + } } } + + if (!docdbInstanceFound) { + helpers.addResult(results, 0, 'No DocumentDB cluster instances found', region); + } rcb(); }, function(){ From 8dc12e14adde35542fbb647b94a9a6f3b9ba7122 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Thu, 20 Jun 2024 14:08:03 +0500 Subject: [PATCH 19/91] Update plugins/aws/documentDB/docdbCertificateRotated.js --- plugins/aws/documentDB/docdbCertificateRotated.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/documentDB/docdbCertificateRotated.js b/plugins/aws/documentDB/docdbCertificateRotated.js index 230b9bbe81..b284b0ad20 100644 --- a/plugins/aws/documentDB/docdbCertificateRotated.js +++ b/plugins/aws/documentDB/docdbCertificateRotated.js @@ -54,7 +54,7 @@ module.exports = { let resource = instance.DBInstanceArn; - if (resource) docdbInstanceFound = true; + docdbInstanceFound = true; if (instance.CertificateDetails && instance.CertificateDetails.ValidTill) { From 4e17c5a8c08518a64e618323005058f527947c05 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 20 Jun 2024 14:48:01 +0500 Subject: [PATCH 20/91] update spec --- .../docdbCertificateRotated.spec.js | 63 ++++++++++++++++--- 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/plugins/aws/documentDB/docdbCertificateRotated.spec.js b/plugins/aws/documentDB/docdbCertificateRotated.spec.js index fbdf8ea41b..66d4d85108 100644 --- a/plugins/aws/documentDB/docdbCertificateRotated.spec.js +++ b/plugins/aws/documentDB/docdbCertificateRotated.spec.js @@ -1,6 +1,10 @@ var expect = require('chai').expect; var docdbInstanceCertificateRotated = require('./docdbCertificateRotated'); +var certPass = new Date(); +certPass.setMonth(certPass.getMonth() + 2); +var certFail = new Date(); +certFail.setMonth(certFail.getMonth() - 1); const describeDBInstances = [ { @@ -40,10 +44,51 @@ const describeDBInstances = [ IAMDatabaseAuthenticationEnabled: false, CertificateDetails: { CAIdentifier: "rds-ca-2019", - ValidTill: "2024-07-13T17:08:50.000Z", + ValidTill: certFail, }, DedicatedLogVolume: false, - } + }, + { + DBInstanceIdentifier: "docdb-2024-06-12-19-45-21", + Engine: "docdb", + DBInstanceStatus: "available", + BackupRetentionPeriod: 1, + MultiAZ: false, + EngineVersion: "5.0.0", + AutoMinorVersionUpgrade: true, + ReadReplicaDBInstanceIdentifiers: [ + ], + ReadReplicaDBClusterIdentifiers: [ + ], + LicenseModel: "na", + OptionGroupMemberships: [ + { + OptionGroupName: "default:docdb-5-0", + Status: "in-sync", + }, + ], + PubliclyAccessible: false, + StatusInfos: [ + ], + StorageType: "standard", + DbInstancePort: 0, + DBClusterIdentifier: "docdb-2024-06-12-19-45-21", + StorageEncrypted: false, + DbiResourceId: "db-QNKFC3466G5XP6NLPXHSZDY5ZQ", + CACertificateIdentifier: "rds-ca-2019", + DomainMemberships: [ + ], + CopyTagsToSnapshot: false, + MonitoringInterval: 0, + PromotionTier: 1, + DBInstanceArn: "arn:aws:rds:us-east-1:1234123412:db:docdb-2024-06-12-19-45-21", + IAMDatabaseAuthenticationEnabled: false, + CertificateDetails: { + CAIdentifier: "rds-ca-2019", + ValidTill: certPass, + }, + DedicatedLogVolume: false, + }, ]; @@ -65,23 +110,23 @@ const createCache = (instances, instancesErr) => { describe('docdbInstanceCertificateRotated', function () { describe('run', function () { it('should PASS if DocumentDB cluster instance does not need certificate rotation', function (done) { - const cache = createCache(describeDBInstances); - docdbInstanceCertificateRotated.run(cache, { docdb_certificate_rotation_limit: 20 }, (err, results) => { + const cache = createCache([describeDBInstances[1]]); + docdbInstanceCertificateRotated.run(cache, { docdb_certificate_rotation_limit: 30 }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('DocumentDB cluster instance does not need certificate rotation as it expires in 29 days of 20 days limit'); + expect(results[0].message).to.include('DocumentDB cluster instance does not need certificate rotation as it expires in 61 days of 30 days limit'); expect(results[0].region).to.equal('us-east-1'); done(); }); }); - it('should FAIL if DocumentDB cluster instance does not need certificate rotation', function (done) { - const cache = createCache(describeDBInstances); - docdbInstanceCertificateRotated.run(cache, { docdb_certificate_rotation_limit: 40 }, (err, results) => { + it('should FAIL if DocumentDB cluster instance needs certificate rotation', function (done) { + const cache = createCache([describeDBInstances[0]]); + docdbInstanceCertificateRotated.run(cache, { docdb_certificate_rotation_limit: 30 }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('DocumentDB cluster instance needs certificate rotation as it expires in 29 days of 40 days limit'); + expect(results[0].message).to.include('DocumentDB cluster instance needs certificate rotation as it expires in -31 days of 30 days limit'); expect(results[0].region).to.equal('us-east-1'); done(); }); From 4c0ad8a1d12e64bc49c78c4aa6136647560dcbc7 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 20 Jun 2024 15:01:46 +0500 Subject: [PATCH 21/91] update spec --- plugins/aws/documentDB/docdbCertificateRotated.spec.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/aws/documentDB/docdbCertificateRotated.spec.js b/plugins/aws/documentDB/docdbCertificateRotated.spec.js index 66d4d85108..a3c3fe555e 100644 --- a/plugins/aws/documentDB/docdbCertificateRotated.spec.js +++ b/plugins/aws/documentDB/docdbCertificateRotated.spec.js @@ -114,7 +114,6 @@ describe('docdbInstanceCertificateRotated', function () { docdbInstanceCertificateRotated.run(cache, { docdb_certificate_rotation_limit: 30 }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('DocumentDB cluster instance does not need certificate rotation as it expires in 61 days of 30 days limit'); expect(results[0].region).to.equal('us-east-1'); done(); }); @@ -126,7 +125,6 @@ describe('docdbInstanceCertificateRotated', function () { docdbInstanceCertificateRotated.run(cache, { docdb_certificate_rotation_limit: 30 }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('DocumentDB cluster instance needs certificate rotation as it expires in -31 days of 30 days limit'); expect(results[0].region).to.equal('us-east-1'); done(); }); @@ -138,7 +136,6 @@ describe('docdbInstanceCertificateRotated', function () { docdbInstanceCertificateRotated.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No DocumentDB cluster instances found'); expect(results[0].region).to.equal('us-east-1'); done(); }); From a536e5a64c5059d56360ab18bb228e219652ee50 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Sat, 13 Jul 2024 18:50:43 +0500 Subject: [PATCH 22/91] H-plugin QLDB Ledger Deletion Protection Enabled --- exports.js | 1 + plugins/aws/qldb/ledgerDeletionProtection.js | 73 ++++++++++++++ .../aws/qldb/ledgerDeletionProtection.spec.js | 96 +++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 plugins/aws/qldb/ledgerDeletionProtection.js create mode 100644 plugins/aws/qldb/ledgerDeletionProtection.spec.js diff --git a/exports.js b/exports.js index dcbf2a3dbb..e5850da5ac 100644 --- a/exports.js +++ b/exports.js @@ -497,6 +497,7 @@ module.exports = { 'ssmSessionDuration' : require(__dirname + '/plugins/aws/ssm/ssmSessionDuration'), 'ledgerEncrypted' : require(__dirname + '/plugins/aws/qldb/ledgerEncrypted'), + 'ledgerDeletionProtection' : require(__dirname + '/plugins/aws/qldb/ledgerDeletionProtection'), 'lambdaAdminPrivileges' : require(__dirname + '/plugins/aws/lambda/lambdaAdminPrivileges.js'), 'envVarsClientSideEncryption' : require(__dirname + '/plugins/aws/lambda/envVarsClientSideEncryption.js'), diff --git a/plugins/aws/qldb/ledgerDeletionProtection.js b/plugins/aws/qldb/ledgerDeletionProtection.js new file mode 100644 index 0000000000..586866037c --- /dev/null +++ b/plugins/aws/qldb/ledgerDeletionProtection.js @@ -0,0 +1,73 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'Ledger Deletion Protection', + category: 'QLDB', + domain: 'Databases', + severity: 'Medium', + description: 'Ensure that AWS QLDB ledger has deletion protection feature enabled.', + more_info: 'Enabling deletion protection feature for Amazon QLDB ledger acts as a safety net, preventing accidental database deletions or deletion by an unauthorized user. It ensures that the data stays secure and accessible at all times.', + recommended_action: 'Modify QLDB ledger and enable deletion protection.', + link: 'https://docs.aws.amazon.com/qldb/latest/developerguide/ledger-management.basics.html', + apis: ['QLDB:listLedgers','QLDB:describeLedger','STS:getCallerIdentity'], + realtime_triggers: ['qldb:CreateLedger', 'qldb:UpdateLedger', 'qldb:DeleteLedger'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + var defaultRegion = helpers.defaultRegion(settings); + var awsOrGov = helpers.defaultPartition(settings); + var accountId = helpers.addSource(cache, source, ['sts', 'getCallerIdentity', defaultRegion, 'data']); + + async.each(regions.qldb, function(region, rcb){ + var listLedgers = helpers.addSource(cache, source, + ['qldb', 'listLedgers', region]); + + if (!listLedgers) return rcb(); + + if (listLedgers.err || !listLedgers.data) { + helpers.addResult(results, 3, + 'Unable to query Ledgers: ' + helpers.addError(listLedgers), region); + return rcb(); + } + + if (!listLedgers.data.length) { + helpers.addResult(results, 0, 'No Ledgers found', region); + return rcb(); + } + + for (let ledger of listLedgers.data) { + if (!ledger.Name) continue; + + let resource = `arn:${awsOrGov}:qldb:${region}:${accountId}:ledger/${ledger.Name}`; + + var describeLedger = helpers.addSource(cache, source, + ['qldb', 'describeLedger', region, ledger.Name]); + + if (!describeLedger || describeLedger.err || !describeLedger.data ) { + helpers.addResult(results, 3, + `Unable to get Ledgers description: ${helpers.addError(describeLedger)}`, + region, resource); + continue; + } + + if (describeLedger.data.DeletionProtection) { + helpers.addResult(results, 0, + 'QLDB ledger has deletion protection enabled', + region, resource); + } else { + helpers.addResult(results, 2, + 'QLDB ledger does not have deletion protection enabled', + region, resource); + } + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/aws/qldb/ledgerDeletionProtection.spec.js b/plugins/aws/qldb/ledgerDeletionProtection.spec.js new file mode 100644 index 0000000000..a22d30c62c --- /dev/null +++ b/plugins/aws/qldb/ledgerDeletionProtection.spec.js @@ -0,0 +1,96 @@ +var expect = require('chai').expect; +var ledgerDeletionProtection = require('./ledgerDeletionProtection'); + +const listLedgers = [ + { + "Name": "test-ledger", + "State": "ACTIVE", + "CreationDateTime": "2021-11-19T16:29:08.899000+05:00" + } +]; + +const describeLedger = [ + { + "Name": "test-ledger", + "Arn": "arn:aws:qldb:us-east-1:000111222333:ledger/test-ledger", + "State": "ACTIVE", + "CreationDateTime": "2021-11-19T16:29:08.899000+05:00", + "PermissionsMode": "STANDARD", + "DeletionProtection": true, + }, + { + "Name": "test-ledger", + "Arn": "arn:aws:qldb:us-east-1:000111222333:ledger/test-ledger", + "State": "ACTIVE", + "CreationDateTime": "2021-11-19T16:29:08.899000+05:00", + "PermissionsMode": "STANDARD", + "DeletionProtection": false, + } +]; + +const createCache = (ledgers, describeLedger, ledgersErr, describeLedgerErr) => { + var name = (ledgers && ledgers.length) ? ledgers[0].Name: null; + return { + qldb: { + listLedgers: { + 'us-east-1': { + err: ledgersErr, + data: ledgers + }, + }, + describeLedger: { + 'us-east-1': { + [name]: { + data: describeLedger, + err: describeLedgerErr + } + } + } + }, + }; +}; + +describe('ledgerDeletionProtection', function () { + describe('run', function () { + it('should PASS if QLDB ledger has deletion protection enabled', function (done) { + const cache = createCache(listLedgers, describeLedger[0]); + ledgerDeletionProtection.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + + it('should FAIL if QLDb ledger does not have deletion protection enabled', function (done) { + const cache = createCache(listLedgers, describeLedger[1]); + ledgerDeletionProtection.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + + it('should PASS if no QLDB ledgers found', function (done) { + const cache = createCache([]); + ledgerDeletionProtection.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + + it('should UNKNOWN if unable to list QLDB ledgers', function (done) { + const cache = createCache(null, null, null, { message: "Unable to list QLDB ledgers" }); + ledgerDeletionProtection.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + + }); +}) From 7e9ae8ed271f0e8d39f1106c88d2474250315da7 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Sat, 13 Jul 2024 22:23:58 +0500 Subject: [PATCH 23/91] H-plugin QLDB Ledger Has Tags --- exports.js | 1 + plugins/aws/qldb/ledgerHasTags.js | 58 ++++++++++++++ plugins/aws/qldb/ledgerHasTags.spec.js | 106 +++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 plugins/aws/qldb/ledgerHasTags.js create mode 100644 plugins/aws/qldb/ledgerHasTags.spec.js diff --git a/exports.js b/exports.js index dcbf2a3dbb..61bc57fc42 100644 --- a/exports.js +++ b/exports.js @@ -497,6 +497,7 @@ module.exports = { 'ssmSessionDuration' : require(__dirname + '/plugins/aws/ssm/ssmSessionDuration'), 'ledgerEncrypted' : require(__dirname + '/plugins/aws/qldb/ledgerEncrypted'), + 'ledgerHasTags' : require(__dirname + '/plugins/aws/qldb/ledgerHasTags'), 'lambdaAdminPrivileges' : require(__dirname + '/plugins/aws/lambda/lambdaAdminPrivileges.js'), 'envVarsClientSideEncryption' : require(__dirname + '/plugins/aws/lambda/envVarsClientSideEncryption.js'), diff --git a/plugins/aws/qldb/ledgerHasTags.js b/plugins/aws/qldb/ledgerHasTags.js new file mode 100644 index 0000000000..649b00fa11 --- /dev/null +++ b/plugins/aws/qldb/ledgerHasTags.js @@ -0,0 +1,58 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'Ledger Has Tags', + category: 'QLDB', + domain: 'Databases', + severity: 'Low', + description: 'Ensure that AWS QLDB ledger has tags associated.', + more_info: 'Tags help you to group resources together that are related to or associated with each other. It is a best practice to tag cloud resources to better organize and gain visibility into their usage.', + recommended_action: 'Modify QLDB ledger and add tags.', + link: 'https://docs.aws.amazon.com/qldb/latest/developerguide/tagging.html', + apis: ['QLDB:listLedgers','ResourceGroupsTaggingAPI:getResources','STS:getCallerIdentity'], + realtime_triggers: ['qldb:CreateLedger', 'qldb:DeleteLedger', 'qldb:TagResource', 'qldb:UntagResource'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + var defaultRegion = helpers.defaultRegion(settings); + var awsOrGov = helpers.defaultPartition(settings); + var accountId = helpers.addSource(cache, source, ['sts', 'getCallerIdentity', defaultRegion, 'data']); + + async.each(regions.qldb, function(region, rcb){ + var listLedgers = helpers.addSource(cache, source, + ['qldb', 'listLedgers', region]); + + if (!listLedgers) return rcb(); + + if (listLedgers.err || !listLedgers.data) { + helpers.addResult(results, 3, + 'Unable to query Ledgers: ' + helpers.addError(listLedgers), region); + return rcb(); + } + + if (!listLedgers.data.length) { + helpers.addResult(results, 0, 'No Ledgers found', region); + return rcb(); + } + + const arnList = []; + + for (let ledger of listLedgers.data) { + if (!ledger.Name) continue; + + let resource = `arn:${awsOrGov}:qldb:${region}:${accountId}:ledger/${ledger.Name}`; + arnList.push(resource); + } + + helpers.checkTags(cache, 'QLDB ledger', arnList, region, results, settings); + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/aws/qldb/ledgerHasTags.spec.js b/plugins/aws/qldb/ledgerHasTags.spec.js new file mode 100644 index 0000000000..0e06e273d7 --- /dev/null +++ b/plugins/aws/qldb/ledgerHasTags.spec.js @@ -0,0 +1,106 @@ +var expect = require('chai').expect; +var ledgerHasTags = require('./ledgerHasTags'); + +const listLedgers = [ + { + "Name": "test-ledger", + "State": "ACTIVE", + "CreationDateTime": "2021-11-19T16:29:08.899000+05:00" + } +]; + +const getResources = [ + { + "ResourceARN": "arn:aws:qldb:us-east-1:000111222333:ledger/test-ledger", + "Tags": [], + }, + { + "ResourceARN": "arn:aws:qldb:us-east-1:000111222333:ledger/test-ledger", + "Tags": [{key: 'value'}], + } +] + +const createCache = (ledgers, rgData, ledgersErr) => { + var name = (ledgers && ledgers.length) ? ledgers[0].Name: null; + return { + qldb: { + listLedgers: { + 'us-east-1': { + err: ledgersErr, + data: ledgers + }, + }, + }, + resourcegroupstaggingapi: { + getResources: { + 'us-east-1':{ + err: null, + data: rgData + } + } + }, + sts: { + getCallerIdentity: { + 'us-east-1': { + data: '000111222333' + } + } + } + }; +}; + +describe('ledgerHasTags', function () { + describe('run', function () { + it('should PASS if QLDB ledger has tags', function (done) { + const cache = createCache(listLedgers, [getResources[1]]); + ledgerHasTags.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + + it('should FAIL if QLDb ledger does not have tags', function (done) { + const cache = createCache(listLedgers, [getResources[0]]); + ledgerHasTags.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + + it('should PASS if no QLDB ledgers found', function (done) { + const cache = createCache([]); + ledgerHasTags.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + + it('should UNKNOWN if unable to list QLDB ledgers', function (done) { + const cache = createCache(null, null, null, { message: "Unable to list QLDB ledgers" }); + ledgerHasTags.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + + it('should give unknown result if unable to query resource group tagging api', function (done) { + const cache = createCache([listLedgers[0]],null); + ledgerHasTags.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('Unable to query all resources') + done(); + }); + }); + + }); +}) From c7e60615a34392f497c254911516f6bdad606669 Mon Sep 17 00:00:00 2001 From: fatima99s Date: Sun, 14 Jul 2024 21:08:55 +0500 Subject: [PATCH 24/91] FS-Azure/MysqlserverLogAlerts --- exports.js | 1 + .../mysqlFlexibleServerLoggingEnabled.js | 34 +++ .../mysqlFlexibleServerLoggingEnabled.spec.js | 234 ++++++++++++++++++ 3 files changed, 269 insertions(+) create mode 100644 plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.js create mode 100644 plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js diff --git a/exports.js b/exports.js index dcbf2a3dbb..93e22550dd 100644 --- a/exports.js +++ b/exports.js @@ -830,6 +830,7 @@ module.exports = { 'loadBalancerLoggingEnabled' : require(__dirname + '/plugins/azure/logalerts/loadBalancerLoggingEnabled.js'), 'virtualMachineLogging' : require(__dirname + '/plugins/azure/logalerts/virtualMachineLogging.js'), 'flexibleServerLoggingEnabled' : require(__dirname + '/plugins/azure/logalerts/flexibleServerLoggingEnabled.js'), + 'mysqlFlexibleServerLoggingEnabled': require(__dirname + '/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.js'), 'postgreSqlDBLoggingEnabled' : require(__dirname + '/plugins/azure/logalerts/postgreSqlDBLoggingEnabled.js'), 'sqlServerDatabaseRenameAlert' : require(__dirname + '/plugins/azure/logalerts/sqlServerDatabaseRenameAlert.js'), 'virtualMachinesPowerOffAlert' : require(__dirname + '/plugins/azure/logalerts/virtualMachinesPowerOffAlert.js'), diff --git a/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.js b/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.js new file mode 100644 index 0000000000..2d73fd945e --- /dev/null +++ b/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.js @@ -0,0 +1,34 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'MySQL Flexible Server Logging Enabled', + category: 'Log Alerts', + domain: 'Management and Governance', + severity: 'Medium', + description: 'Ensures Activity Log alerts for create/update and delete MySQL Flexible Server events are enabled.', + more_info: 'Monitoring for create/update and delete MySQL Flexible Server events gives insight into network access changes and may reduce the time it takes to detect suspicious activity.', + recommended_action: 'Add a new log alert to the Alerts service that monitors for MySQL Flexible Server create/update and delete events.', + link: 'https://learn.microsoft.com/en-us/azure/azure-monitor/platform/activity-log-alerts', + apis: ['activityLogAlerts:listBySubscriptionId'], + realtime_triggers: ['microsoftinsights:activitylogalerts:write', 'microsoftinsights:activitylogalerts:delete'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.activityLogAlerts, function(location, rcb) { + var conditionResource = 'microsoft.dbformysql/flexibleservers'; + var text = 'MySQL Flexible Server'; + var activityLogAlerts = helpers.addSource(cache, source, + ['activityLogAlerts', 'listBySubscriptionId', location]); + + helpers.checkLogAlerts(activityLogAlerts, conditionResource, text, results, location); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js b/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js new file mode 100644 index 0000000000..6815ac07ae --- /dev/null +++ b/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js @@ -0,0 +1,234 @@ +var expect = require("chai").expect; +var mysqlFlexibleServerLoggingEnabled = require("./mysqlFlexibleServerLoggingEnabled"); + +const activityLogAlerts = [ + { + "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourceGroups/Default-ActivityLogAlerts/providers/microsoft.insights/activityLogAlerts/NSG2", + "name": "NSG2", + "type": "Microsoft.Insights/ActivityLogAlerts", + "location": "global", + "tags": {}, + "scopes": [ + "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a" + ], + "enabled": true, + "condition": { + "allOf": [ + { + "field": "category", + "equals": "Security" + }, + { + "field": "operationName", + "equals": "Microsoft.DBforMySQL/flexibleservers/" + } + ] + }, + "actions": { + "actionGroups": [ + { + "actionGroupId": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourcegroups/default-activitylogalerts/providers/microsoft.insights/actiongroups/testactiong", + "webhookProperties": {} + } + ] + } + }, + { + "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourceGroups/Default-ActivityLogAlerts/providers/microsoft.insights/activityLogAlerts/NSG2", + "name": "NSG2", + "type": "Microsoft.Insights/ActivityLogAlerts", + "location": "global", + "tags": {}, + "scopes": [ + "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a" + ], + "enabled": true, + "condition": { + "allOf": [ + { + "field": "category", + "equals": "Security" + }, + { + "field": "operationName", + "equals": "Microsoft.DBforMySQL/flexibleServers/write" + }, + { + "field": "operationName", + "equals": "Microsoft.DBforMySQL/flexibleServers/delete" + } + ] + }, + "actions": { + "actionGroups": [ + { + "actionGroupId": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourcegroups/default-activitylogalerts/providers/microsoft.insights/actiongroups/testactiong", + "webhookProperties": {} + } + ] + } + }, + { + "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourceGroups/Default-ActivityLogAlerts/providers/microsoft.insights/activityLogAlerts/NSG2", + "name": "NSG2", + "type": "Microsoft.Insights/ActivityLogAlerts", + "location": "global", + "tags": {}, + "scopes": [ + "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a" + ], + "enabled": true, + "condition": { + "allOf": [ + { + "field": "category", + "equals": "Security" + }, + { + "field": "operationName", + "equals": "Microsoft.DBforMySQL/flexibleServers/write" + } + ] + }, + "actions": { + "actionGroups": [ + { + "actionGroupId": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourcegroups/default-activitylogalerts/providers/microsoft.insights/actiongroups/testactiong", + "webhookProperties": {} + } + ] + } + }, + { + "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourceGroups/Default-ActivityLogAlerts/providers/microsoft.insights/activityLogAlerts/NSG2", + "name": "NSG2", + "type": "Microsoft.Insights/ActivityLogAlerts", + "location": "global", + "tags": {}, + "scopes": [ + "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a" + ], + "enabled": true, + "condition": { + "allOf": [ + { + "field": "category", + "equals": "Security" + }, + { + "field": "operationName", + "equals": "Microsoft.DBforMySQL/flexibleServers/delete" + } + ] + }, + "actions": { + "actionGroups": [ + { + "actionGroupId": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourcegroups/default-activitylogalerts/providers/microsoft.insights/actiongroups/testactiong", + "webhookProperties": {} + } + ] + } + } +]; + +const createCache = (err, data) => { + return { + activityLogAlerts: { + listBySubscriptionId: { + global: { + err: err, + data: data, + }, + }, + }, + }; +}; + +describe("mysqlFlexibleServerLoggingEnabled", function () { + describe("run", function () { + it("should give failing result if no activity log alerts found", function (done) { + const cache = createCache(null, []); + mysqlFlexibleServerLoggingEnabled.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 Activity Alerts found"); + expect(results[0].region).to.equal("global"); + done(); + }); + }); + + it("should give unknown result if unable to query for Activity alerts", function (done) { + const cache = createCache(null); + mysqlFlexibleServerLoggingEnabled.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 Activity Alerts"); + expect(results[0].region).to.equal("global"); + done(); + }); + }); + + it("should give failing result if MySQL Flexible Server write and delete is not enabled", function (done) { + const cache = createCache(null, [activityLogAlerts[0]]); + mysqlFlexibleServerLoggingEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include( + "Log Alert for MySQL Flexible Server write and delete is not enabled" + ); + expect(results[0].region).to.equal("global"); + done(); + }); + }); + + it("should give failing and passing results if MySQL Flexible Server delete is not enaled but write is enabled", function (done) { + const cache = createCache(null, [activityLogAlerts[2]]); + mysqlFlexibleServerLoggingEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(2); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include( + "Log alert for MySQL Flexible Server write is enabled" + ); + expect(results[0].region).to.equal("global"); + expect(results[1].status).to.equal(2); + expect(results[1].message).to.include( + "Log Alert for MySQL Flexible Server delete is not enabled" + ); + expect(results[0].region).to.equal("global"); + done(); + }); + }); + + it("should give failing and passing results if MySQL Flexible Server write is not enaled but delete is enabled", function (done) { + const cache = createCache(null, [activityLogAlerts[3]]); + mysqlFlexibleServerLoggingEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(2); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include( + "Log alert for MySQL Flexible Server delete is enabled" + ); + expect(results[0].region).to.equal("global"); + expect(results[1].status).to.equal(2); + expect(results[1].message).to.include( + "Log alert for MySQL Flexible Server write is not enabled" + ); + expect(results[0].region).to.equal("global"); + done(); + }); + }); + + it("should give passing result if MySQL Flexible Server Database write and delete is enabled", function (done) { + const cache = createCache(null, [activityLogAlerts[1]]); + mysqlFlexibleServerLoggingEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include( + "Log Alert for MySQL Flexible Server write and delete is enabled" + ); + expect(results[0].region).to.equal("global"); + done(); + }); + }); + }); +}); From 69e81c47ffa0c95404dac15caa9ffc891300cedd Mon Sep 17 00:00:00 2001 From: fatima99s Date: Sun, 14 Jul 2024 21:34:44 +0500 Subject: [PATCH 25/91] FS-Azure/mysqlCmk --- exports.js | 1 + .../mysqlFlexibleServerCMKEncrypted.js | 53 +++++++++ .../mysqlFlexibleServerCMKEncrypted.spec.js | 103 ++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js create mode 100644 plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.spec.js diff --git a/exports.js b/exports.js index dcbf2a3dbb..f8783d3fdf 100644 --- a/exports.js +++ b/exports.js @@ -867,6 +867,7 @@ module.exports = { 'mysqlFlexibleServersMinTls' : require(__dirname + '/plugins/azure/mysqlserver/mysqlFlexibleServersMinTls.js'), 'mysqlFlexibleServerVersion' : require(__dirname + '/plugins/azure/mysqlserver/mysqlFlexibleServerVersion.js'), 'mysqlServerHasTags' : require(__dirname + '/plugins/azure/mysqlserver/mysqlServerHasTags.js'), + 'mysqlFlexibleServerCMKEncrypted': require(__dirname + '/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js'), 'mysqlFlexibleServerPublicAccess': require(__dirname + '/plugins/azure/mysqlserver/mysqlFlexibleServerPublicAccess.js'), 'mysqlFlexibleServerDignosticLogs': require(__dirname + '/plugins/azure/mysqlserver/mysqlFlexibleServerDignosticLogs.js'), 'mysqlFlexibleServerIdentity' : require(__dirname + '/plugins/azure/mysqlserver/mysqlFlexibleServerIdentity.js'), diff --git a/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js b/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js new file mode 100644 index 0000000000..d164e6674d --- /dev/null +++ b/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js @@ -0,0 +1,53 @@ +const async = require('async'); +const helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'MySQL Flexible Server CMK Encrypted', + category: 'MySQL Server', + domain: 'Databases', + severity: 'High', + description: 'Ensures that MySQL flexible servers are encrypted using CMK.', + more_info: 'MySQL flexible server allows you to encrypt data using customer-managed keys (CMK) instead of using platform-managed keys, which are enabled by default. Using CMK encryption offers enhanced security and compliance, allowing centralized management and control of encryption keys through Azure Key Vault.', + recommended_action: 'Modify MySQL flexible server and disable public network access.', + link: 'https://learn.microsoft.com/en-us/azure/mysql/flexible-server/concepts-customer-managed-key', + apis: ['servers:listMysqlFlexibleServer'], + realtime_triggers: ['microsoftdbformysql:flexibleservers:write','microsoftdbformysql:flexibleservers:delete'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + + async.each(locations.servers, (location, rcb) => { + const servers = helpers.addSource(cache, source, + ['servers', 'listMysqlFlexibleServer', location]); + + if (!servers) return rcb(); + + if (servers.err || !servers.data) { + helpers.addResult(results, 3, + 'Unable to query for MySQL flexible servers: ' + helpers.addError(servers), location); + return rcb(); + } + + if (!servers.data.length) { + helpers.addResult(results, 0, 'No existing MySQL flexible servers found', location); + return rcb(); + } + + for (var flexibleServer of servers.data) { + if (!flexibleServer.id) continue; + + if (flexibleServer.dataEncryption && flexibleServer.dataEncryption.primaryKeyURI ) { + helpers.addResult(results, 0, 'MySQL flexible server is encrypted using CMK', location, flexibleServer.id); + } else { + helpers.addResult(results, 2, 'MySQL flexible server is not encrypted using CMK', location, flexibleServer.id); + } + } + rcb(); + }, function() { + // Global checking goes here + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.spec.js b/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.spec.js new file mode 100644 index 0000000000..418c8a2f7a --- /dev/null +++ b/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.spec.js @@ -0,0 +1,103 @@ +var assert = require('assert'); +var expect = require('chai').expect; +var auth = require('./mysqlFlexibleServerCMKEncrypted'); + +const createCache = (err, list) => { + return { + servers: { + listMysqlFlexibleServer: { + 'eastus': { + err: err, + data: list + } + } + } + } +}; + +describe('mysqlFlexibleServerManagedIdentity', function() { + describe('run', function() { + it('should PASS if no existing servers found', function(done) { + const callback = (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No existing MySQL flexible servers found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + null, + [], + {} + ); + + auth.run(cache, {}, callback); + }); + + it('should FAIL if MySQL server is not CMK encrypted', function(done) { + const callback = (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('MySQL flexible server is not encrypted using CMK'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + null, + [ + { + "id": "/subscriptions/12345/resourceGroups/Default/providers/Microsoft.DBforMySQL/flexibleServers/test-server", + "type": "Microsoft.DBforMySQL/flexibleServers", + "version": '5.8' + } + ], + ); + + auth.run(cache, {}, callback); + }); + + it('should PASS if MySQL server is CMK encrypted', function(done) { + const callback = (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('MySQL flexible server is encrypted using CMK'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + null, + [ + { + "id": "/subscriptions/12345/resourceGroups/Default/providers/Microsoft.DBforMySQL/flexibleServers/test-server", + "type": "Microsoft.DBforMySQL/flexibleServers", + "version": "8.0", + "dataEncryption": { + "primaryKeyURI" : "https://test.vault.azure.net/keys/test2/9e0e3453676456e" + } + } + ] + ); + + auth.run(cache, {}, callback); + }); + + it('should UNKNOWN if unable to query for server', function(done) { + const callback = (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 MySQL flexible servers: '); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + null, null + ); + + auth.run(cache, {}, callback); + }); + }) +}) \ No newline at end of file From bf2d5e9cf5b6a6272d216bfe239c9b33950ea04d Mon Sep 17 00:00:00 2001 From: fatima99s Date: Sun, 14 Jul 2024 23:05:04 +0500 Subject: [PATCH 26/91] FS-Azure/MLRegisteryPlublicAccess --- exports.js | 2 + helpers/azure/api.js | 6 +- .../machinelearning/mlRegistryPublicAccess.js | 56 +++++++++++ .../mlRegistryPublicAccess.spec.js | 94 +++++++++++++++++++ .../workspacePublicAccessDisabled.js | 2 +- 5 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 plugins/azure/machinelearning/mlRegistryPublicAccess.js create mode 100644 plugins/azure/machinelearning/mlRegistryPublicAccess.spec.js diff --git a/exports.js b/exports.js index dcbf2a3dbb..81848cc733 100644 --- a/exports.js +++ b/exports.js @@ -737,6 +737,8 @@ module.exports = { 'workspacePublicAccessDisabled' : require(__dirname + '/plugins/azure/machinelearning/workspacePublicAccessDisabled.js'), 'workspaceLoggingEnabled' : require(__dirname + '/plugins/azure/machinelearning/workspaceLoggingEnabled.js'), 'mlWorkspaceHasTags' : require(__dirname + '/plugins/azure/machinelearning/mlWorkspaceHasTags.js'), + 'mlRegistryPublicAccess' : require(__dirname + '/plugins/azure/machinelearning/mlRegistryPublicAccess.js'), + 'minimumTlsVersion' : require(__dirname + '/plugins/azure/redisCache/minimumTlsVersion.js'), diff --git a/helpers/azure/api.js b/helpers/azure/api.js index 000b92f186..8d6384fc73 100644 --- a/helpers/azure/api.js +++ b/helpers/azure/api.js @@ -380,7 +380,11 @@ var calls = { machineLearning: { listWorkspaces: { url: 'https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.MachineLearningServices/workspaces?api-version=2024-04-01' - } + }, + listRegistries: { + url: 'https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.MachineLearningServices/registries?api-version=2024-04-01' + }, + }, loadBalancers: { listAll: { diff --git a/plugins/azure/machinelearning/mlRegistryPublicAccess.js b/plugins/azure/machinelearning/mlRegistryPublicAccess.js new file mode 100644 index 0000000000..30f672be0a --- /dev/null +++ b/plugins/azure/machinelearning/mlRegistryPublicAccess.js @@ -0,0 +1,56 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Machine Learning Registry Public Access Disabled', + category: 'AI & ML', + domain: 'Machine Learning', + severity: 'High', + description: 'Ensures that Azure Machine Learning registries are not publicly accessible.', + more_info: 'Disabling public network access for Azure Machine Learning registries helps prevent data leakage risks by ensuring that your registries are not accessible over the public internet. Instead, private endpoints provide network isolation, securing connections within a virtual network (VNet) and preventing exposure of sensitive data.', + recommended_action: 'Ensure that Azure Machine Learning registries have public network access disabled.', + link: 'https://learn.microsoft.com/en-us/azure/machine-learning/how-to-registry-network-isolation', + apis: ['machineLearning:listRegistries'], + realtime_triggers: ['microsoftmachinelearningservices:registries:write','microsoftmachinelearningservices:registries:delete'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + + async.each(locations.machineLearning, function(location, rcb) { + var machineLearningRegistries = helpers.addSource(cache, source, + ['machineLearning', 'listRegistries', location]); + + if (!machineLearningRegistries) return rcb(); + + if (machineLearningRegistries.err || !machineLearningRegistries.data) { + helpers.addResult(results, 3, + 'Unable to query for Machine Learning registries: ' + helpers.addError(machineLearningRegistries), location); + return rcb(); + } + + if (!machineLearningRegistries.data.length) { + helpers.addResult(results, 0, 'No existing Machine Learning registries found', location); + return rcb(); + } + + for (let registry of machineLearningRegistries.data) { + if (!registry.id) continue; + + if (registry.publicNetworkAccess && registry.publicNetworkAccess.toLowerCase()=='disabled') { + helpers.addResult(results, 0, + 'Machine Learning registry has public network access disabled', location, registry.id); + } else { + helpers.addResult(results, 2, + 'Machine Learning registry has public network access enabled', location, registry.id); + } + } + + rcb(); + }, function() { + // Global checking goes here + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/machinelearning/mlRegistryPublicAccess.spec.js b/plugins/azure/machinelearning/mlRegistryPublicAccess.spec.js new file mode 100644 index 0000000000..a3c21ad047 --- /dev/null +++ b/plugins/azure/machinelearning/mlRegistryPublicAccess.spec.js @@ -0,0 +1,94 @@ +var expect = require('chai').expect; +var mlRegistryPublicAccess = require('./mlRegistryPublicAccess'); + +const registry = [ + { + "id": "/subscriptions/12345667/resourceGroups/test/providers/Microsoft.MachineLearningServices/registries/test1", + "name": "test", + "type": "Microsoft.MachineLearningServices/registries", + "tags": { + "test": "test" + }, + "publicNetworkAccess" : "Disabled" + + }, + { + "id": "/subscriptions/12345667/resourceGroups/test/providers/Microsoft.MachineLearningServices/registries/test1", + "name": "test", + "type": "Microsoft.MachineLearningServices/registries", + "publicNetworkAccess" : "Enabled" + }, + +]; + +const createCache = (registries) => { + return { + machineLearning: { + listRegistries: { + 'eastus': { + data: registries + } + } + } + }; +}; + +const createErrorCache = () => { + return { + machineLearning: { + listRegistries: { + 'eastus': {} + } + } + }; +}; + +describe('mlRegistryPublicAccess', function() { + describe('run', function() { + it('should give passing result if no Machine Learning registry found', function(done) { + const cache = createCache([]); + mlRegistryPublicAccess.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No existing Machine Learning registries found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Machine Learning registry', function(done) { + const cache = createErrorCache(); + mlRegistryPublicAccess.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 Machine Learning registries: '); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + + it('should give passing result if Machine Learning registry has public access disabled', function(done) { + const cache = createCache([registry[0]]); + mlRegistryPublicAccess.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Machine Learning registry has public network access disabled'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if Machine Learning registry does not have public access disabled', function(done) { + const cache = createCache([registry[1]]); + mlRegistryPublicAccess.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Machine Learning registry has public network access enabled'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + }); +}); \ No newline at end of file diff --git a/plugins/azure/machinelearning/workspacePublicAccessDisabled.js b/plugins/azure/machinelearning/workspacePublicAccessDisabled.js index ed3b46012e..81ddbbb611 100644 --- a/plugins/azure/machinelearning/workspacePublicAccessDisabled.js +++ b/plugins/azure/machinelearning/workspacePublicAccessDisabled.js @@ -11,7 +11,7 @@ module.exports = { recommended_action: 'Ensure that Azure Machine Learning workspaces have public network access disabled.', link: 'https://learn.microsoft.com/en-us/azure/machine-learning/how-to-secure-workspace-vnet', apis: ['machineLearning:listWorkspaces'], - realtime_triggers: ['microsoftcognitiveservices:accounts:write','microsoftcognitiveservices:accounts:delete'], + realtime_triggers: ['microsoft:machinelearningservices:workspaces:write', 'microsoft:machinelearningservices:workspaces:delete'], run: function(cache, settings, callback) { const results = []; From 3ef676834f07ae19a5ef8c9c8786888111fcca30 Mon Sep 17 00:00:00 2001 From: fatima99s Date: Sun, 14 Jul 2024 23:16:10 +0500 Subject: [PATCH 27/91] FS-Azure/MLRegistriesTags --- exports.js | 1 + .../machinelearning/mlRegistryHasTags.js | 56 +++++++++++ .../machinelearning/mlRegistryHasTags.spec.js | 94 +++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 plugins/azure/machinelearning/mlRegistryHasTags.js create mode 100644 plugins/azure/machinelearning/mlRegistryHasTags.spec.js diff --git a/exports.js b/exports.js index dcbf2a3dbb..114f04d01b 100644 --- a/exports.js +++ b/exports.js @@ -736,6 +736,7 @@ module.exports = { 'workspacePublicAccessDisabled' : require(__dirname + '/plugins/azure/machinelearning/workspacePublicAccessDisabled.js'), 'workspaceLoggingEnabled' : require(__dirname + '/plugins/azure/machinelearning/workspaceLoggingEnabled.js'), + 'mlRegistryHasTags' : require(__dirname + '/plugins/azure/machinelearning/mlRegistryHasTags.js'), 'mlWorkspaceHasTags' : require(__dirname + '/plugins/azure/machinelearning/mlWorkspaceHasTags.js'), diff --git a/plugins/azure/machinelearning/mlRegistryHasTags.js b/plugins/azure/machinelearning/mlRegistryHasTags.js new file mode 100644 index 0000000000..8b369826d5 --- /dev/null +++ b/plugins/azure/machinelearning/mlRegistryHasTags.js @@ -0,0 +1,56 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Machine Learning Registry Has Tags', + category: 'AI & ML', + domain: 'Machine Learning', + severity: 'High', + description: 'Ensures that Azure Machine Learning registries have tags associated.', + more_info: 'Tags help you to group resources together that are related to or associated with each other. It is a best practice to tag cloud resources to better organize and gain visibility into their usage.', + recommended_action: 'Modify Machine Learning registry and add tags.', + link: 'https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources', + apis: ['machineLearning:listRegistries'], + realtime_triggers: ['microsoftmachinelearningservices:registries:write','microsoftmachinelearningservices:registries:delete'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + + async.each(locations.machineLearning, function(location, rcb) { + var machineLearningRegistries = helpers.addSource(cache, source, + ['machineLearning', 'listRegistries', location]); + + if (!machineLearningRegistries) return rcb(); + + if (machineLearningRegistries.err || !machineLearningRegistries.data) { + helpers.addResult(results, 3, + 'Unable to query for Machine Learning registries: ' + helpers.addError(machineLearningRegistries), location); + return rcb(); + } + + if (!machineLearningRegistries.data.length) { + helpers.addResult(results, 0, 'No existing Machine Learning registries found', location); + return rcb(); + } + + for (let registry of machineLearningRegistries.data) { + if (!registry.id) continue; + + if (registry.tags && Object.entries(registry.tags).length > 0) { + helpers.addResult(results, 0, + 'Machine Learning registry has tags associated', location, registry.id); + } else { + helpers.addResult(results, 2, + 'Machine Learning registry does not have tags associated', location, registry.id); + } + } + + rcb(); + }, function() { + // Global checking goes here + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/machinelearning/mlRegistryHasTags.spec.js b/plugins/azure/machinelearning/mlRegistryHasTags.spec.js new file mode 100644 index 0000000000..b7ecc79e6d --- /dev/null +++ b/plugins/azure/machinelearning/mlRegistryHasTags.spec.js @@ -0,0 +1,94 @@ +var expect = require('chai').expect; +var mlRegistryHasTags = require('./mlRegistryHasTags'); + +const registry = [ + { + "id": "/subscriptions/12345667/resourceGroups/test/providers/Microsoft.MachineLearningServices/registries/test1", + "name": "test", + "type": "Microsoft.MachineLearningServices/registries", + "tags": { + "test": "test" + }, + "publicNetworkAccess" : "Disabled" + + }, + { + "id": "/subscriptions/12345667/resourceGroups/test/providers/Microsoft.MachineLearningServices/registries/test1", + "name": "test", + "type": "Microsoft.MachineLearningServices/registries", + "publicNetworkAccess" : "Enabled" + }, + +]; + +const createCache = (registries) => { + return { + machineLearning: { + listRegistries: { + 'eastus': { + data: registries + } + } + } + }; +}; + +const createErrorCache = () => { + return { + machineLearning: { + listRegistries: { + 'eastus': {} + } + } + }; +}; + +describe('mlRegistryHasTags', function() { + describe('run', function() { + it('should give passing result if no Machine Learning registry found', function(done) { + const cache = createCache([]); + mlRegistryHasTags.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No existing Machine Learning registries found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Machine Learning registry', function(done) { + const cache = createErrorCache(); + mlRegistryHasTags.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 Machine Learning registries: '); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + + it('should give passing result if Machine Learning registry has tags associated', function(done) { + const cache = createCache([registry[0]]); + mlRegistryHasTags.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Machine Learning registry has tags associated'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if Machine Learning registry does not have tags associated', function(done) { + const cache = createCache([registry[1]]); + mlRegistryHasTags.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Machine Learning registry does not have tags associated'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + }); +}); \ No newline at end of file From e876809bb8f81f78b8981642bd74ce6a98390182 Mon Sep 17 00:00:00 2001 From: fatima99s Date: Sun, 14 Jul 2024 23:59:02 +0500 Subject: [PATCH 28/91] FS-Azure/MLWorkspaceCMK --- exports.js | 1 + .../mlWorkspaceCMKEncrypted.js | 55 +++++++++++ .../mlWorkspaceCMKEncrypted.spec.js | 97 +++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js create mode 100644 plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.spec.js diff --git a/exports.js b/exports.js index dcbf2a3dbb..d4411d13f9 100644 --- a/exports.js +++ b/exports.js @@ -735,6 +735,7 @@ module.exports = { 'containerAppHasTags' : require(__dirname + '/plugins/azure/containerapps/containerAppHasTags.js'), 'workspacePublicAccessDisabled' : require(__dirname + '/plugins/azure/machinelearning/workspacePublicAccessDisabled.js'), + 'mlWorkspaceCMKEncrypted' : require(__dirname + '/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js'), 'workspaceLoggingEnabled' : require(__dirname + '/plugins/azure/machinelearning/workspaceLoggingEnabled.js'), 'mlWorkspaceHasTags' : require(__dirname + '/plugins/azure/machinelearning/mlWorkspaceHasTags.js'), diff --git a/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js b/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js new file mode 100644 index 0000000000..617ed20dfe --- /dev/null +++ b/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js @@ -0,0 +1,55 @@ +const async = require('async'); +const helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Machine Learning Workspace CMK Encrypted', + category: 'MySQL Server', + domain: 'Databases', + severity: 'High', + description: 'Ensures that Machine Learning Workspaces are encrypted using CMK.', + more_info: 'Azure Machine Learning allows you to encrypt workspces using customer-managed keys (CMK) instead of using platform-managed keys, which are enabled by default. Using CMK encryption offers enhanced security and compliance, allowing centralized management and control of encryption keys through Azure Key Vault.', + recommended_action: 'Ensure that Machine Learning Workspaces are encrypted using CMK.', + link: 'https://learn.microsoft.com/en-us/azure/machine-learning/concept-customer-managed-keys', + apis: ['machineLearning:listWorkspaces'], + realtime_triggers: ['microsoft:machinelearningservices:workspaces:write', 'microsoft:machinelearningservices:workspaces:delete'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + + async.each(locations.machineLearning, function(location, rcb) { + + var machineLearningWorkspaces = helpers.addSource(cache, source, + ['machineLearning', 'listWorkspaces', location]); + + if (!machineLearningWorkspaces) return rcb(); + + if (machineLearningWorkspaces.err || !machineLearningWorkspaces.data) { + helpers.addResult(results, 3, + 'Unable to query for Machine Learning workspaces: ' + helpers.addError(machineLearningWorkspaces), location); + return rcb(); + } + + if (!machineLearningWorkspaces.data.length) { + helpers.addResult(results, 0, 'No existing Machine Learning workspaces found', location); + return rcb(); + } + + for (let workspace of machineLearningWorkspaces.data) { + if (!workspace.id) continue; + + if (workspace.encryption && workspace.encryption.keyVaultProperties && workspace.encryption.keyVaultProperties.keyIdentifier) { + helpers.addResult(results, 0, 'Machine Learning workspace is encrypted using CMK', location, workspace.id); + } else { + helpers.addResult(results, 2, 'Machine Learning workspace is not encrypted using CMK', location, workspace.id); + } + } + + rcb(); + }, function() { + // Global checking goes here + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.spec.js b/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.spec.js new file mode 100644 index 0000000000..5427b8f472 --- /dev/null +++ b/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.spec.js @@ -0,0 +1,97 @@ +var expect = require('chai').expect; +var mlWorkspaceCMKEncrypted = require('./mlWorkspaceCMKEncrypted'); + +const workspaces = [ + { + "id": "/subscriptions/12345667/resourceGroups/test/providers/Microsoft.MachineLearningServices/workspaces/test1", + "name": "test", + "type": "Microsoft.MachineLearningServices/workspaces", + "encryption": { + "keyVaultProperties": { + "keyIdentifier": "https://dummy.vault.azure.net/keys/test2/9e34232342342343242343", + "identityClientId": null, + "keyVaultArmId": "/subscriptions/12345667/resourceGroups/test1223/providers/Microsoft.KeyVault/vaults/dummy" + }, + } + + + }, + { + "id": "/subscriptions/12345667/resourceGroups/test/providers/Microsoft.MachineLearningServices/workspaces/test1", + "name": "test", + "type": "Microsoft.MachineLearningServices/workspaces", + + }, +]; + +const createCache = (workspaces) => { + return { + machineLearning: { + listWorkspaces: { + 'eastus': { + data: workspaces + } + } + } + }; +}; + +const createErrorCache = () => { + return { + machineLearning: { + listWorkspaces: { + 'eastus': {} + } + } + }; +}; + +describe('mlWorkspaceCMKEncrypted', function() { + describe('run', function() { + it('should give passing result if no Machine Learning workspace found', function(done) { + const cache = createCache([]); + mlWorkspaceCMKEncrypted.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No existing Machine Learning workspaces found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Machine Learning workspaces', function(done) { + const cache = createErrorCache(); + mlWorkspaceCMKEncrypted.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 Machine Learning workspaces: '); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + + it('should give passing result if Machine Learning workspace is not encrypted using CMK', function(done) { + const cache = createCache([workspaces[0]]); + mlWorkspaceCMKEncrypted.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Machine Learning workspace is encrypted using CMK'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if Machine Learning workspace is not CMK encrypted', function(done) { + const cache = createCache([workspaces[1]]); + mlWorkspaceCMKEncrypted.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Machine Learning workspace is not encrypted using CMK'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + }); +}); \ No newline at end of file From 0e2e96123758bc70850a040827d9f3505b941f5d Mon Sep 17 00:00:00 2001 From: fatima99s Date: Mon, 15 Jul 2024 00:27:39 +0500 Subject: [PATCH 29/91] FS-Azure/MLworkspceHBI --- exports.js | 2 + .../azure/machinelearning/mlWorkspaceHBI.js | 57 ++++++++++++ .../machinelearning/mlWorkspaceHBI.spec.js | 92 +++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 plugins/azure/machinelearning/mlWorkspaceHBI.js create mode 100644 plugins/azure/machinelearning/mlWorkspaceHBI.spec.js diff --git a/exports.js b/exports.js index dcbf2a3dbb..b1e2515be1 100644 --- a/exports.js +++ b/exports.js @@ -734,6 +734,8 @@ module.exports = { 'containerAppHttpsOnly' : require(__dirname + '/plugins/azure/containerapps/containerAppHttpsOnly.js'), 'containerAppHasTags' : require(__dirname + '/plugins/azure/containerapps/containerAppHasTags.js'), + + 'mlRegistryPublicAccess' : require(__dirname + '/plugins/azure/machinelearning/mlWorkspaceHBI.js'), 'workspacePublicAccessDisabled' : require(__dirname + '/plugins/azure/machinelearning/workspacePublicAccessDisabled.js'), 'workspaceLoggingEnabled' : require(__dirname + '/plugins/azure/machinelearning/workspaceLoggingEnabled.js'), 'mlWorkspaceHasTags' : require(__dirname + '/plugins/azure/machinelearning/mlWorkspaceHasTags.js'), diff --git a/plugins/azure/machinelearning/mlWorkspaceHBI.js b/plugins/azure/machinelearning/mlWorkspaceHBI.js new file mode 100644 index 0000000000..6e23f223b2 --- /dev/null +++ b/plugins/azure/machinelearning/mlWorkspaceHBI.js @@ -0,0 +1,57 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Machine Learning Workspace High Business Impact Enabled', + category: 'AI & ML', + domain: 'Machine Learning', + severity: 'Medium', + description: 'Ensures that Machine Learning workspaces have High Business Impact (HBI) feature enabled.', + more_info: 'Enabling a high business impact workspace controls the data Microsoft collects for diagnostics and prevents sending confidential telemetry data to Microsoft, ensuring security measures, compliance, and risk management protocols are in place to protect sensitive data.', + recommended_action: 'Ensures that High Business Impact (HBI) feature enabled for Machine Learning workspace.', + link: 'https://learn.microsoft.com/en-us/azure/machine-learning/concept-data-encryption', + apis: ['machineLearning:listWorkspaces'], + realtime_triggers: ['microsoft:machinelearningservices:workspaces:write', 'microsoft:machinelearningservices:workspaces:delete', 'microsoftresources:tags:write'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + + async.each(locations.machineLearning, function(location, rcb) { + + var machineLearningWorkspaces = helpers.addSource(cache, source, + ['machineLearning', 'listWorkspaces', location]); + + if (!machineLearningWorkspaces) return rcb(); + + if (machineLearningWorkspaces.err || !machineLearningWorkspaces.data) { + helpers.addResult(results, 3, + 'Unable to query for Machine Learning workspaces: ' + helpers.addError(machineLearningWorkspaces), location); + return rcb(); + } + + if (!machineLearningWorkspaces.data.length) { + helpers.addResult(results, 0, 'No existing Machine Learning workspaces found', location); + return rcb(); + } + + for (let workspace of machineLearningWorkspaces.data) { + if (!workspace.id) continue; + + if (workspace.hbiWorkspace) { + helpers.addResult(results, 0, + 'Machine Learning workspace has high business impact (HBI) feature enabled', location, workspace.id); + } else { + helpers.addResult(results, 2, + 'Machine Learning workspace does not have high business impact (HBI) feature enabled', location, workspace.id); + } + } + + rcb(); + }, function() { + // Global checking goes here + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/machinelearning/mlWorkspaceHBI.spec.js b/plugins/azure/machinelearning/mlWorkspaceHBI.spec.js new file mode 100644 index 0000000000..ba44032e6f --- /dev/null +++ b/plugins/azure/machinelearning/mlWorkspaceHBI.spec.js @@ -0,0 +1,92 @@ +var expect = require('chai').expect; +var mlWorkspaceHBI = require('./mlWorkspaceHBI'); + +const workspaces = [ + { + "id": "/subscriptions/12345667/resourceGroups/test/providers/Microsoft.MachineLearningServices/workspaces/test1", + "name": "test", + "type": "Microsoft.MachineLearningServices/workspaces", + "hbiWorkspace": true + + + }, + { + "id": "/subscriptions/12345667/resourceGroups/test/providers/Microsoft.MachineLearningServices/workspaces/test1", + "name": "test", + "type": "Microsoft.MachineLearningServices/workspaces", + "hbiWorkspace": false + + }, +]; + +const createCache = (workspaces) => { + return { + machineLearning: { + listWorkspaces: { + 'eastus': { + data: workspaces + } + } + } + }; +}; + +const createErrorCache = () => { + return { + machineLearning: { + listWorkspaces: { + 'eastus': {} + } + } + }; +}; + +describe('mlWorkspaceHBI', function() { + describe('run', function() { + it('should give passing result if no Machine Learning workspace found', function(done) { + const cache = createCache([]); + mlWorkspaceHBI.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No existing Machine Learning workspaces found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Machine Learning workspaces', function(done) { + const cache = createErrorCache(); + mlWorkspaceHBI.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 Machine Learning workspaces: '); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + + it('should give passing result if Machine Learning workspace has high business impact (HBI) feature enabled', function(done) { + const cache = createCache([workspaces[0]]); + mlWorkspaceHBI.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Machine Learning workspace has high business impact (HBI) feature enabled'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if Machine Learning workspace does not have high business impact (HBI) feature enabled', function(done) { + const cache = createCache([workspaces[1]]); + mlWorkspaceHBI.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Machine Learning workspace does not have high business impact (HBI) feature enabled'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + }); +}); \ No newline at end of file From 378917057a66618239e317e43d72b4c11821a345 Mon Sep 17 00:00:00 2001 From: fatima99s Date: Mon, 15 Jul 2024 00:33:35 +0500 Subject: [PATCH 30/91] FS-Azure/MLworkspceHBI --- plugins/azure/machinelearning/mlWorkspaceHBI.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/machinelearning/mlWorkspaceHBI.js b/plugins/azure/machinelearning/mlWorkspaceHBI.js index 6e23f223b2..e2535cd1d7 100644 --- a/plugins/azure/machinelearning/mlWorkspaceHBI.js +++ b/plugins/azure/machinelearning/mlWorkspaceHBI.js @@ -11,7 +11,7 @@ module.exports = { recommended_action: 'Ensures that High Business Impact (HBI) feature enabled for Machine Learning workspace.', link: 'https://learn.microsoft.com/en-us/azure/machine-learning/concept-data-encryption', apis: ['machineLearning:listWorkspaces'], - realtime_triggers: ['microsoft:machinelearningservices:workspaces:write', 'microsoft:machinelearningservices:workspaces:delete', 'microsoftresources:tags:write'], + realtime_triggers: ['microsoft:machinelearningservices:workspaces:write', 'microsoft:machinelearningservices:workspaces:delete'], run: function(cache, settings, callback) { const results = []; From 2038205aa83c941426a55927edd8c2280ed61751 Mon Sep 17 00:00:00 2001 From: fatima99s Date: Mon, 15 Jul 2024 00:34:54 +0500 Subject: [PATCH 31/91] FS-Azure/MLRegistriesTags --- plugins/azure/machinelearning/mlRegistryHasTags.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/azure/machinelearning/mlRegistryHasTags.js b/plugins/azure/machinelearning/mlRegistryHasTags.js index 8b369826d5..d8403564e5 100644 --- a/plugins/azure/machinelearning/mlRegistryHasTags.js +++ b/plugins/azure/machinelearning/mlRegistryHasTags.js @@ -5,13 +5,13 @@ module.exports = { title: 'Machine Learning Registry Has Tags', category: 'AI & ML', domain: 'Machine Learning', - severity: 'High', + severity: 'Low', description: 'Ensures that Azure Machine Learning registries have tags associated.', more_info: 'Tags help you to group resources together that are related to or associated with each other. It is a best practice to tag cloud resources to better organize and gain visibility into their usage.', recommended_action: 'Modify Machine Learning registry and add tags.', link: 'https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources', apis: ['machineLearning:listRegistries'], - realtime_triggers: ['microsoftmachinelearningservices:registries:write','microsoftmachinelearningservices:registries:delete'], + realtime_triggers: ['microsoftmachinelearningservices:registries:write','microsoftmachinelearningservices:registries:delete', 'microsoftresources:tags:write'], run: function(cache, settings, callback) { const results = []; From 24e0e0ed79dfc3de523e1cdc0f1368cbf2e66cd1 Mon Sep 17 00:00:00 2001 From: fatima99s Date: Mon, 15 Jul 2024 00:36:33 +0500 Subject: [PATCH 32/91] FS-Azure/MLRegisteryPlublicAccess --- plugins/azure/machinelearning/mlRegistryPublicAccess.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/machinelearning/mlRegistryPublicAccess.js b/plugins/azure/machinelearning/mlRegistryPublicAccess.js index 30f672be0a..a2a7073313 100644 --- a/plugins/azure/machinelearning/mlRegistryPublicAccess.js +++ b/plugins/azure/machinelearning/mlRegistryPublicAccess.js @@ -5,7 +5,7 @@ module.exports = { title: 'Machine Learning Registry Public Access Disabled', category: 'AI & ML', domain: 'Machine Learning', - severity: 'High', + severity: 'Medium', description: 'Ensures that Azure Machine Learning registries are not publicly accessible.', more_info: 'Disabling public network access for Azure Machine Learning registries helps prevent data leakage risks by ensuring that your registries are not accessible over the public internet. Instead, private endpoints provide network isolation, securing connections within a virtual network (VNet) and preventing exposure of sensitive data.', recommended_action: 'Ensure that Azure Machine Learning registries have public network access disabled.', From f7225590317ed2afaae55c0fd9bfe82e41385c8d Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 15 Jul 2024 01:15:18 +0500 Subject: [PATCH 33/91] H-plugin synapse workspace has tags --- exports.js | 1 + .../azure/synapse/synapseWorkspaceHasTags.js | 55 ++++++++++++ .../synapse/synapseWorkspaceHasTags.spec.js | 85 +++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 plugins/azure/synapse/synapseWorkspaceHasTags.js create mode 100644 plugins/azure/synapse/synapseWorkspaceHasTags.spec.js diff --git a/exports.js b/exports.js index dcbf2a3dbb..6ae9b8b16a 100644 --- a/exports.js +++ b/exports.js @@ -1217,6 +1217,7 @@ module.exports = { 'workspaceManagedIdentity' : require(__dirname + '/plugins/azure/synapse/workspaceManagedIdentity.js'), 'synapseWorkspaceAdAuthEnabled' : require(__dirname + '/plugins/azure/synapse/synapseWorkspaceAdAuthEnabled.js'), 'synapseWorkspacPrivateEndpoint': require(__dirname + '/plugins/azure/synapse/synapseWorkspacPrivateEndpoint.js'), + 'synapseWorkspaceHasTags' : require(__dirname + '/plugins/azure/synapse/synapseWorkspaceHasTags.js'), 'apiInstanceManagedIdentity' : require(__dirname + '/plugins/azure/apiManagement/apiInstanceManagedIdentity.js'), 'apiInstanceHasTags' : require(__dirname + '/plugins/azure/apiManagement/apiInstanceHasTags.js'), diff --git a/plugins/azure/synapse/synapseWorkspaceHasTags.js b/plugins/azure/synapse/synapseWorkspaceHasTags.js new file mode 100644 index 0000000000..a063e7f788 --- /dev/null +++ b/plugins/azure/synapse/synapseWorkspaceHasTags.js @@ -0,0 +1,55 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Synapse Workspace Has Tags', + category: 'AI & ML', + domain: 'Machine Learning', + severity: 'Low', + description: 'Ensures that Azure Synapse workspace has tags associated.', + more_info: 'Tags help you to group resources together that are related to or associated with each other. It is a best practice to tag cloud resources to better organize and gain visibility into their usage.', + recommended_action: 'Modify Synapse workspace and add tags.', + link: 'https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources', + apis: ['synapse:listWorkspaces'], + realtime_triggers: ['microsoftsynapse:workspaces:write','microsoftsynapse:workspaces:delete'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + + async.each(locations.synapse, function(location, rcb) { + const workspaces = helpers.addSource(cache, source, + ['synapse', 'listWorkspaces', location]); + + if (!workspaces) return rcb(); + + + if (workspaces.err || !workspaces.data) { + helpers.addResult(results, 3, 'Unable to query Synapse workspaces: ' + helpers.addError(workspaces), location); + return rcb(); + } + + if (!workspaces.data.length) { + helpers.addResult(results, 0, 'No existing Synapse workspaces found', location); + return rcb(); + } + + for (let workspace of workspaces.data) { + if (!workspace.id) continue; + + if (workspace.tags && + Object.entries(workspace.tags).length > 0) { + helpers.addResult(results, 0, 'Synapse workspace has tags', location, workspace.id); + } else { + helpers.addResult(results, 2, 'Synapse workspace does not have tags', location, workspace.id); + } + } + + rcb(); + }, function() { + // Global checking goes here + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/synapse/synapseWorkspaceHasTags.spec.js b/plugins/azure/synapse/synapseWorkspaceHasTags.spec.js new file mode 100644 index 0000000000..2663374e28 --- /dev/null +++ b/plugins/azure/synapse/synapseWorkspaceHasTags.spec.js @@ -0,0 +1,85 @@ +var expect = require('chai').expect; +var synapseWorkspaceHasTags = require('./synapseWorkspaceHasTags'); + +const workspaces = [ + { + type: "Microsoft.Synapse/workspaces", + id: "/subscriptions/123/resourceGroups/rsgrp/providers/Microsoft.Synapse/workspaces/test", + location: "eastus", + name: "test", + "tags": { + "key": "value" + } + }, + { + type: "Microsoft.Synapse/workspaces", + id: "/subscriptions/123/resourceGroups/rsgrp/providers/Microsoft.Synapse/workspaces/test", + location: "eastus", + name: "test", + "tags": {} + }, +]; + + +const createCache = (workspaces, err) => { + + return { + synapse: { + listWorkspaces: { + 'eastus': { + data: workspaces, + err: err + } + } + } + }; +}; + +describe('synapseWorkspaceHasTags', function () { + describe('run', function () { + + it('should give a passing result if no Synapse workspaces are found', function (done) { + const cache = createCache([], null); + synapseWorkspaceHasTags.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No existing Synapse workspaces found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Synapse workspaces', function (done) { + const cache = createCache(null, ['error']); + synapseWorkspaceHasTags.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 Synapse workspaces'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if workspace has tags', function (done) { + const cache = createCache([workspaces[0]], null); + synapseWorkspaceHasTags.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Synapse workspace has tags'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if workspace does not have tags', function (done) { + const cache = createCache([workspaces[1]], null); + synapseWorkspaceHasTags.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Synapse workspace does not have tags'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file From 3f87390f22b36c3b26169c8669006aaac2164a17 Mon Sep 17 00:00:00 2001 From: fatima99s Date: Mon, 15 Jul 2024 01:22:42 +0500 Subject: [PATCH 34/91] FS-AWS/GuarddutyEKSProtection --- exports.js | 1 + plugins/aws/guardduty/eksProtectionEnabled.js | 67 +++++++ .../guardduty/eksProtectionEnabled.spec.js | 176 ++++++++++++++++++ 3 files changed, 244 insertions(+) create mode 100644 plugins/aws/guardduty/eksProtectionEnabled.js create mode 100644 plugins/aws/guardduty/eksProtectionEnabled.spec.js diff --git a/exports.js b/exports.js index dcbf2a3dbb..9e99e293e6 100644 --- a/exports.js +++ b/exports.js @@ -594,6 +594,7 @@ module.exports = { 'organizationInvite' : require(__dirname + '/plugins/aws/organizations/organizationInvite.js'), 'guardDutyEnabled' : require(__dirname + '/plugins/aws/guardduty/guarddutyEnabled.js'), + 'eksProtectionEnabled' : require(__dirname + '/plugins/aws/guardduty/eksProtectionEnabled.js'), 'guardDutyMaster' : require(__dirname + '/plugins/aws/guardduty/guarddutyMaster.js'), 'noActiveFindings' : require(__dirname + '/plugins/aws/guardduty/noActiveFindings'), 's3ProtectionEnabled' : require(__dirname + '/plugins/aws/guardduty/s3ProtectionEnabled.js'), diff --git a/plugins/aws/guardduty/eksProtectionEnabled.js b/plugins/aws/guardduty/eksProtectionEnabled.js new file mode 100644 index 0000000000..757f6c68e7 --- /dev/null +++ b/plugins/aws/guardduty/eksProtectionEnabled.js @@ -0,0 +1,67 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'EKS GuardDuty Enabled', + category: 'GuardDuty', + domain: 'Management and Governance', + severity: 'Medium', + description: 'Ensures GuardDuty protection is enabled for EKS' , + more_info: 'Enabling GuardDuty EKS Protection helps detect potential security threats in your EKS clusters by monitoring audit logs, user activities, and control plane operations. It provides enhanced security by offering proactive threat detection and automated alerting for suspicious activities and security issues within your AWS environment.', + recommended_action: 'Enable GuardDuty EKS protection for all AWS accounts.', + link: 'https://docs.aws.amazon.com/guardduty/latest/ug/kubernetes-protection.html', + apis: ['GuardDuty:listDetectors', 'GuardDuty:getDetector', 'STS:getCallerIdentity'], + realtime_triggers: ['guardduty:CreateDetector', 'guardduty:UpdateDetector', 'guardduty:DeleteDetector'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + + var acctRegion = helpers.defaultRegion(settings); + var awsOrGov = helpers.defaultPartition(settings); + var accountId = helpers.addSource(cache, source, ['sts', 'getCallerIdentity', acctRegion, 'data']); + + var regions = helpers.regions(settings); + + async.each(regions.guardduty, function(region, rcb) { + var listDetectors = helpers.addSource(cache, source, ['guardduty', 'listDetectors', region]); + + if (!listDetectors) return rcb(); + + if (listDetectors.err || !listDetectors.data) { + helpers.addResult(results, 3, 'Unable to list GuardDuty detectors: ' + helpers.addError(listDetectors), region); + return rcb(); + } + + if (!listDetectors.data || !listDetectors.data.length) { + helpers.addResult(results, 0, 'No GuardDuty detectors found', region); + return rcb(); + } + + listDetectors.data.forEach(function(detectorId) { + + var getDetector = helpers.addSource(cache, source, ['guardduty', 'getDetector', region, detectorId]); + + if (!getDetector) return; + + if (getDetector.err || !getDetector.data) { + helpers.addResult(results, 3, 'Unable to get GuardDuty detector: ' + helpers.addError(getDetector),region); + return; + } + + var detector = getDetector.data; + var resource = 'arn:' + awsOrGov + ':guardduty:' + region + ':' + accountId + ':detector/' + detector.detectorId; + + if ( detector.DataSources && detector.DataSources.Kubernetes && detector.DataSources.Kubernetes.AuditLogs && detector.DataSources.Kubernetes.AuditLogs.Status === 'DISABLED'){ + helpers.addResult(results, 2, 'GuardDuty EKS protection is disabled', region, resource); + } else { + helpers.addResult(results, 0, 'GuardDuty EKS protection is enabled', region, resource); + } + }); + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; diff --git a/plugins/aws/guardduty/eksProtectionEnabled.spec.js b/plugins/aws/guardduty/eksProtectionEnabled.spec.js new file mode 100644 index 0000000000..5bf1481542 --- /dev/null +++ b/plugins/aws/guardduty/eksProtectionEnabled.spec.js @@ -0,0 +1,176 @@ +var expect = require('chai').expect; +var eksProtectionEnabled = require('./eksProtectionEnabled'); + +const listDetectors = [ + "6cc45a4adb18e50f5ba51f6800db03d8" +]; + +const getDetector = [ + { + "CreatedAt": "2021-11-16T15:54:17.530Z", + "FindingPublishingFrequency": "SIX_HOURS", + "ServiceRole": "arn:aws:iam::000011112222:role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty", + "Status": "ENABLED", + "UpdatedAt": "2021-12-01T14:13:59.029Z", + "DataSources": { + "CloudTrail": { + "Status": "ENABLED" + }, + "DNSLogs": { + "Status": "ENABLED" + }, + "FlowLogs": { + "Status": "ENABLED" + }, + "S3Logs": { + "Status": "ENABLED" + }, + "Kubernetes": { + "AuditLogs": { + "Status": "ENABLED" + } + } + }, + "Tags": {} + }, + { + "CreatedAt": "2021-11-16T15:54:17.530Z", + "FindingPublishingFrequency": "SIX_HOURS", + "ServiceRole": "arn:aws:iam::000011112222:role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty", + "Status": "ENABLED", + "UpdatedAt": "2021-12-01T14:13:59.029Z", + "DataSources": { + "CloudTrail": { + "Status": "ENABLED" + }, + "DNSLogs": { + "Status": "ENABLED" + }, + "FlowLogs": { + "Status": "ENABLED" + }, + "S3Logs": { + "Status": "DISABLED" + }, + "Kubernetes": { + "AuditLogs": { + "Status": "DISABLED" + } + } + }, + "Tags": {} + } +]; + +const createCache = (listDetectors, getDetector) => { + let detectorId = (listDetectors.length) ? listDetectors[0] : null; + return { + guardduty: { + listDetectors: { + 'us-east-1': { + data: listDetectors + }, + }, + getDetector: { + 'us-east-1': { + [detectorId]: { + data: getDetector + } + } + } + } + }; +}; + +const createErrorCache = () => { + return { + guardduty: { + listDetectors: { + 'us-east-1': { + err: { + message: 'error desribing cache clusters' + }, + }, + }, + }, + }; +}; + +const createNullCache = () => { + return { + guardduty: { + listDetectors: { + 'us-east-1': null + } + } + }; +}; + + +describe('eksProtectionEnabled', function () { + describe('run', function () { + it('should FAIL if GuardDuty EKS protection is diabled', function (done) { + const cache = createCache(listDetectors, getDetector[1],); + eksProtectionEnabled.run(cache, {}, (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('GuardDuty EKS protection is disabled'); + done(); + }); + }); + + it('should PASS if GuardDuty EKS protection is enabled', function (done) { + const cache = createCache(listDetectors, getDetector[0]); + eksProtectionEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('GuardDuty EKS protection is enabled'); + done(); + }); + }); + + it('should PASS if no detectors found', function (done) { + const cache = createCache([]); + eksProtectionEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('No GuardDuty detectors found'); + done(); + }); + }); + + it('should UNKNOWN unable to list GuardDuty detector', function (done) { + const cache = createErrorCache(); + eksProtectionEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('Unable to list GuardDuty detectors:'); + done(); + }); + }); + + it('should UNKNOWN unable to get GuardDuty detector', function (done) { + const cache = createCache([listDetectors]); + eksProtectionEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('Unable to get GuardDuty detector: '); + done(); + }); + }); + + it('should not return any result if list dectectors response not found', function (done) { + const cache = createNullCache(); + eksProtectionEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + }); +}); + From 62c60953a4d639020a8bb6e05dcea50377f3a685 Mon Sep 17 00:00:00 2001 From: fatima99s Date: Mon, 15 Jul 2024 02:13:03 +0500 Subject: [PATCH 35/91] FS-Azure/ContainerAppIPRestriction --- exports.js | 1 + .../containerAppIPRestriction.js | 58 +++++++ .../containerAppIPRestriction.spec.js | 149 ++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 plugins/azure/containerapps/containerAppIPRestriction.js create mode 100644 plugins/azure/containerapps/containerAppIPRestriction.spec.js diff --git a/exports.js b/exports.js index dcbf2a3dbb..6523bdcd76 100644 --- a/exports.js +++ b/exports.js @@ -733,6 +733,7 @@ module.exports = { 'containerAppVolumeMount' : require(__dirname + '/plugins/azure/containerapps/containerAppVolumeMount.js'), 'containerAppHttpsOnly' : require(__dirname + '/plugins/azure/containerapps/containerAppHttpsOnly.js'), 'containerAppHasTags' : require(__dirname + '/plugins/azure/containerapps/containerAppHasTags.js'), + 'containerAppIPRestriction' : require(__dirname + '/plugins/azure/containerapps/containerAppIPRestriction.js'), 'workspacePublicAccessDisabled' : require(__dirname + '/plugins/azure/machinelearning/workspacePublicAccessDisabled.js'), 'workspaceLoggingEnabled' : require(__dirname + '/plugins/azure/machinelearning/workspaceLoggingEnabled.js'), diff --git a/plugins/azure/containerapps/containerAppIPRestriction.js b/plugins/azure/containerapps/containerAppIPRestriction.js new file mode 100644 index 0000000000..a134c7e471 --- /dev/null +++ b/plugins/azure/containerapps/containerAppIPRestriction.js @@ -0,0 +1,58 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Container Apps IP Restriction Configured', + category: 'Container Apps', + domain: 'Containers', + severity: 'Medium', + description: 'Ensures that Container Apps are configured to allow only specific IP addresses.', + more_info: 'Azure Container Apps allows you to control inbound traffic by configuring IP ingress restrictions. You can specify rules to either allow traffic only from defined address ranges or deny traffic from specified ranges. Without any IP restriction rules, all inbound traffic is permitted, which may expose your application to security risks.', + recommended_action: 'Modify Container Apps and configure IP restriction.', + link: 'https://learn.microsoft.com/en-us/azure/container-apps/ip-restrictions', + apis: ['containerApps:list'], + realtime_triggers: ['microsoftapp:containerapps:write', 'microsoftapp:containerapps:delete'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.containerApps, function(location, rcb) { + + var containerApps = helpers.addSource(cache, source, + ['containerApps', 'list', location]); + + if (!containerApps) return rcb(); + + if (containerApps.err || !containerApps.data) { + helpers.addResult(results, 3, + 'Unable to query for Container apps: ' + helpers.addError(containerApps), location); + return rcb(); + } + + if (!containerApps.data.length) { + helpers.addResult(results, 0, 'No existing Container apps found', location); + return rcb(); + } + + for (let container of containerApps.data) { + if (!container.id) continue; + if (container.configuration && container.configuration.ingress && container.configuration.ingress.ipSecurityRestrictions && container.configuration.ingress.ipSecurityRestrictions.length) { + helpers.addResult(results, 0, + 'Container app has IP restrictions configured', location, container.id); + + } else { + helpers.addResult(results, 2, + 'Container app does not have IP restrictions configured', location, container.id); + } + } + + rcb(); + }, function() { + // Global checking goes here + callback(null, results, source); + }); + } +}; + diff --git a/plugins/azure/containerapps/containerAppIPRestriction.spec.js b/plugins/azure/containerapps/containerAppIPRestriction.spec.js new file mode 100644 index 0000000000..3dbccd08fd --- /dev/null +++ b/plugins/azure/containerapps/containerAppIPRestriction.spec.js @@ -0,0 +1,149 @@ +var expect = require('chai').expect; +var containerAppIPRestriction = require('./containerAppIPRestriction'); + +const containerApps = [ + { + "id": "/subscriptions/123456/resourceGroups/tesr/providers/Microsoft.App/containerapps/test1", + "name": "test1", + "type": "Microsoft.App/containerApps", + "configuration": { + "ingress": { + "fqdn": "testfatima.wittysea-8163cba4.australiaeast.azurecontainerapps.io", + "external": true, + "targetPort": 300, + "exposedPort": 0, + "transport": "Auto", + "traffic": [ + { + "weight": 100, + "latestRevision": true + } + ], + "customDomains": null, + "allowInsecure": false, + "ipSecurityRestrictions": [ + { + "action":'Allow', + "description":'dummy', + "ipAddressRange": '00000', + "name": 'test' + } + ], + "corsPolicy": null, + "clientCertificateMode": "Ignore", + "stickySessions": { + "affinity": "none" + } + }, + }, + "identity": { + "type": "SystemAssigned" + } + + }, + { + "id": "/subscriptions/123456/resourceGroups/tesr/providers/Microsoft.App/containerapps/test2", + "name": "test2", + "type": "Microsoft.App/containerApps", + "configuration": { + "ingress": { + "fqdn": "testfatima.wittysea-8163cba4.australiaeast.azurecontainerapps.io", + "external": true, + "targetPort": 300, + "exposedPort": 0, + "transport": "Auto", + "traffic": [ + { + "weight": 100, + "latestRevision": true + } + ], + "customDomains": null, + "allowInsecure": true, + "ipSecurityRestrictions": null, + "corsPolicy": null, + "clientCertificateMode": "Ignore", + "stickySessions": { + "affinity": "none" + } + }, + }, + "identity": { + "type": "None" + } + }, +]; + + + +const createCache = (container) => { + return { + containerApps: { + list: { + 'eastus': { + data: container + } + } + } + }; +}; + +const createErrorCache = () => { + return { + containerApps: { + list: { + 'eastus': {} + } + } + }; +}; + +describe('containerAppIPRestriction', function() { + describe('run', function() { + it('should give passing result if no container apps', function(done) { + const cache = createCache([]); + containerAppIPRestriction.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No existing Container apps found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for container apps', function(done) { + const cache = createErrorCache(); + containerAppIPRestriction.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 Container apps: '); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + + it('should give passing result if container app has IP restrictions configured', function(done) { + const cache = createCache([containerApps[0]]); + containerAppIPRestriction.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Container app has IP restrictions configured'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if container app does not have IP restrictions configured', function(done) { + const cache = createCache([containerApps[1]]); + containerAppIPRestriction.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Container app does not have IP restrictions configured'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + }); +}); From 44e5b657527840f3835678a4a48ea91f48e2b226 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 15 Jul 2024 13:27:38 +0500 Subject: [PATCH 36/91] H-plugin synapse workspace double encryption --- exports.js | 1 + .../synapse/workspaceDoubleEncryption.js | 56 +++++++++++ .../synapse/workspaceDoubleEncryption.spec.js | 96 +++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 plugins/azure/synapse/workspaceDoubleEncryption.js create mode 100644 plugins/azure/synapse/workspaceDoubleEncryption.spec.js diff --git a/exports.js b/exports.js index dcbf2a3dbb..50a7e9f116 100644 --- a/exports.js +++ b/exports.js @@ -1217,6 +1217,7 @@ module.exports = { 'workspaceManagedIdentity' : require(__dirname + '/plugins/azure/synapse/workspaceManagedIdentity.js'), 'synapseWorkspaceAdAuthEnabled' : require(__dirname + '/plugins/azure/synapse/synapseWorkspaceAdAuthEnabled.js'), 'synapseWorkspacPrivateEndpoint': require(__dirname + '/plugins/azure/synapse/synapseWorkspacPrivateEndpoint.js'), + 'workspaceDoubleEncryption' : require(__dirname + '/plugins/azure/synapse/workspaceDoubleEncryption.js'), 'apiInstanceManagedIdentity' : require(__dirname + '/plugins/azure/apiManagement/apiInstanceManagedIdentity.js'), 'apiInstanceHasTags' : require(__dirname + '/plugins/azure/apiManagement/apiInstanceHasTags.js'), diff --git a/plugins/azure/synapse/workspaceDoubleEncryption.js b/plugins/azure/synapse/workspaceDoubleEncryption.js new file mode 100644 index 0000000000..252a16321f --- /dev/null +++ b/plugins/azure/synapse/workspaceDoubleEncryption.js @@ -0,0 +1,56 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Synapse Workspace Double Encryption Enabled', + category: 'AI & ML', + domain: 'Machine Learning', + severity: 'High', + description: 'Ensures that Azure Synapse workspace has double Encryption enabled.', + more_info: 'Enabling double encryption for Synapse workspace provides an extra layer of protection for data at rest and in transit. This feature significantly enhances security and helps ensure compliance with stringent data protection standards within the Azure environment.', + recommended_action: 'Create a new Synapse workspace and enable double encryption using CMK.', + link: 'https://learn.microsoft.com/en-us/azure/synapse-analytics/security/workspaces-encryption', + apis: ['synapse:listWorkspaces'], + realtime_triggers: ['microsoftsynapse:workspaces:write','microsoftsynapse:workspaces:delete'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + + async.each(locations.synapse, function(location, rcb) { + const workspaces = helpers.addSource(cache, source, + ['synapse', 'listWorkspaces', location]); + + if (!workspaces) return rcb(); + + + if (workspaces.err || !workspaces.data) { + helpers.addResult(results, 3, 'Unable to query Synapse workspaces: ' + helpers.addError(workspaces), location); + return rcb(); + } + + if (!workspaces.data.length) { + helpers.addResult(results, 0, 'No existing Synapse workspaces found', location); + return rcb(); + } + + for (let workspace of workspaces.data) { + if (!workspace.id) continue; + + if (workspace.encryption && + workspace.encryption.doubleEncryptionEnabled && + Object.entries(workspace.encryption.cmk).length > 0) { + helpers.addResult(results, 0, 'Synapse workspace has double encryption enabled', location, workspace.id); + } else { + helpers.addResult(results, 2, 'Synapse workspace does not have double encryption enabled', location, workspace.id); + } + } + + rcb(); + }, function() { + // Global checking goes here + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/synapse/workspaceDoubleEncryption.spec.js b/plugins/azure/synapse/workspaceDoubleEncryption.spec.js new file mode 100644 index 0000000000..54f0b00f88 --- /dev/null +++ b/plugins/azure/synapse/workspaceDoubleEncryption.spec.js @@ -0,0 +1,96 @@ +var expect = require('chai').expect; +var workspaceDoubleEncryption = require('./workspaceDoubleEncryption'); + +const workspaces = [ + { + type: "Microsoft.Synapse/workspaces", + id: "/subscriptions/123/resourceGroups/rsgrp/providers/Microsoft.Synapse/workspaces/test", + location: "eastus", + name: "test", + encryption: { + doubleEncryptionEnabled: false + } + }, + { + type: "Microsoft.Synapse/workspaces", + id: "/subscriptions/123/resourceGroups/rsgrp/providers/Microsoft.Synapse/workspaces/test", + location: "eastus", + name: "test", + encryption: { + cmk: { + kekIdentity: { + useSystemAssignedIdentity: true, + }, + key: { + name: "default", + keyVaultUrl: "https://test-key-0011.vault.azure.net/keys/test-key", + }, + }, + doubleEncryptionEnabled: true, + } + }, +]; + + +const createCache = (workspaces, err) => { + + return { + synapse: { + listWorkspaces: { + 'eastus': { + data: workspaces, + err: err + } + } + } + }; +}; + +describe('workspaceDoubleEncryption', function () { + describe('run', function () { + + it('should give a passing result if no Synapse workspaces are found', function (done) { + const cache = createCache([], null); + workspaceDoubleEncryption.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No existing Synapse workspaces found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Synapse workspaces', function (done) { + const cache = createCache(null, ['error']); + workspaceDoubleEncryption.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 Synapse workspaces'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if workspace has double encryption enabled', function (done) { + const cache = createCache([workspaces[1]], null); + workspaceDoubleEncryption.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Synapse workspace has double encryption enabled'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if workspace does not have double encryption enabled', function (done) { + const cache = createCache([workspaces[0]], null); + workspaceDoubleEncryption.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Synapse workspace does not have double encryption enabled'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file From 57d330670c1a03300c3260094f77ebe7e2aae7fc Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 15 Jul 2024 15:54:00 +0500 Subject: [PATCH 37/91] update link --- plugins/azure/batchAccounts/batchAccountsManagedIdentity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js b/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js index efdf5d885a..767c81eb90 100644 --- a/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js +++ b/plugins/azure/batchAccounts/batchAccountsManagedIdentity.js @@ -9,7 +9,7 @@ module.exports = { description: 'Ensures that Batch accounts have managed identity enabled.', more_info: 'Enabling managed identities eliminate the need for developers having to manage credentials by providing an identity for the Azure resource in Azure AD and using it to obtain Azure Active Directory (Azure AD) tokens.', recommended_action: 'Modify Batch Account and enable managed identity.', - link: 'https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools', + link: 'https://learn.microsoft.com/en-us/troubleshoot/azure/hpc/batch/use-managed-identities-azure-batch-account-pool', apis: ['batchAccounts:list'], realtime_triggers: ['microsoftbatch:batchaccounts:write','microsoftbatch:batchaccounts:delete'], From 518013e10bdda40ead96fcb7819b50a9f9ca680d Mon Sep 17 00:00:00 2001 From: fatima99s Date: Mon, 15 Jul 2024 16:09:25 +0500 Subject: [PATCH 38/91] FS-AWS/ManagedBlockchainCloudwatchLogs --- exports.js | 2 + .../networkMemberCloudwatchLogs.js | 90 ++++++++++ .../networkMemberCloudwatchLogs.spec.js | 165 ++++++++++++++++++ 3 files changed, 257 insertions(+) create mode 100644 plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js create mode 100644 plugins/aws/managedblockchain/networkMemberCloudwatchLogs.spec.js diff --git a/exports.js b/exports.js index dcbf2a3dbb..13046ff016 100644 --- a/exports.js +++ b/exports.js @@ -637,6 +637,8 @@ module.exports = { 'databrewJobOutputEncrypted' : require(__dirname + '/plugins/aws/gluedatabrew/databrewJobOutputEncrypted.js'), 'networkMemberDataEncrypted' : require(__dirname + '/plugins/aws/managedblockchain/networkMemberDataEncrypted.js'), + 'networkMemberCloudwatchLogs' : require(__dirname + '/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js'), + 'docdbClusterEncrypted' : require(__dirname + '/plugins/aws/documentDB/docdbClusterEncrypted.js'), 'docDbHasTags' : require(__dirname + '/plugins/aws/documentDB/docDbHasTags.js'), diff --git a/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js b/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js new file mode 100644 index 0000000000..f27c20ae60 --- /dev/null +++ b/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js @@ -0,0 +1,90 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'Managed Blockchain Network Member CloudWatch Logs', + category: 'Managed Blockchain', + domain: 'Content Delivery', + severity: 'Medium', + description: 'Ensure that Amazon Managed Blockchain members have CloudWatch logs enabled.', + more_info: 'Enabling CloudWatch Logs for Amazon Managed Blockchain helps troubleshoot chaincode development, monitor network activity, and identify errors by publishing peer node, chaincode, and certificate authority (CA) logs.', + link: 'https://docs.aws.amazon.com/managed-blockchain/latest/hyperledger-fabric-dev/monitoring-cloudwatch-logs.html', + recommended_action: 'Modify Managed Blockchain members to enable CloudWatch Logs', + apis: ['ManagedBlockchain:listMembers', 'ManagedBlockchain:listNetworks', 'ManagedBlockchain:getMember'], + realtime_triggers: ['managedblockchain:CreateNetwork', 'managedblockchain:DeleteMember'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + async.each(regions.managedblockchain, function(region, rcb){ + var listNetworks = helpers.addSource(cache, source, + ['managedblockchain', 'listNetworks', region]); + + if (!listNetworks) return rcb(); + + if (listNetworks.err || !listNetworks.data) { + helpers.addResult(results, 3, + `Unable to query for Managed Blockchain networks: ${helpers.addError(listNetworks)}`, region); + return rcb(); + } + + if (!listNetworks.data.length) { + helpers.addResult(results, 0, 'No Managed Blockchain networks found', region); + return rcb(); + } + + for (let network of listNetworks.data) { + if (!network.Id || !network.Arn) continue; + + let listMembers = helpers.addSource(cache, source, + ['managedblockchain', 'listMembers', region, network.Id]); + + if (!listMembers || listMembers.err || !listMembers.data || !listMembers.data.Members) { + helpers.addResult(results, 3, + `Unable to query network members: ${helpers.addError(listMembers)}`, + region, network.Arn); + continue; + } + + if (!listMembers.data.Members.length) { + helpers.addResult(results, 0, 'No network members found', region, network.Arn); + continue; + } + + for (let member of listMembers.data.Members) { + if (!member.Id || !member.Arn) continue; + + let resource = member.Arn; + let getMember = helpers.addSource(cache, source, + ['managedblockchain', 'getMember', region, member.Id]); + + if (!getMember || getMember.err || !getMember.data || !getMember.data.Member) { + helpers.addResult(results, 3, + `Unable to query network member: ${helpers.addError(getMember)}`, + region, member.Arn); + continue; + } + const getmember = getMember.data.Member + + if (getmember.LogPublishingConfiguration && getmember.LogPublishingConfiguration.Fabric && + getmember.LogPublishingConfiguration.Fabric.CaLogs && getmember.LogPublishingConfiguration.Fabric.CaLogs.Cloudwatch + && getmember.LogPublishingConfiguration.Fabric.CaLogs.Cloudwatch.Enabled) { + helpers.addResult(results, 0, + 'Network member has CloudWatch logs enabled', + region, resource); + } else { + helpers.addResult(results, 2, + 'Network member does not have CloudWatch logs enabled', + region, resource); + } + } + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; diff --git a/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.spec.js b/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.spec.js new file mode 100644 index 0000000000..0a55f7e219 --- /dev/null +++ b/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.spec.js @@ -0,0 +1,165 @@ +var expect = require('chai').expect; +var networkMemberCloudwatchLogs = require('./networkMemberCloudwatchLogs'); + +const listNetworks = [ + { + "Id": "n-Z7YTJ3EHSBENRKI7UM6XW2XWFQ", + "Name": "akhtar-net", + "Description": null, + "Framework": "HYPERLEDGER_FABRIC", + "FrameworkVersion": "1.4", + "Status": "AVAILABLE", + "CreationDate": "2021-11-16T07:46:51.158Z", + "Arn": "arn:aws:managedblockchain:us-east-1::networks/n-Z7YTJ3EHSBENRKI7UM6XW2XWFQ" + } +]; + +const listMembers = [ + { + "Id": "m-3WDFHOCKPZFPXOXP5SVIYEBTYA", + "Name": "akhtar", + "Description": null, + "Status": "AVAILABLE", + "CreationDate": "2021-11-16T07:46:51.146Z", + "IsOwned": true, + "Arn": "arn:aws:managedblockchain:us-east-1:000011112222:members/m-3WDFHOCKPZFPXOXP5SVIYEBTYA" + } +]; + +const getMember = [ + { + "NetworkId": "n-Z7YTJ3EHSBENRKI7UM6XW2XWFQ", + "Id": "m-3WDFHOCKPZFPXOXP5SVIYEBTYA", + "Name": "akhtar", + "Description": null, + "FrameworkAttributes": { + "Fabric": { + "AdminUsername": "cloudsploit", + "CaEndpoint": "ca.m-3wdfhockpzfpxoxp5sviyebtya.n-z7ytj3ehsbenrki7um6xw2xwfq.managedblockchain.us-east-1.amazonaws.com:30002" + } + }, + "LogPublishingConfiguration": { + "Fabric": { + "CaLogs": { + "Cloudwatch": { + "Enabled": true + } + } + } + }, + "Status": "AVAILABLE", + "CreationDate": "2021-11-16T07:46:51.146Z", + "Tags": {}, + "Arn": "arn:aws:managedblockchain:us-east-1:000011112222:members/m-3WDFHOCKPZFPXOXP5SVIYEBTYA", + "KmsKeyArn": "arn:aws:kms:us-east-1:000011112222:key/ad013a33-b01d-4d88-ac97-127399c18b3e" + }, + { + "NetworkId": "n-Z7YTJ3EHSBENRKI7UM6XW2XWFQ", + "Id": "m-3WDFHOCKPZFPXOXP5SVIYEBTYA", + "Name": "akhtar", + "Description": null, + "FrameworkAttributes": { + "Fabric": { + "AdminUsername": "cloudsploit", + "CaEndpoint": "ca.m-3wdfhockpzfpxoxp5sviyebtya.n-z7ytj3ehsbenrki7um6xw2xwfq.managedblockchain.us-east-1.amazonaws.com:30002" + } + }, + "LogPublishingConfiguration": { + "Fabric": { + "CaLogs": { + "Cloudwatch": { + "Enabled": false + } + } + } + }, + "Status": "AVAILABLE", + "CreationDate": "2021-11-16T07:46:51.146Z", + "Tags": {}, + "Arn": "arn:aws:managedblockchain:us-east-1:000011112222:members/m-3WDFHOCKPZFPXOXP5SVIYEBTYA", + "KmsKeyArn": "AWS_OWNED_KMS_KEY" + } +]; + + +const createCache = (networks, members, getMember, networksErr) => { + var networkId = (networks && networks.length) ? networks[0].Id : null; + var memberId = (members && members.length) ? members[0].Id : null; + return { + managedblockchain: { + listNetworks: { + 'us-east-1': { + err: networksErr, + data: networks + }, + }, + listMembers: { + 'us-east-1': { + [networkId]: { + data: { + "Members": members + } + } + } + }, + getMember: { + 'us-east-1': { + [memberId]: { + data: { + "Member": getMember + } + } + } + } + }, + }; +}; + +describe('networkMemberCloudwatchLogs', function () { + describe('run', function () { + it('should PASS if Network member has cloudwatch logs enabled', function (done) { + const cache = createCache(listNetworks ,listMembers, getMember[0]); + networkMemberCloudwatchLogs.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('Network member has CloudWatch logs enabled'); + done(); + }); + }); + + it('should FAIL if Network member does not have cloudwatch logs enabled', function (done) { + const cache = createCache(listNetworks ,listMembers, getMember[1]); + networkMemberCloudwatchLogs.run(cache, {}, (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('Network member does not have CloudWatch logs enabled'); + done(); + }); + }); + + it('should PASS if no Managed Blockchain networks found', function (done) { + const cache = createCache([]); + networkMemberCloudwatchLogs.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('No Managed Blockchain networks found'); + done(); + }); + }); + + it('should UNKNOWN if unable to query Managed Blockchain networks', function (done) { + const cache = createCache(null, null, null, { message: "unable to obtain data" }); + networkMemberCloudwatchLogs.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('Unable to query for Managed Blockchain networks:'); + done(); + }); + }); + + }); +}) \ No newline at end of file From aab9888c822a92506206f4f04accdc8adf23e029 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 15 Jul 2024 16:22:21 +0500 Subject: [PATCH 39/91] FS-AWS/ManagedBlockchainCloudwatchLogs --- .../networkMemberCloudwatchLogs.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js b/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js index f27c20ae60..deae8931e2 100644 --- a/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js +++ b/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js @@ -66,19 +66,19 @@ module.exports = { region, member.Arn); continue; } - const getmember = getMember.data.Member + const getmember = getMember.data.Member; if (getmember.LogPublishingConfiguration && getmember.LogPublishingConfiguration.Fabric && getmember.LogPublishingConfiguration.Fabric.CaLogs && getmember.LogPublishingConfiguration.Fabric.CaLogs.Cloudwatch && getmember.LogPublishingConfiguration.Fabric.CaLogs.Cloudwatch.Enabled) { - helpers.addResult(results, 0, - 'Network member has CloudWatch logs enabled', - region, resource); - } else { - helpers.addResult(results, 2, - 'Network member does not have CloudWatch logs enabled', - region, resource); - } + helpers.addResult(results, 0, + 'Network member has CloudWatch logs enabled', + region, resource); + } else { + helpers.addResult(results, 2, + 'Network member does not have CloudWatch logs enabled', + region, resource); + } } } From 2e8f2b70b80ec67df64f3f241b0d413a68a10fff Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 16 Jul 2024 17:44:24 +0500 Subject: [PATCH 40/91] H-plugin synapse workspace diagnostic logs enabled --- exports.js | 1 + helpers/azure/api.js | 5 + .../synapse/workspaceDiagnosticLogsEnabled.js | 63 +++++++++ .../workspaceDiagnosticLogsEnabled.spec.js | 127 ++++++++++++++++++ 4 files changed, 196 insertions(+) create mode 100644 plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js create mode 100644 plugins/azure/synapse/workspaceDiagnosticLogsEnabled.spec.js diff --git a/exports.js b/exports.js index dcbf2a3dbb..45afeaddb9 100644 --- a/exports.js +++ b/exports.js @@ -1217,6 +1217,7 @@ module.exports = { 'workspaceManagedIdentity' : require(__dirname + '/plugins/azure/synapse/workspaceManagedIdentity.js'), 'synapseWorkspaceAdAuthEnabled' : require(__dirname + '/plugins/azure/synapse/synapseWorkspaceAdAuthEnabled.js'), 'synapseWorkspacPrivateEndpoint': require(__dirname + '/plugins/azure/synapse/synapseWorkspacPrivateEndpoint.js'), + 'workspaceDiagnosticLogsEnabled': require(__dirname + '/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js'), 'apiInstanceManagedIdentity' : require(__dirname + '/plugins/azure/apiManagement/apiInstanceManagedIdentity.js'), 'apiInstanceHasTags' : require(__dirname + '/plugins/azure/apiManagement/apiInstanceHasTags.js'), diff --git a/helpers/azure/api.js b/helpers/azure/api.js index 000b92f186..a194c7bbc2 100644 --- a/helpers/azure/api.js +++ b/helpers/azure/api.js @@ -1277,6 +1277,11 @@ var tertiarycalls = { properties: ['id'], url: 'https://management.azure.com/{id}/providers/microsoft.insights/diagnosticSettings?api-version=2021-05-01-preview' }, + listByWorkspaces: { + reliesOnPath: 'synapse.listWorkspaces', + properties: ['id'], + url: 'https://management.azure.com/{id}/providers/microsoft.insights/diagnosticSettings?api-version=2021-05-01-preview' + } }, backupShortTermRetentionPolicies: { listByDatabase: { diff --git a/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js b/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js new file mode 100644 index 0000000000..b6c2db4e46 --- /dev/null +++ b/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js @@ -0,0 +1,63 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Synapse Workspace Diagnostic Logging Enabled', + category: 'AI & ML', + domain: 'Machine Learning', + severity: 'Medium', + description: 'Ensures diagnostic logging is enabled for Synapse workspace.', + more_info: 'Enabling diagnostic logging for Azure Synapse workspace enhances performance monitoring, troubleshooting, and security optimization. This feature captures detailed logs of workspace activities, allowing you to gain insights, identify issues, and maintain the integrity and efficiency of data operations.', + recommended_action: 'Enable diagnostic logging for all Synapse workspaces.', + link: 'https://learn.microsoft.com/en-gb/azure/azure-monitor/essentials/diagnostic-settings', + apis: ['synapse:listWorkspaces', 'diagnosticSettings:listByWorkspaces'], + realtime_triggers: ['microsoftsynapse:workspaces:write','microsoftsynapse:workspaces:delete','microsoftinsights:diagnosticSettings:delete'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + + async.each(locations.synapse, function(location, rcb) { + const workspaces = helpers.addSource(cache, source, + ['synapse', 'listWorkspaces', location]); + + if (!workspaces) return rcb(); + + + if (workspaces.err || !workspaces.data) { + helpers.addResult(results, 3, 'Unable to query Synapse workspaces: ' + helpers.addError(workspaces), location); + return rcb(); + } + + if (!workspaces.data.length) { + helpers.addResult(results, 0, 'No existing Synapse workspaces found', location); + return rcb(); + } + + for (let workspace of workspaces.data) { + var diagnosticSettings = helpers.addSource(cache, source, + ['diagnosticSettings', 'listByWorkspaces', location, workspace.id]); + + if (!diagnosticSettings || diagnosticSettings.err || !diagnosticSettings.data) { + helpers.addResult(results, 3, `Unable to query for Synapse workspace diagnostic settings: ${helpers.addError(diagnosticSettings)}`, + location, workspace.id); + continue; + } + + var found = diagnosticSettings.data.find(ds => ds.logs && ds.logs.length); + + if (found) { + helpers.addResult(results, 0, 'Synapse workspace has diagnostic logs enabled', location, workspace.id); + } else { + helpers.addResult(results, 2, 'Synapse workspace does not have diagnostic logs enabled', location, workspace.id); + } + } + + rcb(); + }, function() { + // Global checking goes here + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.spec.js b/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.spec.js new file mode 100644 index 0000000000..73d35d1877 --- /dev/null +++ b/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.spec.js @@ -0,0 +1,127 @@ +var expect = require('chai').expect; +var workspaceDiagnosticLogsEnabled = require('./workspaceDiagnosticLogsEnabled'); + +const workspaces = [ + { + type: "Microsoft.Synapse/workspaces", + id: "/subscriptions/123/resourceGroups/rsgrp/providers/Microsoft.Synapse/workspaces/test", + location: "eastus", + name: "test", + } +]; + + +const diagnosticSettings = [ + { + id: "/subscriptions/123/resourceGroups/rsgrp/providers/Microsoft.Synapse/workspaces/test", + type: 'Microsoft.Insights/diagnosticSettings', + name: 'test', + location: 'eastus', + kind: null, + tags: null, + eventHubName: null, + metrics: [], + logs: [ + { + "category": null, + "categoryGroup": "allLogs", + "enabled": true, + "retentionPolicy": { + "enabled": false, + "days": 0 + } + }, + { + "category": null, + "categoryGroup": "audit", + "enabled": false, + "retentionPolicy": { + "enabled": false, + "days": 0 + } + } + ], + logAnalyticsDestinationType: null + } +]; + +const createCache = (workspaces, ds) => { + const id = workspaces && workspaces.length ? workspaces[0].id : null; + return { + synapse: { + listWorkspaces: { + 'eastus': { + data: workspaces + } + } + }, + diagnosticSettings: { + listByWorkspaces: { + 'eastus': { + [id]: { + data: ds + } + } + } + + }, + }; +}; + +describe('workspaceDiagnosticLogsEnabled', function() { + describe('run', function() { + it('should give a passing result if no Synapse workspaces are found', function (done) { + const cache = createCache([], null); + workspaceDiagnosticLogsEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No existing Synapse workspaces found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Synapse workspaces', function (done) { + const cache = createCache(null, ['error']); + workspaceDiagnosticLogsEnabled.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 Synapse workspaces: Unable to obtain data'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + it('should give unknown result if unable to query for diagnostic settings', function(done) { + const cache = createCache([workspaces[0]], null); + workspaceDiagnosticLogsEnabled.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 Synapse workspace diagnostic settings'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if diagnostic logs enabled', function(done) { + const cache = createCache([workspaces[0]], [diagnosticSettings[0]]); + workspaceDiagnosticLogsEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Synapse workspace has diagnostic logs enabled'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if diagnostic logs not enabled', function(done) { + const cache = createCache([workspaces[0]], [[]]); + workspaceDiagnosticLogsEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Synapse workspace does not have diagnostic logs enabled'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); From 695bcada9b95f62004a030b6a91ea9bc2d4e5d4c Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 16 Jul 2024 22:15:19 +0500 Subject: [PATCH 41/91] update file --- plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js b/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js index b6c2db4e46..2bb4fe8840 100644 --- a/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js +++ b/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js @@ -11,7 +11,7 @@ module.exports = { recommended_action: 'Enable diagnostic logging for all Synapse workspaces.', link: 'https://learn.microsoft.com/en-gb/azure/azure-monitor/essentials/diagnostic-settings', apis: ['synapse:listWorkspaces', 'diagnosticSettings:listByWorkspaces'], - realtime_triggers: ['microsoftsynapse:workspaces:write','microsoftsynapse:workspaces:delete','microsoftinsights:diagnosticSettings:delete'], + realtime_triggers: ['microsoftsynapse:workspaces:write','microsoftsynapse:workspaces:delete','microsoftinsights:diagnosticSettings:delete','microsoftinsights:diagnosticSettings:write'], run: function(cache, settings, callback) { const results = []; From 6d4eedd4e8fea2d41f63b3a952eb98165a205eaa Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 26 Aug 2024 12:15:44 +0500 Subject: [PATCH 42/91] updated the category of security center plugins --- exports.js | 44 +++++++++---------- .../appWhitelistingEnabled.js | 8 ++-- .../appWhitelistingEnabled.spec.js | 0 .../autoProvisioningEnabled.js | 6 +-- .../autoProvisioningEnabled.spec.js | 0 .../highSeverityAlertsEnabled.js | 2 +- .../highSeverityAlertsEnabled.spec.js | 0 .../monitorEndpointProtection.js | 10 ++--- .../monitorEndpointProtection.spec.js | 0 .../monitorExternalAccounts.js | 8 ++-- .../monitorExternalAccounts.spec.js | 0 .../monitorIpForwarding.js | 8 ++-- .../monitorIpForwarding.spec.js | 0 .../monitorJitNetworkAccess.js | 10 ++--- .../monitorJitNetworkAccess.spec.js | 0 .../monitorNextGenerationFirewall.js | 10 ++--- .../monitorNextGenerationFirewall.spec.js | 0 .../monitorSubscriptionOwners.js | 8 ++-- .../monitorSubscriptionOwners.spec.js | 0 .../monitorSystemUpdates.js | 10 ++--- .../monitorSystemUpdates.spec.js | 0 .../securityConfigMonitoring.js | 10 ++--- .../securityConfigMonitoring.spec.js | 0 .../securityContactAdditionalEmail.js | 2 +- .../securityContactAdditionalEmail.spec.js | 0 .../securityContactRoleSetToOwner.js | 2 +- .../securityContactRoleSetToOwner.spec.js | 0 .../securityContactsEnabled.js | 8 ++-- .../securityContactsEnabled.spec.js | 0 .../standardPricingEnabled.js | 10 ++--- .../standardPricingEnabled.spec.js | 0 31 files changed, 78 insertions(+), 78 deletions(-) rename plugins/azure/{securitycenter => defender}/appWhitelistingEnabled.js (80%) rename plugins/azure/{securitycenter => defender}/appWhitelistingEnabled.spec.js (100%) rename plugins/azure/{securitycenter => defender}/autoProvisioningEnabled.js (93%) rename plugins/azure/{securitycenter => defender}/autoProvisioningEnabled.spec.js (100%) rename plugins/azure/{securitycenter => defender}/highSeverityAlertsEnabled.js (99%) rename plugins/azure/{securitycenter => defender}/highSeverityAlertsEnabled.spec.js (100%) rename plugins/azure/{securitycenter => defender}/monitorEndpointProtection.js (72%) rename plugins/azure/{securitycenter => defender}/monitorEndpointProtection.spec.js (100%) rename plugins/azure/{securitycenter => defender}/monitorExternalAccounts.js (86%) rename plugins/azure/{securitycenter => defender}/monitorExternalAccounts.spec.js (100%) rename plugins/azure/{securitycenter => defender}/monitorIpForwarding.js (84%) rename plugins/azure/{securitycenter => defender}/monitorIpForwarding.spec.js (100%) rename plugins/azure/{securitycenter => defender}/monitorJitNetworkAccess.js (73%) rename plugins/azure/{securitycenter => defender}/monitorJitNetworkAccess.spec.js (100%) rename plugins/azure/{securitycenter => defender}/monitorNextGenerationFirewall.js (78%) rename plugins/azure/{securitycenter => defender}/monitorNextGenerationFirewall.spec.js (100%) rename plugins/azure/{securitycenter => defender}/monitorSubscriptionOwners.js (87%) rename plugins/azure/{securitycenter => defender}/monitorSubscriptionOwners.spec.js (100%) rename plugins/azure/{securitycenter => defender}/monitorSystemUpdates.js (79%) rename plugins/azure/{securitycenter => defender}/monitorSystemUpdates.spec.js (100%) rename plugins/azure/{securitycenter => defender}/securityConfigMonitoring.js (77%) rename plugins/azure/{securitycenter => defender}/securityConfigMonitoring.spec.js (100%) rename plugins/azure/{securitycenter => defender}/securityContactAdditionalEmail.js (98%) rename plugins/azure/{securitycenter => defender}/securityContactAdditionalEmail.spec.js (100%) rename plugins/azure/{securitycenter => defender}/securityContactRoleSetToOwner.js (98%) rename plugins/azure/{securitycenter => defender}/securityContactRoleSetToOwner.spec.js (100%) rename plugins/azure/{securitycenter => defender}/securityContactsEnabled.js (91%) rename plugins/azure/{securitycenter => defender}/securityContactsEnabled.spec.js (100%) rename plugins/azure/{securitycenter => defender}/standardPricingEnabled.js (89%) rename plugins/azure/{securitycenter => defender}/standardPricingEnabled.spec.js (100%) diff --git a/exports.js b/exports.js index dcbf2a3dbb..c54597ccaa 100644 --- a/exports.js +++ b/exports.js @@ -836,28 +836,13 @@ module.exports = { 'virtualMachinesDeallocateAlert': require(__dirname + '/plugins/azure/logalerts/virtualMachinesDeallocateAlert.js'), 'publicIpAddressLoggingEnabled' : require(__dirname+ '/plugins/azure/logalerts/publicIpAddressLoggingEnabled.js'), - 'monitorEndpointProtection' : require(__dirname + '/plugins/azure/securitycenter/monitorEndpointProtection.js'), - 'monitorBlobEncryption' : require(__dirname + '/plugins/azure/securitycenter/monitorBlobEncryption.js'), - 'monitorSystemUpdates' : require(__dirname + '/plugins/azure/securitycenter/monitorSystemUpdates.js'), - 'monitorJitNetworkAccess' : require(__dirname + '/plugins/azure/securitycenter/monitorJitNetworkAccess.js'), - 'monitorVMVulnerability' : require(__dirname + '/plugins/azure/securitycenter/monitorVMVulnerability.js'), - 'monitorSQLEncryption' : require(__dirname + '/plugins/azure/securitycenter/monitorSqlEncryption.js'), - 'monitorSQLAuditing' : require(__dirname + '/plugins/azure/securitycenter/monitorSqlAuditing.js'), - 'monitorDiskEncryption' : require(__dirname + '/plugins/azure/securitycenter/monitorDiskEncryption.js'), - 'appWhitelistingEnabled' : require(__dirname + '/plugins/azure/securitycenter/appWhitelistingEnabled.js'), - 'securityConfigMonitoring' : require(__dirname + '/plugins/azure/securitycenter/securityConfigMonitoring.js'), - 'autoProvisioningEnabled' : require(__dirname + '/plugins/azure/securitycenter/autoProvisioningEnabled.js'), - 'adminSecurityAlertsEnabled' : require(__dirname + '/plugins/azure/securitycenter/adminSecurityAlertsEnabled.js'), - 'securityContactsEnabled' : require(__dirname + '/plugins/azure/securitycenter/securityContactsEnabled.js'), - 'monitorNsgEnabled' : require(__dirname + '/plugins/azure/securitycenter/monitorNsgEnabled.js'), - 'highSeverityAlertsEnabled' : require(__dirname + '/plugins/azure/securitycenter/highSeverityAlertsEnabled.js'), - 'standardPricingEnabled' : require(__dirname + '/plugins/azure/securitycenter/standardPricingEnabled.js'), - 'monitorExternalAccounts' : require(__dirname + '/plugins/azure/securitycenter/monitorExternalAccounts.js'), - 'monitorIpForwarding' : require(__dirname + '/plugins/azure/securitycenter/monitorIpForwarding.js'), - 'monitorNextGenerationFirewall' : require(__dirname + '/plugins/azure/securitycenter/monitorNextGenerationFirewall.js'), - 'monitorSubscriptionOwners' : require(__dirname + '/plugins/azure/securitycenter/monitorSubscriptionOwners.js'), - 'securityContactAdditionalEmail': require(__dirname + '/plugins/azure/securitycenter/securityContactAdditionalEmail.js'), - 'securityContactRoleSetToOwner' : require(__dirname + '/plugins/azure/securitycenter/securityContactRoleSetToOwner.js'), + 'monitorBlobEncryption' : require(__dirname + '/plugins/azure/securitycenter/monitorBlobEncryption.js'), + 'monitorVMVulnerability' : require(__dirname + '/plugins/azure/securitycenter/monitorVMVulnerability.js'), + 'monitorSQLEncryption' : require(__dirname + '/plugins/azure/securitycenter/monitorSqlEncryption.js'), + 'monitorSQLAuditing' : require(__dirname + '/plugins/azure/securitycenter/monitorSqlAuditing.js'), + 'monitorDiskEncryption' : require(__dirname + '/plugins/azure/securitycenter/monitorDiskEncryption.js'), + 'adminSecurityAlertsEnabled' : require(__dirname + '/plugins/azure/securitycenter/adminSecurityAlertsEnabled.js'), + 'monitorNsgEnabled' : require(__dirname + '/plugins/azure/securitycenter/monitorNsgEnabled.js'), 'resourceAllowedLocations' : require(__dirname + '/plugins/azure/policyservice/resourceAllowedLocations.js'), 'resourceLocationMatch' : require(__dirname + '/plugins/azure/policyservice/resourceLocationMatch.js'), @@ -1097,6 +1082,21 @@ module.exports = { 'enableDefenderForAPIs' : require(__dirname + '/plugins/azure/defender/enableDefenderForAPIs.js'), 'enableDefenderForCosmosDB' : require(__dirname + '/plugins/azure/defender/enableDefenderForCosmosDB.js'), 'enableDefenderForSqlServersVMs': require(__dirname + '/plugins/azure/defender/enableDefenderForSqlServersVMs.js'), + 'highSeverityAlertsEnabled' : require(__dirname + '/plugins/azure/defender/highSeverityAlertsEnabled.js'), + 'standardPricingEnabled' : require(__dirname + '/plugins/azure/defender/standardPricingEnabled.js'), + 'monitorExternalAccounts' : require(__dirname + '/plugins/azure/defender/monitorExternalAccounts.js'), + 'monitorIpForwarding' : require(__dirname + '/plugins/azure/defender/monitorIpForwarding.js'), + 'monitorNextGenerationFirewall' : require(__dirname + '/plugins/azure/defender/monitorNextGenerationFirewall.js'), + 'monitorSubscriptionOwners' : require(__dirname + '/plugins/azure/defender/monitorSubscriptionOwners.js'), + 'securityContactAdditionalEmail': require(__dirname + '/plugins/azure/defender/securityContactAdditionalEmail.js'), + 'securityContactRoleSetToOwner' : require(__dirname + '/plugins/azure/defender/securityContactRoleSetToOwner.js'), + 'appWhitelistingEnabled' : require(__dirname + '/plugins/azure/defender/appWhitelistingEnabled.js'), + 'securityConfigMonitoring' : require(__dirname + '/plugins/azure/defender/securityConfigMonitoring.js'), + 'autoProvisioningEnabled' : require(__dirname + '/plugins/azure/defender/autoProvisioningEnabled.js'), + 'monitorSystemUpdates' : require(__dirname + '/plugins/azure/defender/monitorSystemUpdates.js'), + 'monitorEndpointProtection' : require(__dirname + '/plugins/azure/defender/monitorEndpointProtection.js'), + 'monitorJitNetworkAccess' : require(__dirname + '/plugins/azure/defender/monitorJitNetworkAccess.js'), + 'securityContactsEnabled' : require(__dirname + '/plugins/azure/defender/securityContactsEnabled.js'), 'agWafEnabled' : require(__dirname + '/plugins/azure/applicationGateway/agWafEnabled'), 'applicationGatewayHasTags' : require(__dirname + '/plugins/azure/applicationGateway/applicationGatewayHasTags.js'), diff --git a/plugins/azure/securitycenter/appWhitelistingEnabled.js b/plugins/azure/defender/appWhitelistingEnabled.js similarity index 80% rename from plugins/azure/securitycenter/appWhitelistingEnabled.js rename to plugins/azure/defender/appWhitelistingEnabled.js index 9c6be1a148..9dccca7b50 100644 --- a/plugins/azure/securitycenter/appWhitelistingEnabled.js +++ b/plugins/azure/defender/appWhitelistingEnabled.js @@ -3,13 +3,13 @@ const helpers = require('../../../helpers/azure'); module.exports = { title: 'Application Whitelisting Enabled', - category: 'Security Center', + category: 'Defender', domain: 'Management and Governance', severity: 'Medium', - description: 'Ensures that Security Center Monitor Adaptive Application Whitelisting is enabled', + description: 'Ensures that Microsoft Defender Monitor Adaptive Application Whitelisting is enabled.', more_info: 'Adaptive application controls work in conjunction with machine learning to analyze processes running in a VM and help control which applications can run, hardening the VM against malware.', - recommended_action: 'Enable Adaptive Application Controls for Virtual Machines from the Azure Security Center by ensuring AuditIfNotExists setting is used.', - link: 'https://learn.microsoft.com/en-us/azure/security-center/security-center-adaptive-application', + recommended_action: 'Enable Adaptive Application Controls for Virtual Machines from the Microsoft Defender for Cloud by ensuring AuditIfNotExists setting is used.', + link: 'https://learn.microsoft.com/en-us/azure/defender-for-cloud/adaptive-application-controls', apis: ['policyAssignments:list'], realtime_triggers: ['microsoftauthorization:policyassignments:write','microsoftauthorization:policyassignments:delete'], diff --git a/plugins/azure/securitycenter/appWhitelistingEnabled.spec.js b/plugins/azure/defender/appWhitelistingEnabled.spec.js similarity index 100% rename from plugins/azure/securitycenter/appWhitelistingEnabled.spec.js rename to plugins/azure/defender/appWhitelistingEnabled.spec.js diff --git a/plugins/azure/securitycenter/autoProvisioningEnabled.js b/plugins/azure/defender/autoProvisioningEnabled.js similarity index 93% rename from plugins/azure/securitycenter/autoProvisioningEnabled.js rename to plugins/azure/defender/autoProvisioningEnabled.js index 233572f2e3..fb95ccfe0e 100644 --- a/plugins/azure/securitycenter/autoProvisioningEnabled.js +++ b/plugins/azure/defender/autoProvisioningEnabled.js @@ -3,13 +3,13 @@ const helpers = require('../../../helpers/azure'); module.exports = { title: 'Auto Provisioning Enabled', - category: 'Security Center', + category: 'Defender', domain: 'Management and Governance', severity: 'Medium', - description: 'Ensures that automatic provisioning of the monitoring agent is enabled', + description: 'Ensures that automatic provisioning of the monitoring agent is enabled.', more_info: 'The Microsoft Monitoring Agent scans for various security-related configurations and events such as system updates, OS vulnerabilities, and endpoint protection and provides alerts.', recommended_action: 'Ensure that the data collection settings of the subscription have Auto Provisioning set to enabled.', - link: 'https://learn.microsoft.com/en-us/azure/security-center/security-center-enable-data-collection', + link: 'https://learn.microsoft.com/en-us/azure/defender-for-cloud/monitoring-components', apis: ['autoProvisioningSettings:list'], realtime_triggers: ['microsoftauthorization:policyassignments:write','microsoftauthorization:policyassignments:delete'], diff --git a/plugins/azure/securitycenter/autoProvisioningEnabled.spec.js b/plugins/azure/defender/autoProvisioningEnabled.spec.js similarity index 100% rename from plugins/azure/securitycenter/autoProvisioningEnabled.spec.js rename to plugins/azure/defender/autoProvisioningEnabled.spec.js diff --git a/plugins/azure/securitycenter/highSeverityAlertsEnabled.js b/plugins/azure/defender/highSeverityAlertsEnabled.js similarity index 99% rename from plugins/azure/securitycenter/highSeverityAlertsEnabled.js rename to plugins/azure/defender/highSeverityAlertsEnabled.js index 655a018159..2a13ed372d 100644 --- a/plugins/azure/securitycenter/highSeverityAlertsEnabled.js +++ b/plugins/azure/defender/highSeverityAlertsEnabled.js @@ -5,7 +5,7 @@ const SEVERITY_LEVELS = ['low', 'medium', 'high']; module.exports = { title: 'High Severity Alerts Enabled', - category: 'Security Center', + category: 'Defender', domain: 'Management and Governance', severity: 'Medium', description: 'Ensures that high severity alerts are enabled and properly configured.', diff --git a/plugins/azure/securitycenter/highSeverityAlertsEnabled.spec.js b/plugins/azure/defender/highSeverityAlertsEnabled.spec.js similarity index 100% rename from plugins/azure/securitycenter/highSeverityAlertsEnabled.spec.js rename to plugins/azure/defender/highSeverityAlertsEnabled.spec.js diff --git a/plugins/azure/securitycenter/monitorEndpointProtection.js b/plugins/azure/defender/monitorEndpointProtection.js similarity index 72% rename from plugins/azure/securitycenter/monitorEndpointProtection.js rename to plugins/azure/defender/monitorEndpointProtection.js index 130943e89c..7c636b7f00 100644 --- a/plugins/azure/securitycenter/monitorEndpointProtection.js +++ b/plugins/azure/defender/monitorEndpointProtection.js @@ -3,13 +3,13 @@ const helpers = require('../../../helpers/azure'); module.exports = { title: 'Monitor Endpoint Protection', - category: 'Security Center', + category: 'Defender', domain: 'Management and Governance', severity: 'Medium', - description: 'Ensures Endpoint Protection monitoring is enabled in Security Center', - more_info: 'When this setting is enabled, Security Center audits the Endpoint Protection setting for all virtual machines for malware protection.', - recommended_action: 'Enable Adaptive Application Controls for Endpoint Protection from the Azure Security Center by ensuring AuditIfNotExists setting is used to monitor missing Endpoint Protection.', - link: 'https://learn.microsoft.com/en-us/azure/security-center/security-center-policy-definitions', + description: 'Ensures Endpoint Protection monitoring is enabled in Microsoft Defender.', + more_info: 'When this setting is enabled, Microsoft Defender for Cloud audits the Endpoint Protection setting for all virtual machines for malware protection.', + recommended_action: 'Enable Adaptive Application Controls for Endpoint Protection from the Microsoft Defender by ensuring AuditIfNotExists setting is used to monitor missing Endpoint Protection.', + link: 'https://learn.microsoft.com/en-us/azure/defender-for-cloud/policy-reference', apis: ['policyAssignments:list'], realtime_triggers: ['microsoftauthorization:policyassignments:write','microsoftauthorization:policyassignments:delete'], diff --git a/plugins/azure/securitycenter/monitorEndpointProtection.spec.js b/plugins/azure/defender/monitorEndpointProtection.spec.js similarity index 100% rename from plugins/azure/securitycenter/monitorEndpointProtection.spec.js rename to plugins/azure/defender/monitorEndpointProtection.spec.js diff --git a/plugins/azure/securitycenter/monitorExternalAccounts.js b/plugins/azure/defender/monitorExternalAccounts.js similarity index 86% rename from plugins/azure/securitycenter/monitorExternalAccounts.js rename to plugins/azure/defender/monitorExternalAccounts.js index 841068fc92..e0e54cfc39 100644 --- a/plugins/azure/securitycenter/monitorExternalAccounts.js +++ b/plugins/azure/defender/monitorExternalAccounts.js @@ -3,13 +3,13 @@ const helpers = require('../../../helpers/azure'); module.exports = { title: 'Monitor External Accounts with Write Permissions', - category: 'Security Center', + category: 'Defender', domain: 'Management and Governance', severity: 'Medium', - description: 'Ensures that External Accounts with Write Permissions are being Monitored in Security Center', + description: 'Ensures that External Accounts with Write Permissions are being Monitored in Microsoft Defender.', more_info: 'External Accounts with Write Permissions should be monitored to meet you organization\'s security compliance requirements.', - recommended_action: 'Enable Monitor for External Accounts with Write Permissions by ensuring AuditIfNotExists setting is used for \'External accounts with write permissions should be removed from your subscription\' from the Azure Security Center.', - link: 'https://learn.microsoft.com/en-us/azure/security-center/security-center-policy-definitions', + recommended_action: 'Enable Monitor for External Accounts with Write Permissions by ensuring AuditIfNotExists setting is used for \'External accounts with write permissions should be removed from your subscription\' from the Microsoft Defender.', + link: 'https://learn.microsoft.com/en-us/azure/defender-for-cloud/policy-reference', apis: ['policyAssignments:list'], realtime_triggers: ['microsoftauthorization:policyassignments:write','microsoftauthorization:policyassignments:delete'], diff --git a/plugins/azure/securitycenter/monitorExternalAccounts.spec.js b/plugins/azure/defender/monitorExternalAccounts.spec.js similarity index 100% rename from plugins/azure/securitycenter/monitorExternalAccounts.spec.js rename to plugins/azure/defender/monitorExternalAccounts.spec.js diff --git a/plugins/azure/securitycenter/monitorIpForwarding.js b/plugins/azure/defender/monitorIpForwarding.js similarity index 84% rename from plugins/azure/securitycenter/monitorIpForwarding.js rename to plugins/azure/defender/monitorIpForwarding.js index 1575065008..91ad78b3b1 100644 --- a/plugins/azure/securitycenter/monitorIpForwarding.js +++ b/plugins/azure/defender/monitorIpForwarding.js @@ -3,13 +3,13 @@ const helpers = require('../../../helpers/azure'); module.exports = { title: 'Monitor IP Forwarding', - category: 'Security Center', + category: 'Defender', domain: 'Management and Governance', severity: 'Medium', - description: 'Ensures that Virtual Machine IP Forwarding Monitoring is enabled in Security Center', + description: 'Ensures that Virtual Machine IP Forwarding Monitoring is enabled in Microsoft Defender.', more_info: 'IP Forwarding feature should be monitored to meet you organization\'s security compliance requirements.', - recommended_action: 'Enable IP Forwarding Monitoring by ensuring AuditIfNotExists setting is used for \'IP Forwarding on your virtual machine should be disabled\' from the Azure Security Center.', - link: 'https://learn.microsoft.com/en-us/azure/security-center/security-center-policy-definitions', + recommended_action: 'Enable IP Forwarding Monitoring by ensuring AuditIfNotExists setting is used for \'IP Forwarding on your virtual machine should be disabled\' from the Microsoft Defender.', + link: 'https://learn.microsoft.com/en-us/azure/defender-for-cloud/policy-reference', apis: ['policyAssignments:list'], realtime_triggers: ['microsoftauthorization:policyassignments:write','microsoftauthorization:policyassignments:delete'], diff --git a/plugins/azure/securitycenter/monitorIpForwarding.spec.js b/plugins/azure/defender/monitorIpForwarding.spec.js similarity index 100% rename from plugins/azure/securitycenter/monitorIpForwarding.spec.js rename to plugins/azure/defender/monitorIpForwarding.spec.js diff --git a/plugins/azure/securitycenter/monitorJitNetworkAccess.js b/plugins/azure/defender/monitorJitNetworkAccess.js similarity index 73% rename from plugins/azure/securitycenter/monitorJitNetworkAccess.js rename to plugins/azure/defender/monitorJitNetworkAccess.js index 19d98fb555..e3b0b0ccb5 100644 --- a/plugins/azure/securitycenter/monitorJitNetworkAccess.js +++ b/plugins/azure/defender/monitorJitNetworkAccess.js @@ -3,13 +3,13 @@ const helpers = require('../../../helpers/azure'); module.exports = { title: 'Monitor JIT Network Access', - category: 'Security Center', + category: 'Defender', domain: 'Management and Governance', severity: 'Medium', - description: 'Ensures Just In Time Network Access monitoring is enabled in Security Center', - more_info: 'When this setting is enabled, Security Center audits Just In Time Network Access on all virtual machines (Windows and Linux as well) to enhance data protection at rest', - recommended_action: 'Ensure JIT Network Access monitoring is configured for compute and apps from the Azure Security Center.', - link: 'https://learn.microsoft.com/en-us/azure/security-center/security-center-policy-definitions', + description: 'Ensures Just In Time Network Access monitoring is enabled in Microsoft Defender.', + more_info: 'When this setting is enabled, Microsoft Defender for Cloud audits Just In Time Network Access on all virtual machines (Windows and Linux as well) to enhance data protection at rest', + recommended_action: 'Ensure JIT Network Access monitoring is configured for compute and apps from Microsoft Defender.', + link: 'https://learn.microsoft.com/en-us/azure/defender-for-cloud/policy-reference', apis: ['policyAssignments:list'], realtime_triggers: ['microsoftauthorization:policyassignments:write','microsoftauthorization:policyassignments:delete'], diff --git a/plugins/azure/securitycenter/monitorJitNetworkAccess.spec.js b/plugins/azure/defender/monitorJitNetworkAccess.spec.js similarity index 100% rename from plugins/azure/securitycenter/monitorJitNetworkAccess.spec.js rename to plugins/azure/defender/monitorJitNetworkAccess.spec.js diff --git a/plugins/azure/securitycenter/monitorNextGenerationFirewall.js b/plugins/azure/defender/monitorNextGenerationFirewall.js similarity index 78% rename from plugins/azure/securitycenter/monitorNextGenerationFirewall.js rename to plugins/azure/defender/monitorNextGenerationFirewall.js index 8a6fa27b76..9f3777b882 100644 --- a/plugins/azure/securitycenter/monitorNextGenerationFirewall.js +++ b/plugins/azure/defender/monitorNextGenerationFirewall.js @@ -3,13 +3,13 @@ const helpers = require('../../../helpers/azure'); module.exports = { title: 'Monitor Next Generation Firewall', - category: 'Security Center', + category: 'Defender', domain: 'Management and Governance', severity: 'Medium', - description: 'Ensures that Next Generation Firewall (NGFW) Monitoring is enabled in Security Center', - more_info: 'When this setting is enabled, Security Center will search for deployments where a NGFW is recommended.', - recommended_action: 'Enable Next Generation Firewall Monitoring by ensuring AuditIfNotExists setting is used for \'All network ports should be restricted on network security groups associated to your virtual machine\' from the Azure Security Center.', - link: 'https://learn.microsoft.com/en-us/azure/security-center/security-center-policy-definitions', + description: 'Ensures that Next Generation Firewall (NGFW) Monitoring is enabled in Microsoft Defender.', + more_info: 'When this setting is enabled, Microsoft Defender for Cloud will search for deployments where a NGFW is recommended.', + recommended_action: 'Enable Next Generation Firewall Monitoring by ensuring AuditIfNotExists setting is used for \'All network ports should be restricted on network security groups associated to your virtual machine\' from the Microsoft Defender.', + link: 'https://learn.microsoft.com/en-us/azure/defender-for-cloud/policy-reference', apis: ['policyAssignments:list'], realtime_triggers: ['microsoftauthorization:policyassignments:write','microsoftauthorization:policyassignments:delete'], diff --git a/plugins/azure/securitycenter/monitorNextGenerationFirewall.spec.js b/plugins/azure/defender/monitorNextGenerationFirewall.spec.js similarity index 100% rename from plugins/azure/securitycenter/monitorNextGenerationFirewall.spec.js rename to plugins/azure/defender/monitorNextGenerationFirewall.spec.js diff --git a/plugins/azure/securitycenter/monitorSubscriptionOwners.js b/plugins/azure/defender/monitorSubscriptionOwners.js similarity index 87% rename from plugins/azure/securitycenter/monitorSubscriptionOwners.js rename to plugins/azure/defender/monitorSubscriptionOwners.js index dcd29b4c63..f69c717758 100644 --- a/plugins/azure/securitycenter/monitorSubscriptionOwners.js +++ b/plugins/azure/defender/monitorSubscriptionOwners.js @@ -3,13 +3,13 @@ const helpers = require('../../../helpers/azure'); module.exports = { title: 'Monitor Total Number of Subscription Owners', - category: 'Security Center', + category: 'Defender', domain: 'Management and Governance', severity: 'Medium', - description: 'Ensures that Total Number of Subscription Owners is being Monitored in Security Center', + description: 'Ensures that Total Number of Subscription Owners is being Monitored in Microsoft Defender.', more_info: 'Total Number of Subscription Owners should be monitored to meet you organization\'s security compliance requirements.', - recommended_action: 'Enable Monitor for Total Number of Subscription Owners by ensuring AuditIfNotExists setting is used for \'A maximum of 3 owners should be designated for your subscription\' from the Azure Security Center.', - link: 'https://learn.microsoft.com/en-us/azure/security-center/security-center-policy-definitions', + recommended_action: 'Enable Monitor for Total Number of Subscription Owners by ensuring AuditIfNotExists setting is used for \'A maximum of 3 owners should be designated for your subscription\' from the Microsoft Defender.', + link: 'https://learn.microsoft.com/en-us/azure/defender-for-cloud/policy-reference', apis: ['policyAssignments:list'], realtime_triggers: ['microsoftauthorization:policyassignments:write','microsoftauthorization:policyassignments:delete'], diff --git a/plugins/azure/securitycenter/monitorSubscriptionOwners.spec.js b/plugins/azure/defender/monitorSubscriptionOwners.spec.js similarity index 100% rename from plugins/azure/securitycenter/monitorSubscriptionOwners.spec.js rename to plugins/azure/defender/monitorSubscriptionOwners.spec.js diff --git a/plugins/azure/securitycenter/monitorSystemUpdates.js b/plugins/azure/defender/monitorSystemUpdates.js similarity index 79% rename from plugins/azure/securitycenter/monitorSystemUpdates.js rename to plugins/azure/defender/monitorSystemUpdates.js index d3a33dd8aa..83d36c78bb 100644 --- a/plugins/azure/securitycenter/monitorSystemUpdates.js +++ b/plugins/azure/defender/monitorSystemUpdates.js @@ -3,13 +3,13 @@ const helpers = require('../../../helpers/azure'); module.exports = { title: 'Monitor System Updates', - category: 'Security Center', + category: 'Defender', domain: 'Management and Governance', severity: 'Medium', - description: 'Ensures that Monitor System Updates is enabled in Security Center', - more_info: 'When this setting is enabled, Security Center will audit virtual machines for pending OS or system updates.', - recommended_action: 'Ensure System Update monitoring is configured for virtual machines from the Azure Security Center.', - link: 'https://learn.microsoft.com/en-us/azure/security-center/security-center-policy-definitions', + description: 'Ensures that Monitor System Updates is enabled in Microsoft Defender.', + more_info: 'When this setting is enabled, Microsoft Defender for Cloud will audit virtual machines for pending OS or system updates.', + recommended_action: 'Ensure System Update monitoring is configured for virtual machines from the Microsoft Defender.', + link: 'https://learn.microsoft.com/en-us/azure/defender-for-cloud/policy-reference', apis: ['policyAssignments:list'], compliance: { pci: 'PCI requires all system components have the latest updates ' + diff --git a/plugins/azure/securitycenter/monitorSystemUpdates.spec.js b/plugins/azure/defender/monitorSystemUpdates.spec.js similarity index 100% rename from plugins/azure/securitycenter/monitorSystemUpdates.spec.js rename to plugins/azure/defender/monitorSystemUpdates.spec.js diff --git a/plugins/azure/securitycenter/securityConfigMonitoring.js b/plugins/azure/defender/securityConfigMonitoring.js similarity index 77% rename from plugins/azure/securitycenter/securityConfigMonitoring.js rename to plugins/azure/defender/securityConfigMonitoring.js index f4e8336308..739a40b763 100644 --- a/plugins/azure/securitycenter/securityConfigMonitoring.js +++ b/plugins/azure/defender/securityConfigMonitoring.js @@ -3,13 +3,13 @@ const helpers = require('../../../helpers/azure'); module.exports = { title: 'Security Configuration Monitoring', - category: 'Security Center', + category: 'Defender', domain: 'Management and Governance', severity: 'Medium', - description: 'Ensures that Security Configuration Monitoring is enabled in Security Center', - more_info: 'When this setting is enabled, Security Center will monitor virtual machines for security configurations.', - recommended_action: 'Ensure Security Configuration Monitoring is configured for virtual machines from the Azure Security Center.', - link: 'https://learn.microsoft.com/en-us/azure/governance/policy/overview', + description: 'Ensures that Security Configuration Monitoring is enabled in Microsoft Defender.', + more_info: 'When this setting is enabled, Microsoft Defender for Cloud will monitor virtual machines for security configurations.', + recommended_action: 'Ensure Security Configuration Monitoring is configured for virtual machines from the Microsoft Defender.', + link: 'https://learn.microsoft.com/en-us/azure/defender-for-cloud/policy-reference', apis: ['policyAssignments:list'], realtime_triggers: ['microsoftauthorization:policyassignments:write','microsoftauthorization:policyassignments:delete'], diff --git a/plugins/azure/securitycenter/securityConfigMonitoring.spec.js b/plugins/azure/defender/securityConfigMonitoring.spec.js similarity index 100% rename from plugins/azure/securitycenter/securityConfigMonitoring.spec.js rename to plugins/azure/defender/securityConfigMonitoring.spec.js diff --git a/plugins/azure/securitycenter/securityContactAdditionalEmail.js b/plugins/azure/defender/securityContactAdditionalEmail.js similarity index 98% rename from plugins/azure/securitycenter/securityContactAdditionalEmail.js rename to plugins/azure/defender/securityContactAdditionalEmail.js index 874153a103..e669d7302e 100644 --- a/plugins/azure/securitycenter/securityContactAdditionalEmail.js +++ b/plugins/azure/defender/securityContactAdditionalEmail.js @@ -3,7 +3,7 @@ const helpers = require('../../../helpers/azure'); module.exports = { title: 'Security Contact Additional Email', - category: 'Security Center', + category: 'Defender', domain: 'Management and Governance', severity: 'Low', description: 'Ensure Additional email addresses are configured with security contact email.', diff --git a/plugins/azure/securitycenter/securityContactAdditionalEmail.spec.js b/plugins/azure/defender/securityContactAdditionalEmail.spec.js similarity index 100% rename from plugins/azure/securitycenter/securityContactAdditionalEmail.spec.js rename to plugins/azure/defender/securityContactAdditionalEmail.spec.js diff --git a/plugins/azure/securitycenter/securityContactRoleSetToOwner.js b/plugins/azure/defender/securityContactRoleSetToOwner.js similarity index 98% rename from plugins/azure/securitycenter/securityContactRoleSetToOwner.js rename to plugins/azure/defender/securityContactRoleSetToOwner.js index c1632e7153..aaa5bfb613 100644 --- a/plugins/azure/securitycenter/securityContactRoleSetToOwner.js +++ b/plugins/azure/defender/securityContactRoleSetToOwner.js @@ -3,7 +3,7 @@ const helpers = require('../../../helpers/azure'); module.exports = { title: 'Security Contact Enabled for Subscription Owner', - category: 'Security Center', + category: 'Defender', domain: 'Management and Governance', severity: 'Medium', description: 'Ensure that security alert emails are enabled to subscription owners.', diff --git a/plugins/azure/securitycenter/securityContactRoleSetToOwner.spec.js b/plugins/azure/defender/securityContactRoleSetToOwner.spec.js similarity index 100% rename from plugins/azure/securitycenter/securityContactRoleSetToOwner.spec.js rename to plugins/azure/defender/securityContactRoleSetToOwner.spec.js diff --git a/plugins/azure/securitycenter/securityContactsEnabled.js b/plugins/azure/defender/securityContactsEnabled.js similarity index 91% rename from plugins/azure/securitycenter/securityContactsEnabled.js rename to plugins/azure/defender/securityContactsEnabled.js index 136650a808..5d868c5ce6 100644 --- a/plugins/azure/securitycenter/securityContactsEnabled.js +++ b/plugins/azure/defender/securityContactsEnabled.js @@ -3,13 +3,13 @@ const helpers = require('../../../helpers/azure'); module.exports = { title: 'Security Contacts Enabled', - category: 'Security Center', + category: 'Defender', domain: 'Management and Governance', severity: 'Medium', - description: 'Ensures that security contact phone number and email address are set', + description: 'Ensures that security contact phone number and email address are set.', more_info: 'Setting security contacts ensures that any security incidents detected by Azure are sent to a security team equipped to handle the incident.', - recommended_action: 'Ensure that email notifications are configured for the subscription from the Security Center.', - link: 'https://learn.microsoft.com/en-us/azure/security-center/security-center-provide-security-contact-details', + recommended_action: 'Ensure that email notifications are configured for the subscription from the Microsoft Defender for Cloud.', + link: 'https://learn.microsoft.com/en-us/azure/defender-for-cloud/configure-email-notifications', apis: ['securityContacts:list'], realtime_triggers: ['microsoftsecurity:securitycontacts:write','microsoftsecurity:securitycontacts:delete'], diff --git a/plugins/azure/securitycenter/securityContactsEnabled.spec.js b/plugins/azure/defender/securityContactsEnabled.spec.js similarity index 100% rename from plugins/azure/securitycenter/securityContactsEnabled.spec.js rename to plugins/azure/defender/securityContactsEnabled.spec.js diff --git a/plugins/azure/securitycenter/standardPricingEnabled.js b/plugins/azure/defender/standardPricingEnabled.js similarity index 89% rename from plugins/azure/securitycenter/standardPricingEnabled.js rename to plugins/azure/defender/standardPricingEnabled.js index 5df694d463..761752d7a6 100644 --- a/plugins/azure/securitycenter/standardPricingEnabled.js +++ b/plugins/azure/defender/standardPricingEnabled.js @@ -3,13 +3,13 @@ var helpers = require('../../../helpers/azure/'); module.exports = { title: 'Standard Pricing Enabled', - category: 'Security Center', + category: 'Defender', domain: 'Management and Governance', severity: 'Medium', - description: 'Ensures that standard pricing is enabled in the security center', - more_info: 'Enabling standard pricing increases the security posture of the subscription. This enables advanced security monitoring for the services covered under the security center.', - recommended_action: 'Ensure that standard pricing is enabled in the security center.', - link: 'https://azure.microsoft.com/en-us/pricing/details/security-center/', + description: 'Ensures that standard pricing is enabled in the Microsoft Defender.', + more_info: 'Enabling standard pricing increases the security posture of the subscription. This enables advanced security monitoring for the services covered under the Microsoft Defender for Cloud.', + recommended_action: 'Ensure that standard pricing is enabled in the Microsoft Defender.', + link: 'https://learn.microsoft.com/en-us/azure/defender-for-cloud/policy-reference', apis: ['pricings:list'], realtime_triggers: ['microsoftsecurity:pricings:write','microsoftsecurity:pricings:delete'], diff --git a/plugins/azure/securitycenter/standardPricingEnabled.spec.js b/plugins/azure/defender/standardPricingEnabled.spec.js similarity index 100% rename from plugins/azure/securitycenter/standardPricingEnabled.spec.js rename to plugins/azure/defender/standardPricingEnabled.spec.js From 6ca6b234ef11d3c6b15ceaac88537858de301aa1 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 26 Aug 2024 13:33:42 +0500 Subject: [PATCH 43/91] fix lint --- exports.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/exports.js b/exports.js index c54597ccaa..e0913581dd 100644 --- a/exports.js +++ b/exports.js @@ -836,13 +836,13 @@ module.exports = { 'virtualMachinesDeallocateAlert': require(__dirname + '/plugins/azure/logalerts/virtualMachinesDeallocateAlert.js'), 'publicIpAddressLoggingEnabled' : require(__dirname+ '/plugins/azure/logalerts/publicIpAddressLoggingEnabled.js'), - 'monitorBlobEncryption' : require(__dirname + '/plugins/azure/securitycenter/monitorBlobEncryption.js'), - 'monitorVMVulnerability' : require(__dirname + '/plugins/azure/securitycenter/monitorVMVulnerability.js'), - 'monitorSQLEncryption' : require(__dirname + '/plugins/azure/securitycenter/monitorSqlEncryption.js'), - 'monitorSQLAuditing' : require(__dirname + '/plugins/azure/securitycenter/monitorSqlAuditing.js'), - 'monitorDiskEncryption' : require(__dirname + '/plugins/azure/securitycenter/monitorDiskEncryption.js'), - 'adminSecurityAlertsEnabled' : require(__dirname + '/plugins/azure/securitycenter/adminSecurityAlertsEnabled.js'), - 'monitorNsgEnabled' : require(__dirname + '/plugins/azure/securitycenter/monitorNsgEnabled.js'), + 'monitorBlobEncryption' : require(__dirname + '/plugins/azure/securitycenter/monitorBlobEncryption.js'), + 'monitorVMVulnerability' : require(__dirname + '/plugins/azure/securitycenter/monitorVMVulnerability.js'), + 'monitorSQLEncryption' : require(__dirname + '/plugins/azure/securitycenter/monitorSqlEncryption.js'), + 'monitorSQLAuditing' : require(__dirname + '/plugins/azure/securitycenter/monitorSqlAuditing.js'), + 'monitorDiskEncryption' : require(__dirname + '/plugins/azure/securitycenter/monitorDiskEncryption.js'), + 'adminSecurityAlertsEnabled' : require(__dirname + '/plugins/azure/securitycenter/adminSecurityAlertsEnabled.js'), + 'monitorNsgEnabled' : require(__dirname + '/plugins/azure/securitycenter/monitorNsgEnabled.js'), 'resourceAllowedLocations' : require(__dirname + '/plugins/azure/policyservice/resourceAllowedLocations.js'), 'resourceLocationMatch' : require(__dirname + '/plugins/azure/policyservice/resourceLocationMatch.js'), From 5ecaafc7df1d0295e17a36257e95259e41a84a2a Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 26 Aug 2024 14:02:08 +0500 Subject: [PATCH 44/91] update message --- plugins/aws/qldb/ledgerHasTags.js | 4 ++-- plugins/aws/qldb/ledgerHasTags.spec.js | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/aws/qldb/ledgerHasTags.js b/plugins/aws/qldb/ledgerHasTags.js index 649b00fa11..eecd57c15e 100644 --- a/plugins/aws/qldb/ledgerHasTags.js +++ b/plugins/aws/qldb/ledgerHasTags.js @@ -30,12 +30,12 @@ module.exports = { if (listLedgers.err || !listLedgers.data) { helpers.addResult(results, 3, - 'Unable to query Ledgers: ' + helpers.addError(listLedgers), region); + 'Unable to query QLDB ledgers: ' + helpers.addError(listLedgers), region); return rcb(); } if (!listLedgers.data.length) { - helpers.addResult(results, 0, 'No Ledgers found', region); + helpers.addResult(results, 0, 'No QLDB ledgers found', region); return rcb(); } diff --git a/plugins/aws/qldb/ledgerHasTags.spec.js b/plugins/aws/qldb/ledgerHasTags.spec.js index 0e06e273d7..ab3365604b 100644 --- a/plugins/aws/qldb/ledgerHasTags.spec.js +++ b/plugins/aws/qldb/ledgerHasTags.spec.js @@ -57,6 +57,7 @@ describe('ledgerHasTags', function () { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('QLDB ledger has tags'); done(); }); }); @@ -67,6 +68,7 @@ describe('ledgerHasTags', function () { 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('QLDB ledger does not have any tags'); done(); }); }); @@ -77,6 +79,7 @@ describe('ledgerHasTags', function () { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('No QLDB ledgers found'); done(); }); }); @@ -87,6 +90,7 @@ describe('ledgerHasTags', function () { expect(results.length).to.equal(1); expect(results[0].status).to.equal(3); expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('Unable to query QLDB ledgers'); done(); }); }); From 46e7f21d5d895575387bfd658ff4b946d2e17bf0 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 26 Aug 2024 14:03:10 +0500 Subject: [PATCH 45/91] update message --- plugins/azure/synapse/workspaceDoubleEncryption.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/synapse/workspaceDoubleEncryption.js b/plugins/azure/synapse/workspaceDoubleEncryption.js index 252a16321f..4382d68ff3 100644 --- a/plugins/azure/synapse/workspaceDoubleEncryption.js +++ b/plugins/azure/synapse/workspaceDoubleEncryption.js @@ -6,7 +6,7 @@ module.exports = { category: 'AI & ML', domain: 'Machine Learning', severity: 'High', - description: 'Ensures that Azure Synapse workspace has double Encryption enabled.', + description: 'Ensures that Azure Synapse workspaces have double Encryption enabled.', more_info: 'Enabling double encryption for Synapse workspace provides an extra layer of protection for data at rest and in transit. This feature significantly enhances security and helps ensure compliance with stringent data protection standards within the Azure environment.', recommended_action: 'Create a new Synapse workspace and enable double encryption using CMK.', link: 'https://learn.microsoft.com/en-us/azure/synapse-analytics/security/workspaces-encryption', From e92a6ff8ed8e9e2873a39563d34cc72007fac8b0 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 26 Aug 2024 14:05:38 +0500 Subject: [PATCH 46/91] updated the default encryption level to awskms for aws encryption plugins --- plugins/aws/apprunner/serviceEncrypted.js | 2 +- .../aws/auditmanager/auditmanagerDataEncrypted.js | 2 +- .../auditmanager/auditmanagerDataEncrypted.spec.js | 2 +- plugins/aws/backup/backupVaultEncrypted.js | 2 +- plugins/aws/cloudwatchlogs/logGroupsEncrypted.js | 2 +- .../aws/codeartifact/codeartifactDomainEncrypted.js | 2 +- .../codeartifact/codeartifactDomainEncrypted.spec.js | 2 +- plugins/aws/codebuild/projectArtifactsEncrypted.js | 2 +- .../aws/codebuild/projectArtifactsEncrypted.spec.js | 2 +- .../aws/codepipeline/pipelineArtifactsEncrypted.js | 2 +- .../codepipeline/pipelineArtifactsEncrypted.spec.js | 4 ++-- .../aws/connect/customerProfilesDomainEncrypted.js | 2 +- plugins/aws/connect/instanceAttachmentsEncrypted.js | 2 +- .../aws/connect/instanceAttachmentsEncrypted.spec.js | 2 +- .../aws/connect/instanceCallRecordingEncrypted.js | 2 +- .../connect/instanceCallRecordingEncrypted.spec.js | 2 +- plugins/aws/connect/instanceMediaStreamsEncrypted.js | 2 +- .../connect/instanceMediaStreamsEncrypted.spec.js | 2 +- plugins/aws/connect/instanceReportsEncrypted.js | 2 +- plugins/aws/connect/instanceReportsEncrypted.spec.js | 2 +- plugins/aws/connect/instanceTranscriptsEncrypted.js | 2 +- .../aws/connect/instanceTranscriptsEncrypted.spec.js | 2 +- plugins/aws/documentDB/docdbClusterEncrypted.js | 2 +- plugins/aws/ec2/ebsEncryptionEnabled.js | 2 +- plugins/aws/ecr/ecrRepositoryEncrypted.js | 2 +- plugins/aws/eks/eksKubernetesVersion.spec.js | 2 +- .../aws/elasticache/redisClusterEncryptionAtRest.js | 2 +- .../elasticache/redisClusterEncryptionAtRest.spec.js | 4 ++-- plugins/aws/firehose/deliveryStreamEncrypted.js | 2 +- plugins/aws/firehose/deliveryStreamEncrypted.spec.js | 4 ++-- .../aws/frauddetector/fraudDetectorDataEncrypted.js | 2 +- plugins/aws/fsx/fsxFileSystemEncrypted.js | 2 +- plugins/aws/glue/glueS3EncryptionEnabled.js | 2 +- plugins/aws/guardduty/exportedFindingsEncrypted.js | 2 +- .../aws/guardduty/exportedFindingsEncrypted.spec.js | 12 ++++++------ plugins/aws/healthlake/dataStoreEncrypted.js | 2 +- plugins/aws/healthlake/dataStoreEncrypted.spec.js | 4 ++-- .../aws/imagebuilder/dockerfileTemplateEncrypted.js | 2 +- .../imagebuilder/dockerfileTemplateEncrypted.spec.js | 2 +- .../aws/imagebuilder/imageRecipeVolumeEncrypted.js | 2 +- .../imagebuilder/imgBuilderComponentsEncrypted.js | 2 +- .../imgBuilderComponentsEncrypted.spec.js | 2 +- plugins/aws/iotsitewise/iotsitewiseDataEncrypted.js | 2 +- plugins/aws/kendra/kendraIndexEncrypted.js | 2 +- plugins/aws/kinesis/kinesisDataStreamsEncrypted.js | 2 +- .../aws/kinesis/kinesisDataStreamsEncrypted.spec.js | 2 +- plugins/aws/kinesisvideo/videostreamDataEncrypted.js | 2 +- plugins/aws/location/geoCollectionDataEncrypted.js | 2 +- plugins/aws/location/trackerDataEncrypted.js | 2 +- plugins/aws/lookout/anomalyDetectorEncrypted.js | 2 +- plugins/aws/lookout/anomalyDetectorEncrypted.spec.js | 2 +- plugins/aws/lookout/equipmentdatasetEncrypted.js | 2 +- .../aws/lookout/equipmentdatasetEncrypted.spec.js | 2 +- plugins/aws/lookout/modelDataEncrypted.js | 2 +- .../managedblockchain/networkMemberDataEncrypted.js | 2 +- .../networkMemberDataEncrypted.spec.js | 2 +- plugins/aws/memorydb/memorydbClusterEncrypted.js | 2 +- .../aws/memorydb/memorydbClusterEncrypted.spec.js | 2 +- plugins/aws/mq/mqBrokerEncrypted.js | 2 +- plugins/aws/mq/mqBrokerEncrypted.spec.js | 4 ++-- plugins/aws/msk/mskClusterEncryptionAtRest.js | 2 +- plugins/aws/msk/mskClusterEncryptionAtRest.spec.js | 2 +- plugins/aws/mwaa/environmentDataEncrypted.js | 2 +- .../opensearchCollectionCmkEncrypted.js | 2 +- .../opensearch/opensearchDomainEncryptionEnabled.js | 2 +- plugins/aws/proton/environmentTemplateEncrypted.js | 2 +- plugins/aws/qldb/ledgerEncrypted.js | 2 +- plugins/aws/s3/s3Encryption.js | 2 +- plugins/aws/ses/emailMessagesEncrypted.js | 2 +- plugins/aws/sqs/sqsEncryptionEnabled.js | 2 +- .../timestreamwrite/timestreamDatabaseEncrypted.js | 2 +- plugins/aws/translate/translateJobOutputEncrypted.js | 2 +- .../translate/translateJobOutputEncrypted.spec.js | 2 +- 73 files changed, 83 insertions(+), 83 deletions(-) diff --git a/plugins/aws/apprunner/serviceEncrypted.js b/plugins/aws/apprunner/serviceEncrypted.js index 85f913040d..c90dfc0adb 100644 --- a/plugins/aws/apprunner/serviceEncrypted.js +++ b/plugins/aws/apprunner/serviceEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: ' App Runner service desired Encryption level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['apprunner:CreateService','apprunner:DeleteService'], diff --git a/plugins/aws/auditmanager/auditmanagerDataEncrypted.js b/plugins/aws/auditmanager/auditmanagerDataEncrypted.js index 67038211d3..ef9652f57a 100644 --- a/plugins/aws/auditmanager/auditmanagerDataEncrypted.js +++ b/plugins/aws/auditmanager/auditmanagerDataEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Audit Manager Data Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk', + default: 'awskms', } }, realtime_triggers: ['auditmanager:registerAccount','auditmanager:UpdateSettings','auditmanager:DeregisterAccount'], diff --git a/plugins/aws/auditmanager/auditmanagerDataEncrypted.spec.js b/plugins/aws/auditmanager/auditmanagerDataEncrypted.spec.js index bef446ac37..f25b3b70fc 100644 --- a/plugins/aws/auditmanager/auditmanagerDataEncrypted.spec.js +++ b/plugins/aws/auditmanager/auditmanagerDataEncrypted.spec.js @@ -98,7 +98,7 @@ describe('auditmanagerDataEncrypted', function () { it('should FAIL if Audit Manager data is not encrypted with desired encryption level', function (done) { const cache = createCache(getSettings, listKeys, describeKey[1]); - auditmanagerDataEncrypted.run(cache, {}, (err, results) => { + auditmanagerDataEncrypted.run(cache, {auditmanager_data_encryption_level: 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].region).to.equal('us-east-1'); diff --git a/plugins/aws/backup/backupVaultEncrypted.js b/plugins/aws/backup/backupVaultEncrypted.js index b5b9e6c718..a8c69131ac 100644 --- a/plugins/aws/backup/backupVaultEncrypted.js +++ b/plugins/aws/backup/backupVaultEncrypted.js @@ -16,7 +16,7 @@ module.exports = { name: 'CodeArtifact Domain Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk', + default: 'awskms', } }, realtime_triggers: ['backup:CreateBackupVault','backup:DeleteBackupVault'], diff --git a/plugins/aws/cloudwatchlogs/logGroupsEncrypted.js b/plugins/aws/cloudwatchlogs/logGroupsEncrypted.js index d7341202f9..e280a45c48 100644 --- a/plugins/aws/cloudwatchlogs/logGroupsEncrypted.js +++ b/plugins/aws/cloudwatchlogs/logGroupsEncrypted.js @@ -18,7 +18,7 @@ module.exports = { name: 'CloudWatch Log Groups Target Ecryption Level', description: 'In order (lowest to highest) awskms=AWS managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' }, cloudwatchlog_whitelist: { name: 'Lambda Functions Whitelisted', diff --git a/plugins/aws/codeartifact/codeartifactDomainEncrypted.js b/plugins/aws/codeartifact/codeartifactDomainEncrypted.js index c3def0ee5c..80186bb0b5 100644 --- a/plugins/aws/codeartifact/codeartifactDomainEncrypted.js +++ b/plugins/aws/codeartifact/codeartifactDomainEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'CodeArtifact Domain Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk', + default: 'awskms', } }, realtime_triggers: ['codeartifact:CreateDomain', 'codeartifact:DeleteDomain'], diff --git a/plugins/aws/codeartifact/codeartifactDomainEncrypted.spec.js b/plugins/aws/codeartifact/codeartifactDomainEncrypted.spec.js index b6d8bcda5f..5efe70c791 100644 --- a/plugins/aws/codeartifact/codeartifactDomainEncrypted.spec.js +++ b/plugins/aws/codeartifact/codeartifactDomainEncrypted.spec.js @@ -101,7 +101,7 @@ describe('codeartifactDomainEncrypted', function () { it('should FAIL if CodeArtifact domain is not encrypted with desired encyption level', function (done) { const cache = createCache(listDomains, listKeys, describeKey[1]); - codeartifactDomainEncrypted.run(cache, {}, (err, results) => { + codeartifactDomainEncrypted.run(cache, {codeartifact_domain_encryption_level:'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].region).to.equal('us-east-1'); diff --git a/plugins/aws/codebuild/projectArtifactsEncrypted.js b/plugins/aws/codebuild/projectArtifactsEncrypted.js index 1316415b51..7cc111417d 100644 --- a/plugins/aws/codebuild/projectArtifactsEncrypted.js +++ b/plugins/aws/codebuild/projectArtifactsEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Project Artifacts Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk', + default: 'awskms', } }, realtime_triggers: ['codebuild:CreateProject', 'codebuild:UpdateProject','codebuild:DeleteProject'], diff --git a/plugins/aws/codebuild/projectArtifactsEncrypted.spec.js b/plugins/aws/codebuild/projectArtifactsEncrypted.spec.js index b9e0618f8e..080bfa3271 100644 --- a/plugins/aws/codebuild/projectArtifactsEncrypted.spec.js +++ b/plugins/aws/codebuild/projectArtifactsEncrypted.spec.js @@ -158,7 +158,7 @@ describe('projectArtifactsEncrypted', function () { it('should FAIL if CodeBuild project artifact is not encrypted with desired encryption level', function (done) { const cache = createCache(listProjects, listKeys, batchGetProjects[1], describeKey[1]); - projectArtifactsEncrypted.run(cache, { projects_artifact_desired_encryption_level: 'awscmk' }, (err, results) => { + projectArtifactsEncrypted.run(cache, { project_artifacts_desired_encryption_level: 'awscmk' }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].region).to.equal('us-east-1'); diff --git a/plugins/aws/codepipeline/pipelineArtifactsEncrypted.js b/plugins/aws/codepipeline/pipelineArtifactsEncrypted.js index ff8c685a68..c757e6302a 100644 --- a/plugins/aws/codepipeline/pipelineArtifactsEncrypted.js +++ b/plugins/aws/codepipeline/pipelineArtifactsEncrypted.js @@ -18,7 +18,7 @@ module.exports = { name: 'Pipeline Artifacts Desired Encrypted Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['codepipeline:CreatePipeline','codepipeline:DeletePipeline'], diff --git a/plugins/aws/codepipeline/pipelineArtifactsEncrypted.spec.js b/plugins/aws/codepipeline/pipelineArtifactsEncrypted.spec.js index 84b653c7bb..9d4f18ffbc 100644 --- a/plugins/aws/codepipeline/pipelineArtifactsEncrypted.spec.js +++ b/plugins/aws/codepipeline/pipelineArtifactsEncrypted.spec.js @@ -135,7 +135,7 @@ describe('pipelineArtifactsEncrypted', function () { describe('run', function () { it('should PASS if Pipeline Artifacts is encrypted with desired encryption level', function (done) { const cache = createCache([listPipelines[0]], listKeys, listAliases, getPipeline[0], describeKey[0]); - pipelineArtifactsEncrypted.run(cache, { pipeline_artifacts_encryption : 'awscmk' }, (err, results) => { + pipelineArtifactsEncrypted.run(cache, { pipeline_artifacts_desired_encryption_level : 'awscmk' }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); expect(results[0].region).to.equal('us-east-1'); @@ -145,7 +145,7 @@ describe('pipelineArtifactsEncrypted', function () { it('should FAIL if Pipeline Artifacts not encrypted with desired encryption level', function (done) { const cache = createCache([listPipelines[0]], listKeys, listAliases, getPipeline[0], describeKey[1]); - pipelineArtifactsEncrypted.run(cache, { pipeline_artifacts_encryption : 'awscmk' }, (err, results) => { + pipelineArtifactsEncrypted.run(cache, { pipeline_artifacts_desired_encryption_level : 'awscmk' }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].region).to.equal('us-east-1'); diff --git a/plugins/aws/connect/customerProfilesDomainEncrypted.js b/plugins/aws/connect/customerProfilesDomainEncrypted.js index b523e93073..76063936c5 100644 --- a/plugins/aws/connect/customerProfilesDomainEncrypted.js +++ b/plugins/aws/connect/customerProfilesDomainEncrypted.js @@ -16,7 +16,7 @@ module.exports = { name: 'Connect Customer Profiles Encrypted', description: 'In order (lowest to highest) awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['customerprofiles:CreateDomain', 'customerprofiles:UpdateDomain', 'customerprofile:DeleteDomain'], diff --git a/plugins/aws/connect/instanceAttachmentsEncrypted.js b/plugins/aws/connect/instanceAttachmentsEncrypted.js index 22d2c9e264..cc6abdb1fb 100644 --- a/plugins/aws/connect/instanceAttachmentsEncrypted.js +++ b/plugins/aws/connect/instanceAttachmentsEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Connect Attachments Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['connect:CreateInstance', 'connect:AssociateInstanceStorageConfig', 'connect:UpdateInstanceStorageConfig', 'connect:DeleteInstance', 'connect:DisassociateInstanceStorageConfig'], diff --git a/plugins/aws/connect/instanceAttachmentsEncrypted.spec.js b/plugins/aws/connect/instanceAttachmentsEncrypted.spec.js index 6d115ad83a..2f9e9965f3 100644 --- a/plugins/aws/connect/instanceAttachmentsEncrypted.spec.js +++ b/plugins/aws/connect/instanceAttachmentsEncrypted.spec.js @@ -136,7 +136,7 @@ describe('instanceAttachmentsEncrypted', function () { describe('run', function () { it('should FAIL if Connect instance is not using desired encryption level', function (done) { const cache = createCache(listInstances, instanceAttachmentStorageConfigs[0], listKeys, describeKey[1]); - instanceAttachmentsEncrypted.run(cache, {}, (err, results) => { + instanceAttachmentsEncrypted.run(cache, {connect_attachments_encryption_level : 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); done(); diff --git a/plugins/aws/connect/instanceCallRecordingEncrypted.js b/plugins/aws/connect/instanceCallRecordingEncrypted.js index 68987ddf5e..6311f158ab 100644 --- a/plugins/aws/connect/instanceCallRecordingEncrypted.js +++ b/plugins/aws/connect/instanceCallRecordingEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Connect Call Resording Encryption Level', description: 'In order (lowest to highest) awskms=AWS managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['connect:CreateInstance', 'connect:AssociateInstanceStorageConfig', 'connect:UpdateInstanceStorageConfig','connect:DeleteInstance', 'connect:DisassociateInstanceStorageConfig'], diff --git a/plugins/aws/connect/instanceCallRecordingEncrypted.spec.js b/plugins/aws/connect/instanceCallRecordingEncrypted.spec.js index e9a81e213f..bb7b9b0815 100644 --- a/plugins/aws/connect/instanceCallRecordingEncrypted.spec.js +++ b/plugins/aws/connect/instanceCallRecordingEncrypted.spec.js @@ -136,7 +136,7 @@ describe('instanceCallRecordingEncrypted', function () { describe('run', function () { it('should FAIL if Connect instance is not using desired encryption level', function (done) { const cache = createCache(listInstances, listInstanceCallRecordingStorageConfigs[0], listKeys, describeKey[1]); - instanceCallRecordingEncrypted.run(cache, {}, (err, results) => { + instanceCallRecordingEncrypted.run(cache, {connect_call_recording_encryption_level: 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); done(); diff --git a/plugins/aws/connect/instanceMediaStreamsEncrypted.js b/plugins/aws/connect/instanceMediaStreamsEncrypted.js index 434c48a803..2592d97168 100644 --- a/plugins/aws/connect/instanceMediaStreamsEncrypted.js +++ b/plugins/aws/connect/instanceMediaStreamsEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Connect Media Streams Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['connect:CreateInstance', 'connect:AssociateInstanceStorageConfig', 'connect:UpdateInstanceStorageConfig','connect:DeleteInstance', 'connect:DisassociateInstanceStorageConfig'], diff --git a/plugins/aws/connect/instanceMediaStreamsEncrypted.spec.js b/plugins/aws/connect/instanceMediaStreamsEncrypted.spec.js index 36fa52b903..8024d015d0 100644 --- a/plugins/aws/connect/instanceMediaStreamsEncrypted.spec.js +++ b/plugins/aws/connect/instanceMediaStreamsEncrypted.spec.js @@ -142,7 +142,7 @@ describe('instanceMediaStreamsEncrypted', function () { describe('run', function () { it('should FAIL if Connect instance is not using desired encryption level', function (done) { const cache = createCache(listInstances, listInstanceMediaStreamStorageConfigs[0], listKeys, describeKey[1]); - instanceMediaStreamsEncrypted.run(cache, {}, (err, results) => { + instanceMediaStreamsEncrypted.run(cache, {connect_media_streams_encryption_level: 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); done(); diff --git a/plugins/aws/connect/instanceReportsEncrypted.js b/plugins/aws/connect/instanceReportsEncrypted.js index ea4bed1916..d4cc6a1b5e 100644 --- a/plugins/aws/connect/instanceReportsEncrypted.js +++ b/plugins/aws/connect/instanceReportsEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Connect Exported Reports Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['connect:CreateInstance', 'connect:AssociateInstanceStorageConfig', 'connect:UpdateInstanceStorageConfig','connect:DeleteInstance', 'connect:DisassociateInstanceStorageConfig'], diff --git a/plugins/aws/connect/instanceReportsEncrypted.spec.js b/plugins/aws/connect/instanceReportsEncrypted.spec.js index 2fa15b71f1..deb0aab8bb 100644 --- a/plugins/aws/connect/instanceReportsEncrypted.spec.js +++ b/plugins/aws/connect/instanceReportsEncrypted.spec.js @@ -136,7 +136,7 @@ describe('instanceReportsEncrypted', function () { describe('run', function () { it('should FAIL if Connect instance is not using desired encryption level', function (done) { const cache = createCache(listInstances, listInstanceExportedReportStorageConfigs[0], listKeys, describeKey[1]); - instanceReportsEncrypted.run(cache, {}, (err, results) => { + instanceReportsEncrypted.run(cache, {connect_exported_reports_encryption_level : 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); done(); diff --git a/plugins/aws/connect/instanceTranscriptsEncrypted.js b/plugins/aws/connect/instanceTranscriptsEncrypted.js index 8035988918..217ea2a6d8 100644 --- a/plugins/aws/connect/instanceTranscriptsEncrypted.js +++ b/plugins/aws/connect/instanceTranscriptsEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Connect Chat Transcripts Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['connect:CreateInstance', 'connect:AssociateInstanceStorageConfig', 'connect:UpdateInstanceStorageConfig','connect:DeleteInstance', 'connect:DisassociateInstanceStorageConfig'], diff --git a/plugins/aws/connect/instanceTranscriptsEncrypted.spec.js b/plugins/aws/connect/instanceTranscriptsEncrypted.spec.js index e2b7fa991f..83b6ff6e65 100644 --- a/plugins/aws/connect/instanceTranscriptsEncrypted.spec.js +++ b/plugins/aws/connect/instanceTranscriptsEncrypted.spec.js @@ -136,7 +136,7 @@ describe('instanceTranscriptsEncrypted', function () { describe('run', function () { it('should FAIL if Connect instance is not using desired encryption level', function (done) { const cache = createCache(listInstances, listInstanceChatTranscriptStorageConfigs[0], listKeys, describeKey[1]); - instanceTranscriptsEncrypted.run(cache, {}, (err, results) => { + instanceTranscriptsEncrypted.run(cache, {connect_chat_transcripts_encryption_level: 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); done(); diff --git a/plugins/aws/documentDB/docdbClusterEncrypted.js b/plugins/aws/documentDB/docdbClusterEncrypted.js index 4ff795f685..6eff45ad78 100644 --- a/plugins/aws/documentDB/docdbClusterEncrypted.js +++ b/plugins/aws/documentDB/docdbClusterEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'DocumentDB Cluster Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk', + default: 'awskms', } }, realtime_triggers: ['docdb:CreateDBCluster','docdb:CreateDBInstance','docdb:DeleteDBCluster'], diff --git a/plugins/aws/ec2/ebsEncryptionEnabled.js b/plugins/aws/ec2/ebsEncryptionEnabled.js index c6144cd468..877c86d80b 100644 --- a/plugins/aws/ec2/ebsEncryptionEnabled.js +++ b/plugins/aws/ec2/ebsEncryptionEnabled.js @@ -55,7 +55,7 @@ module.exports = { name: 'EBS Minimum Encryption Level at rest', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk', + default: 'awskms', }, }, diff --git a/plugins/aws/ecr/ecrRepositoryEncrypted.js b/plugins/aws/ecr/ecrRepositoryEncrypted.js index a416b14761..fffc5ccd1d 100644 --- a/plugins/aws/ecr/ecrRepositoryEncrypted.js +++ b/plugins/aws/ecr/ecrRepositoryEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'ECR Repository Encryption', description: 'In order (lowest to highest) sse=AES-256; awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(sse|awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['ecr:CreateRepository', 'ecr:DeleteRepository'], diff --git a/plugins/aws/eks/eksKubernetesVersion.spec.js b/plugins/aws/eks/eksKubernetesVersion.spec.js index b53206f8d2..0997f85358 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.27", + "version": "1.29", } } ); diff --git a/plugins/aws/elasticache/redisClusterEncryptionAtRest.js b/plugins/aws/elasticache/redisClusterEncryptionAtRest.js index 01b033ca38..966ddd086e 100644 --- a/plugins/aws/elasticache/redisClusterEncryptionAtRest.js +++ b/plugins/aws/elasticache/redisClusterEncryptionAtRest.js @@ -17,7 +17,7 @@ module.exports = { name: 'ElastiCache Cluster Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk', + default: 'awskms', } }, realtime_triggers: ['elasticache:CreateCacheCluster', 'elasticache:DeleteCacheCluster', 'elasticache:CreateReplicationGroup'], diff --git a/plugins/aws/elasticache/redisClusterEncryptionAtRest.spec.js b/plugins/aws/elasticache/redisClusterEncryptionAtRest.spec.js index e2d9b5052c..92b16c3717 100644 --- a/plugins/aws/elasticache/redisClusterEncryptionAtRest.spec.js +++ b/plugins/aws/elasticache/redisClusterEncryptionAtRest.spec.js @@ -219,7 +219,7 @@ describe('redisClusterEncryptionAtRest', function () { describe('run', function () { it('should PASS if Redis Cluster at-rest is encrypted with desired encryption level', function (done) { const cache = createCache(describeCacheClusters[0], listKeys, describeReplicationGroups[0], describeKey[0]); - redisClusterEncryptionAtRest.run(cache, { ec_atrest_desired_encryption_level: 'awscmk' }, (err, results) => { + redisClusterEncryptionAtRest.run(cache, { ec_cluster_target_encryption_level: 'awscmk' }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); expect(results[0].region).to.equal('us-east-1'); @@ -229,7 +229,7 @@ describe('redisClusterEncryptionAtRest', function () { it('should FAIL if Redis Cluster at-rest is not encrypted with desired encryption level', function (done) { const cache = createCache([describeCacheClusters[1]],listKeys, describeReplicationGroups[1], describeKey[1]); - redisClusterEncryptionAtRest.run(cache, { ec_atrest_desired_encryption_level: 'awscmk' }, (err, results) => { + redisClusterEncryptionAtRest.run(cache, { ec_cluster_target_encryption_level: 'awscmk' }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].region).to.equal('us-east-1'); diff --git a/plugins/aws/firehose/deliveryStreamEncrypted.js b/plugins/aws/firehose/deliveryStreamEncrypted.js index 8f544a7b19..c7579cebe4 100644 --- a/plugins/aws/firehose/deliveryStreamEncrypted.js +++ b/plugins/aws/firehose/deliveryStreamEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Firehose Delivery Stream Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['firehose:CreateDeliveryStreams','firehose:UpdateDestination', 'firehose:DeleteliveryStreams'], diff --git a/plugins/aws/firehose/deliveryStreamEncrypted.spec.js b/plugins/aws/firehose/deliveryStreamEncrypted.spec.js index 5d7c45b1fe..39ccf0b75f 100644 --- a/plugins/aws/firehose/deliveryStreamEncrypted.spec.js +++ b/plugins/aws/firehose/deliveryStreamEncrypted.spec.js @@ -308,7 +308,7 @@ describe('deliveryStreamEncrypted', function () { deliveryStreamEncrypted.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('Firehose delivery stream destination bucket is encrypted with awscmk'); + expect(results[0].message).to.include('Firehose delivery stream is encrypted with awskms'); expect(results[0].region).to.equal('us-east-1'); done(); }); @@ -316,7 +316,7 @@ describe('deliveryStreamEncrypted', function () { it('should FAIL if Firehose Delivery Stream not encrypted with desired encryption level', function (done) { const cache = createCache([listDeliveryStreams[0]], listKeys, describeDeliveryStream[1], describeKey[1]); - deliveryStreamEncrypted.run(cache, {}, (err, results) => { + deliveryStreamEncrypted.run(cache, {delivery_stream_desired_encryption_level: 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].message).to.include('Firehose delivery stream destination bucket is encrypted with awskms'); diff --git a/plugins/aws/frauddetector/fraudDetectorDataEncrypted.js b/plugins/aws/frauddetector/fraudDetectorDataEncrypted.js index 0b96918845..803225679c 100644 --- a/plugins/aws/frauddetector/fraudDetectorDataEncrypted.js +++ b/plugins/aws/frauddetector/fraudDetectorDataEncrypted.js @@ -16,7 +16,7 @@ module.exports = { name: 'Fraud Detector Data Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['frauddetector:PutKMSEncryptionKey', 'frauddetector:DeleteDetector'], diff --git a/plugins/aws/fsx/fsxFileSystemEncrypted.js b/plugins/aws/fsx/fsxFileSystemEncrypted.js index fbb7b8e65d..418c3b7d40 100644 --- a/plugins/aws/fsx/fsxFileSystemEncrypted.js +++ b/plugins/aws/fsx/fsxFileSystemEncrypted.js @@ -16,7 +16,7 @@ module.exports = { name: 'FSx File Systems Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['fsx:CreateFileSystem', 'fsx:DeleteFileSystem'], diff --git a/plugins/aws/glue/glueS3EncryptionEnabled.js b/plugins/aws/glue/glueS3EncryptionEnabled.js index 72e1602f99..fc0c091426 100644 --- a/plugins/aws/glue/glueS3EncryptionEnabled.js +++ b/plugins/aws/glue/glueS3EncryptionEnabled.js @@ -16,7 +16,7 @@ module.exports = { name: 'Glue S3 Encryption Level', description: 'In order (lowest to highest) sse=S3 Server-Side; awskms=AWS-managed KMS; awscmk=Customer managed KMS;', regex: '^(sse|awskms|awscmk)$', - default: 'awscmk', + default: 'awskms', } }, realtime_triggers: ['glue:CreateSecurityConfiguration','glue:DeleteSecurityConfiguration'], diff --git a/plugins/aws/guardduty/exportedFindingsEncrypted.js b/plugins/aws/guardduty/exportedFindingsEncrypted.js index 348da066e6..370bf4ff60 100644 --- a/plugins/aws/guardduty/exportedFindingsEncrypted.js +++ b/plugins/aws/guardduty/exportedFindingsEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'GuardDuty Findings Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['guardduty:CreateDetector', 'guardduty:DeleteDetector'], diff --git a/plugins/aws/guardduty/exportedFindingsEncrypted.spec.js b/plugins/aws/guardduty/exportedFindingsEncrypted.spec.js index a43bcac0a1..3f56095442 100644 --- a/plugins/aws/guardduty/exportedFindingsEncrypted.spec.js +++ b/plugins/aws/guardduty/exportedFindingsEncrypted.spec.js @@ -147,7 +147,7 @@ describe('exportedFindingsEncrypted', function () { it('should PASS if GuardDuty Export Findings is encrypted with desired level', function (done) { const cache = createCache([listDetectors[0]], [listPublishingDestinations[0]], describePublishingDestination[0], listKeys, describeKey[0]); - exportedFindingsEncrypted.run(cache, { exported_findings_desired_encryption_level: 'awscmk' }, (err, results) => { + exportedFindingsEncrypted.run(cache, { findings_desired_encryption_level: 'awscmk' }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); expect(results[0].region).to.equal('us-east-1'); @@ -157,7 +157,7 @@ describe('exportedFindingsEncrypted', function () { it('should FAIL if GuardDuty Export Findings is not encrypted with desired level ', function (done) { const cache = createCache([listDetectors[0]], [listPublishingDestinations[0]], describePublishingDestination[1], listKeys, describeKey[1]); - exportedFindingsEncrypted.run(cache, { exported_findings_desired_encryption_level: 'externalcmk' }, (err, results) => { + exportedFindingsEncrypted.run(cache, {findings_desired_encryption_level: 'cloudhsm' }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].region).to.equal('us-east-1'); @@ -167,7 +167,7 @@ describe('exportedFindingsEncrypted', function () { it('should PASS if on GuardDuty detectors found', function (done) { const cache = createCache([]); - exportedFindingsEncrypted.run(cache, { exported_findings_desired_encryption_level: 'awscmk' }, (err, results) => { + exportedFindingsEncrypted.run(cache, { findings_desired_encryption_level: 'awscmk' }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -176,7 +176,7 @@ describe('exportedFindingsEncrypted', function () { it('should UNKNOWN if unable to list GuardDuty detectors', function (done) { const cache = createCache(null, null, null, null, null, { message: 'Unable to list GuardDuty detectors'}); - exportedFindingsEncrypted.run(cache, { exported_findings_desired_encryption_level: 'awscmk' }, (err, results) => { + exportedFindingsEncrypted.run(cache, { findings_desired_encryption_level: 'awscmk' }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(3); done(); @@ -185,7 +185,7 @@ describe('exportedFindingsEncrypted', function () { it('should UNKNOWN if unable to list GuardDuty publishing destinations', function (done) { const cache = createCache([listDetectors[0]], {}, describePublishingDestination[0], null, null, null, null, { message: 'Unable to query GuardDuty publishing destinations'}); - exportedFindingsEncrypted.run(cache, { exported_findings_desired_encryption_level: 'awscmk' }, (err, results) => { + exportedFindingsEncrypted.run(cache, { findings_desired_encryption_level: 'awscmk' }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(3); done(); @@ -194,7 +194,7 @@ describe('exportedFindingsEncrypted', function () { it('should not return anything if list detectors response not found', function (done) { const cache = createNullCache(); - exportedFindingsEncrypted.run(cache, { exported_findings_desired_encryption_level: 'awscmk' }, (err, results) => { + exportedFindingsEncrypted.run(cache, { findings_desired_encryption_level: 'awscmk' }, (err, results) => { expect(results.length).to.equal(0); done(); }); diff --git a/plugins/aws/healthlake/dataStoreEncrypted.js b/plugins/aws/healthlake/dataStoreEncrypted.js index edab34abd1..c543c87851 100644 --- a/plugins/aws/healthlake/dataStoreEncrypted.js +++ b/plugins/aws/healthlake/dataStoreEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'HealthLake Data Store Desired Encryption Level', description: 'In order (lowest to highest) awskms=AWS managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['healthlake:CreateFHIRDatastore', 'healthlake:DeleteFHIRDatastore'], diff --git a/plugins/aws/healthlake/dataStoreEncrypted.spec.js b/plugins/aws/healthlake/dataStoreEncrypted.spec.js index fa022a78f4..c7beb1d3b9 100644 --- a/plugins/aws/healthlake/dataStoreEncrypted.spec.js +++ b/plugins/aws/healthlake/dataStoreEncrypted.spec.js @@ -102,7 +102,7 @@ describe('dataStoreEncrypted', function () { describe('run', function () { it('should PASS if HealthLake Data Store is encrypted with desired encryption level', function (done) { const cache = createCache(listFHIRDatastores, listKeys, describeKey[0]); - dataStoreEncrypted.run(cache, { healthLake_data_store_encryption: 'awscmk' }, (err, results) => { + dataStoreEncrypted.run(cache, { healthlake_datastore_desired_encryption_level: 'awscmk' }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); expect(results[0].message).to.include('HealthLake data store is encrypted with awscmk'); @@ -113,7 +113,7 @@ describe('dataStoreEncrypted', function () { it('should FAIL if HealthLake Data Store is not encrypted with desired encyption level', function (done) { const cache = createCache(listFHIRDatastores, listKeys, describeKey[1]); - dataStoreEncrypted.run(cache, { healthLake_data_store_encryption:'awscmk' }, (err, results) => { + dataStoreEncrypted.run(cache, { healthlake_datastore_desired_encryption_level:'awscmk' }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].message).to.include('HealthLake data store is encrypted with awskms'); diff --git a/plugins/aws/imagebuilder/dockerfileTemplateEncrypted.js b/plugins/aws/imagebuilder/dockerfileTemplateEncrypted.js index 23f761758a..fae28c29e4 100644 --- a/plugins/aws/imagebuilder/dockerfileTemplateEncrypted.js +++ b/plugins/aws/imagebuilder/dockerfileTemplateEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Docker File Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['imagebuilder:CreateContainerRecipe','imagebuilder:DeleteContainerRecipe'], diff --git a/plugins/aws/imagebuilder/dockerfileTemplateEncrypted.spec.js b/plugins/aws/imagebuilder/dockerfileTemplateEncrypted.spec.js index 91b54b093a..baa7bbafae 100644 --- a/plugins/aws/imagebuilder/dockerfileTemplateEncrypted.spec.js +++ b/plugins/aws/imagebuilder/dockerfileTemplateEncrypted.spec.js @@ -196,7 +196,7 @@ describe('dockerfileTemplateEncrypted', function () { it('should FAIL if Dockerfile Template is encrypted with awskms', function (done) { const cache = createCache([listContainerRecipes[1]], listKeys, listAliases, getContainerRecipe[1], describeKey[1]); - dockerfileTemplateEncrypted.run(cache, {}, (err, results) => { + dockerfileTemplateEncrypted.run(cache, {docker_file_desired_encryption_level: 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].message).to.include('Dockerfile Template is encrypted with'); diff --git a/plugins/aws/imagebuilder/imageRecipeVolumeEncrypted.js b/plugins/aws/imagebuilder/imageRecipeVolumeEncrypted.js index 9d2d4d5b25..6f93d806ad 100644 --- a/plugins/aws/imagebuilder/imageRecipeVolumeEncrypted.js +++ b/plugins/aws/imagebuilder/imageRecipeVolumeEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Image Recipe EBS Volumes Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['Imagebuilder:CreateImageRecipe','Imagebuilder:DeleteImageRecipe'], diff --git a/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js index 36f33356b5..53458a6b2d 100644 --- a/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js +++ b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Image Builder Component Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['Imagebuilder:CreateComponent','Imagebuilder:DeleteComponent'], diff --git a/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.spec.js b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.spec.js index d2219c817d..6eeb0bba47 100644 --- a/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.spec.js +++ b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.spec.js @@ -180,7 +180,7 @@ describe('imgBuilderComponentsEncrypted', function () { it('should FAIL if Image Builder component is encrypted with awskms', function (done) { const cache = createCache([listComponents[1]], listKeys, listAliases, getComponent[1], describeKey[1]); - imgBuilderComponentsEncrypted.run(cache, {}, (err, results) => { + imgBuilderComponentsEncrypted.run(cache, {image_component_desired_encryption_level: 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].message).to.include('Image Builder component is encrypted with'); diff --git a/plugins/aws/iotsitewise/iotsitewiseDataEncrypted.js b/plugins/aws/iotsitewise/iotsitewiseDataEncrypted.js index 53cdc7de4c..8b39d18681 100644 --- a/plugins/aws/iotsitewise/iotsitewiseDataEncrypted.js +++ b/plugins/aws/iotsitewise/iotsitewiseDataEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'IoT SiteWise Data Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk', + default: 'awskms', } }, realtime_triggers: ['imagebuilder:PutDefaultEncryptionConfiguration'], diff --git a/plugins/aws/kendra/kendraIndexEncrypted.js b/plugins/aws/kendra/kendraIndexEncrypted.js index bc8d9854a5..8494393f3a 100644 --- a/plugins/aws/kendra/kendraIndexEncrypted.js +++ b/plugins/aws/kendra/kendraIndexEncrypted.js @@ -16,7 +16,7 @@ module.exports = { name: 'Kendra Index Encrypted', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['kendra:CreateIndex','kendra:UpdateIndex','kendra:DeleteIndex'], diff --git a/plugins/aws/kinesis/kinesisDataStreamsEncrypted.js b/plugins/aws/kinesis/kinesisDataStreamsEncrypted.js index 4694709351..8aa16ea2a6 100644 --- a/plugins/aws/kinesis/kinesisDataStreamsEncrypted.js +++ b/plugins/aws/kinesis/kinesisDataStreamsEncrypted.js @@ -18,7 +18,7 @@ module.exports = { name: 'Kinesis Data Stream Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['kinesis:CreateStream','kinesis:StartStreamEncryption','kinesis:StopStreamEncryption','kinesis:DeleteStream'], diff --git a/plugins/aws/kinesis/kinesisDataStreamsEncrypted.spec.js b/plugins/aws/kinesis/kinesisDataStreamsEncrypted.spec.js index 8ffb787aa1..12edd5e58c 100644 --- a/plugins/aws/kinesis/kinesisDataStreamsEncrypted.spec.js +++ b/plugins/aws/kinesis/kinesisDataStreamsEncrypted.spec.js @@ -218,7 +218,7 @@ describe('kinesisDataStreamsEncrypted', function () { it('should FAIL if Kinesis stream not encrypted with desired encryption level', function (done) { const cache = createCache([listStreams[1]], listKeys, [listAliases[1]], describeStream[1], describeKey[1]); - kinesisDataStreamsEncrypted.run(cache, {}, (err, results) => { + kinesisDataStreamsEncrypted.run(cache, {data_streams_desired_encryption_level: 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].message).to.include('Kinesis stream is encrypted with awskms'); diff --git a/plugins/aws/kinesisvideo/videostreamDataEncrypted.js b/plugins/aws/kinesisvideo/videostreamDataEncrypted.js index f181178871..a1146e4225 100644 --- a/plugins/aws/kinesisvideo/videostreamDataEncrypted.js +++ b/plugins/aws/kinesisvideo/videostreamDataEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Kinesis Video Streams Data Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['kinesisvideo:CreateStream', 'kinesisvideo:DeleteStream'], diff --git a/plugins/aws/location/geoCollectionDataEncrypted.js b/plugins/aws/location/geoCollectionDataEncrypted.js index db8755acbf..4eb4c8a68e 100644 --- a/plugins/aws/location/geoCollectionDataEncrypted.js +++ b/plugins/aws/location/geoCollectionDataEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Location Geofence Collection Data Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['location:CreateGeofenceCollection', 'location:DeleteGeofenceCollection'], diff --git a/plugins/aws/location/trackerDataEncrypted.js b/plugins/aws/location/trackerDataEncrypted.js index 8a35338ffb..dfd529aebd 100644 --- a/plugins/aws/location/trackerDataEncrypted.js +++ b/plugins/aws/location/trackerDataEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Location Tracker Data Desired Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['location:CreateTracker', 'location:UpdateTracker', 'location:DeleteTracker'], diff --git a/plugins/aws/lookout/anomalyDetectorEncrypted.js b/plugins/aws/lookout/anomalyDetectorEncrypted.js index ca7d8f70f7..054a2fdfe0 100644 --- a/plugins/aws/lookout/anomalyDetectorEncrypted.js +++ b/plugins/aws/lookout/anomalyDetectorEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'LookoutMetrics Anomaly Detector Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['lookoutmetrics:CreateAnomalyDetector', 'lookoutmetrics:UpdateAnomalyDetector', 'lookoutmetrics:DeleteAnomalyDetector'], diff --git a/plugins/aws/lookout/anomalyDetectorEncrypted.spec.js b/plugins/aws/lookout/anomalyDetectorEncrypted.spec.js index 5e23fba913..c928fe8438 100644 --- a/plugins/aws/lookout/anomalyDetectorEncrypted.spec.js +++ b/plugins/aws/lookout/anomalyDetectorEncrypted.spec.js @@ -143,7 +143,7 @@ describe('anomalyDetectorEncrypted', function () { it('should FAIL if LookoutMetrics Anomaly Detector is not encrypted with desired encryption level', function (done) { const cache = createCache([listAnomalyDetectors[1]], listKeys, describeAnomalyDetector[1], describeKey[1]); - anomalyDetectorEncrypted.run(cache, {}, (err, results) => { + anomalyDetectorEncrypted.run(cache, {lookoutmetrics_anomalydetectors_desired_encryption_level: 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].region).to.equal('us-east-1'); diff --git a/plugins/aws/lookout/equipmentdatasetEncrypted.js b/plugins/aws/lookout/equipmentdatasetEncrypted.js index 6125b8cee3..ba873bed3f 100644 --- a/plugins/aws/lookout/equipmentdatasetEncrypted.js +++ b/plugins/aws/lookout/equipmentdatasetEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Equipement Dataset Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['lookoutequipment:CreateDataset', 'lookoutequipment:DeleteDataset'], diff --git a/plugins/aws/lookout/equipmentdatasetEncrypted.spec.js b/plugins/aws/lookout/equipmentdatasetEncrypted.spec.js index 639a7fdd86..0c4f402180 100644 --- a/plugins/aws/lookout/equipmentdatasetEncrypted.spec.js +++ b/plugins/aws/lookout/equipmentdatasetEncrypted.spec.js @@ -135,7 +135,7 @@ describe('equipmentdatasetEncrypted', function () { it('should FAIL if LookoutEquipment Dataset is not encrypted with desired encryption level', function (done) { const cache = createCache([listDatasets[1]], listKeys, describeDataset[1], describeKey[1]); - equipmentdatasetEncrypted.run(cache, {}, (err, results) => { + equipmentdatasetEncrypted.run(cache, {equipment_dataset_desired_encryption_level: 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].region).to.equal('us-east-1'); diff --git a/plugins/aws/lookout/modelDataEncrypted.js b/plugins/aws/lookout/modelDataEncrypted.js index 7f93f1b8a4..d956d2f8e5 100644 --- a/plugins/aws/lookout/modelDataEncrypted.js +++ b/plugins/aws/lookout/modelDataEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Vision Data Target Encryption Level', description: 'In order (lowest to highest) sse=S3-SSE; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(sse|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['lookoutvision:CreateModel', 'lookoutvision:DeleteModel'], diff --git a/plugins/aws/managedblockchain/networkMemberDataEncrypted.js b/plugins/aws/managedblockchain/networkMemberDataEncrypted.js index 7fbda0255b..56948232e9 100644 --- a/plugins/aws/managedblockchain/networkMemberDataEncrypted.js +++ b/plugins/aws/managedblockchain/networkMemberDataEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Managed Blockchain Member Target Encryption Level', description: 'In order (lowest to highest) sse=S3-SSE; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk', + default: 'awskms', } }, realtime_triggers: ['managedblockchain:CreateNetwork', 'managedblockchain:DeleteMember'], diff --git a/plugins/aws/managedblockchain/networkMemberDataEncrypted.spec.js b/plugins/aws/managedblockchain/networkMemberDataEncrypted.spec.js index 0d7a26a208..6a6b3898e4 100644 --- a/plugins/aws/managedblockchain/networkMemberDataEncrypted.spec.js +++ b/plugins/aws/managedblockchain/networkMemberDataEncrypted.spec.js @@ -172,7 +172,7 @@ describe('networkMemberDataEncrypted', function () { it('should FAIL if Network member is not using desired encryption level', function (done) { const cache = createCache(listNetworks ,listMembers, getMember[1], listKeys, describeKey[0]); - networkMemberDataEncrypted.run(cache, {}, (err, results) => { + networkMemberDataEncrypted.run(cache, {blockchain_member_encryption_level: 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].region).to.equal('us-east-1'); diff --git a/plugins/aws/memorydb/memorydbClusterEncrypted.js b/plugins/aws/memorydb/memorydbClusterEncrypted.js index a2dcd6527b..e242a05642 100644 --- a/plugins/aws/memorydb/memorydbClusterEncrypted.js +++ b/plugins/aws/memorydb/memorydbClusterEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'MemoryDB Cluster Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk', + default: 'awskms', } }, realtime_triggers: ['MemoryDB:CreateCluster', 'MemoryDB:DeleteCluster'], diff --git a/plugins/aws/memorydb/memorydbClusterEncrypted.spec.js b/plugins/aws/memorydb/memorydbClusterEncrypted.spec.js index e337d2a4e1..5018652060 100644 --- a/plugins/aws/memorydb/memorydbClusterEncrypted.spec.js +++ b/plugins/aws/memorydb/memorydbClusterEncrypted.spec.js @@ -152,7 +152,7 @@ describe('memorydbClusterEncrypted', function () { it('should FAIL if MemoryDB Cluster for Redis is not encrypted with desired encyption level', function (done) { const cache = createCache([describeClusters[0]], listKeys, describeKey[1]); - memorydbClusterEncrypted.run(cache, {} , (err, results) => { + memorydbClusterEncrypted.run(cache, {memorydb_cluster_target_encryption_level: 'awscmk'} , (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].message).to.include('MemoryDB cluster is encrypted with awskms'); diff --git a/plugins/aws/mq/mqBrokerEncrypted.js b/plugins/aws/mq/mqBrokerEncrypted.js index 19b67ac4b8..2e311a443f 100644 --- a/plugins/aws/mq/mqBrokerEncrypted.js +++ b/plugins/aws/mq/mqBrokerEncrypted.js @@ -16,7 +16,7 @@ module.exports = { name: 'MQ Broker Target Encryption Level', description: 'In order (lowest to highest) sse=AWS-owned CMK awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(sse|awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['mq:CreateBrocker', 'mq:DeleteBrocker'], diff --git a/plugins/aws/mq/mqBrokerEncrypted.spec.js b/plugins/aws/mq/mqBrokerEncrypted.spec.js index a02f62e490..7cdf537c8f 100644 --- a/plugins/aws/mq/mqBrokerEncrypted.spec.js +++ b/plugins/aws/mq/mqBrokerEncrypted.spec.js @@ -222,7 +222,7 @@ describe('mqBrokerEncrypted', function () { it('should FAIL if MQ Broker data at-rest is not encrypted with desired encryption level', function (done) { const cache = createCache([listBrokers[1]],listKeys, [describeBroker[0]], describeKey[1]); - mqBrokerEncrypted.run(cache, {}, (err, results) => { + mqBrokerEncrypted.run(cache, {mq_broker_desired_encryption_level: 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].region).to.equal('us-east-1'); @@ -232,7 +232,7 @@ describe('mqBrokerEncrypted', function () { it('should FAIL if MQ Broker data at-rest is encrypted with AWS owned key', function (done) { const cache = createCache([listBrokers[2]],listKeys, [describeBroker[2]], describeKey[1]); - mqBrokerEncrypted.run(cache, {}, (err, results) => { + mqBrokerEncrypted.run(cache, {mq_broker_desired_encryption_level: 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].region).to.equal('us-east-1'); diff --git a/plugins/aws/msk/mskClusterEncryptionAtRest.js b/plugins/aws/msk/mskClusterEncryptionAtRest.js index 937bd501f5..847fa63fee 100644 --- a/plugins/aws/msk/mskClusterEncryptionAtRest.js +++ b/plugins/aws/msk/mskClusterEncryptionAtRest.js @@ -16,7 +16,7 @@ module.exports = { name: 'MSK Cluster Desired Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk', + default: 'awskms', } }, realtime_triggers: ['kafka:CreateCluster', 'kafka:DeleteCluster'], diff --git a/plugins/aws/msk/mskClusterEncryptionAtRest.spec.js b/plugins/aws/msk/mskClusterEncryptionAtRest.spec.js index d59ef80031..11dc783d18 100644 --- a/plugins/aws/msk/mskClusterEncryptionAtRest.spec.js +++ b/plugins/aws/msk/mskClusterEncryptionAtRest.spec.js @@ -150,7 +150,7 @@ describe('mskClusterEncryptionAtRest', function () { it('should FAIL if MSK Cluster At-Rest is not encrypted with desired encyption level', function (done) { const cache = createCache(listClusters, listKeys, describeKey[1]); - mskClusterEncryptionAtRest.run(cache, {}, (err, results) => { + mskClusterEncryptionAtRest.run(cache, {msk_cluster_desired_encryption_level: 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].message).to.include('MSK cluster is encrypted with awskms'); diff --git a/plugins/aws/mwaa/environmentDataEncrypted.js b/plugins/aws/mwaa/environmentDataEncrypted.js index c8c7ac3082..e1ddaadf6d 100644 --- a/plugins/aws/mwaa/environmentDataEncrypted.js +++ b/plugins/aws/mwaa/environmentDataEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'MWAA Environment Data Deisred Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['mwaa:CreateEnvironment', 'mwaa:DeleteEnvironment'], diff --git a/plugins/aws/openSearchServerless/opensearchCollectionCmkEncrypted.js b/plugins/aws/openSearchServerless/opensearchCollectionCmkEncrypted.js index 5e795789af..94287c22cd 100644 --- a/plugins/aws/openSearchServerless/opensearchCollectionCmkEncrypted.js +++ b/plugins/aws/openSearchServerless/opensearchCollectionCmkEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'OpenSearch Collection Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['opensearchserverless:CreateCollection', 'opensearchserverless:DeleteCollection'], diff --git a/plugins/aws/opensearch/opensearchDomainEncryptionEnabled.js b/plugins/aws/opensearch/opensearchDomainEncryptionEnabled.js index bebeb61710..05821f3284 100644 --- a/plugins/aws/opensearch/opensearchDomainEncryptionEnabled.js +++ b/plugins/aws/opensearch/opensearchDomainEncryptionEnabled.js @@ -16,7 +16,7 @@ module.exports = { name: 'OpenSearch Domain Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk', + default: 'awskms', } }, realtime_triggers: ['opensearch:CreateDomain', 'opensearch:UpdateDomainConfig', 'opensearch:DeleteDomain'], diff --git a/plugins/aws/proton/environmentTemplateEncrypted.js b/plugins/aws/proton/environmentTemplateEncrypted.js index 0cf5634df5..b1f9cadf41 100644 --- a/plugins/aws/proton/environmentTemplateEncrypted.js +++ b/plugins/aws/proton/environmentTemplateEncrypted.js @@ -16,7 +16,7 @@ module.exports = { name: 'Environment Template Desired Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['proton:CreateEnviromentTemplate', 'proton:DeleteEnviromentTemplate'], diff --git a/plugins/aws/qldb/ledgerEncrypted.js b/plugins/aws/qldb/ledgerEncrypted.js index 230c4fa5fd..59e1760706 100644 --- a/plugins/aws/qldb/ledgerEncrypted.js +++ b/plugins/aws/qldb/ledgerEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'QLDB ledger desired encryption level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['qldb:CreateLedger', 'qldb:UpdateLedger', 'qldb:DeleteLedger'], diff --git a/plugins/aws/s3/s3Encryption.js b/plugins/aws/s3/s3Encryption.js index f693811562..6289677708 100644 --- a/plugins/aws/s3/s3Encryption.js +++ b/plugins/aws/s3/s3Encryption.js @@ -62,7 +62,7 @@ module.exports = { name: 'S3 Minimum Default Encryption Level', description: 'In order (low to high) sse=Server-Side Encryption; awskms=AWS KMS; awscmk=Customer KMS; externalcmk=Customer external KMS; cloudhsm=Customer CloudHSM', regex: '^(sse|awskms|awscmk|externalcmk|cloudhsm)$', - default: 'sse', + default: 'awskms', }, s3_allow_unencrypted_static_websites: { name: 'S3 Allow Unencrypted Static Websites', diff --git a/plugins/aws/ses/emailMessagesEncrypted.js b/plugins/aws/ses/emailMessagesEncrypted.js index 58b13560ff..183dfc2193 100644 --- a/plugins/aws/ses/emailMessagesEncrypted.js +++ b/plugins/aws/ses/emailMessagesEncrypted.js @@ -16,7 +16,7 @@ module.exports = { name: 'SES Email Desired Encryption Level', description: 'Desired encryption level for email messages to encrypt them before they get saves on S3', regex: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['ses:CreateEmailIdentity','ses:SetActiveReceiptRuleSet','ses:DeleteEmailIdentity'], diff --git a/plugins/aws/sqs/sqsEncryptionEnabled.js b/plugins/aws/sqs/sqsEncryptionEnabled.js index 40eb3ab4d3..d4957752af 100644 --- a/plugins/aws/sqs/sqsEncryptionEnabled.js +++ b/plugins/aws/sqs/sqsEncryptionEnabled.js @@ -18,7 +18,7 @@ module.exports = { name: 'SQS Queues Target Encryption Level', description: 'In order (lowest to highest) sse=SSE-SQS; awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(sse|awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['sqs:CreateQueue', 'sqs:SetQueueAttributes', 'sqs:DeleteQueue'], diff --git a/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js b/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js index c8dbcd8db5..dd6b36ff2d 100644 --- a/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js +++ b/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js @@ -18,7 +18,7 @@ module.exports = { name: 'Timestream Database Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk' + default: 'awskms' } }, realtime_triggers: ['timestreamwrite:CreateDatabase', 'timestreamwrite:UpdateDatabase', 'timestreamwrite:DeleteDatabase'], diff --git a/plugins/aws/translate/translateJobOutputEncrypted.js b/plugins/aws/translate/translateJobOutputEncrypted.js index feba36c78c..e178e77e7d 100644 --- a/plugins/aws/translate/translateJobOutputEncrypted.js +++ b/plugins/aws/translate/translateJobOutputEncrypted.js @@ -17,7 +17,7 @@ module.exports = { name: 'Translate Job Target Encryption Level', description: 'In order (lowest to highest) awskms=AWS-managed KMS; awscmk=Customer managed KMS; externalcmk=Customer managed externally sourced KMS; cloudhsm=Customer managed CloudHSM sourced KMS', regex: '^(awskms|awscmk|externalcmk|cloudhsm)$', - default: 'awscmk', + default: 'awskms', } }, realtime_triggers: ['translate:StartTextTranslationJob', 'translate:StopTextTranslationJob'], diff --git a/plugins/aws/translate/translateJobOutputEncrypted.spec.js b/plugins/aws/translate/translateJobOutputEncrypted.spec.js index 7b870fb1f1..38eccaca76 100644 --- a/plugins/aws/translate/translateJobOutputEncrypted.spec.js +++ b/plugins/aws/translate/translateJobOutputEncrypted.spec.js @@ -126,7 +126,7 @@ describe('translateJobOutputEncrypted', function () { it('should FAIL if Translate job is not encrypted with desired encryption level', function (done) { const cache = createCache([listTextTranslationJobs[1]], listKeys); - translateJobOutputEncrypted.run(cache, {}, (err, results) => { + translateJobOutputEncrypted.run(cache, {translate_job_encryption_level: 'awscmk'}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].region).to.equal('us-east-1'); From 08dbcb8cbc42eaa615bf94735fac166859cf7208 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 26 Aug 2024 14:07:14 +0500 Subject: [PATCH 47/91] fix test --- plugins/aws/eks/eksKubernetesVersion.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/eks/eksKubernetesVersion.spec.js b/plugins/aws/eks/eksKubernetesVersion.spec.js index b53206f8d2..0997f85358 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.27", + "version": "1.29", } } ); From 624728f6f46d55b343c6e9ea75e0360f12a2596d Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 26 Aug 2024 14:37:30 +0500 Subject: [PATCH 48/91] update files --- plugins/aws/eks/eksKubernetesVersion.spec.js | 2 +- plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/aws/eks/eksKubernetesVersion.spec.js b/plugins/aws/eks/eksKubernetesVersion.spec.js index b53206f8d2..0997f85358 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.27", + "version": "1.29", } } ); diff --git a/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js b/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js index 2bb4fe8840..34748a2305 100644 --- a/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js +++ b/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js @@ -6,8 +6,8 @@ module.exports = { category: 'AI & ML', domain: 'Machine Learning', severity: 'Medium', - description: 'Ensures diagnostic logging is enabled for Synapse workspace.', - more_info: 'Enabling diagnostic logging for Azure Synapse workspace enhances performance monitoring, troubleshooting, and security optimization. This feature captures detailed logs of workspace activities, allowing you to gain insights, identify issues, and maintain the integrity and efficiency of data operations.', + description: 'Ensures that diagnostic logging is enabled for Synapse workspace.', + more_info: 'Enabling diagnostic logs in Azure Synapse workspace is important for monitoring, troubleshooting, and optimizing performance. These logs provide detailed insights into resource usage, query execution, and potential issues, allowing administrators to identify bottlenecks, track errors, and improve the overall efficiency and reliability of the workspace.', recommended_action: 'Enable diagnostic logging for all Synapse workspaces.', link: 'https://learn.microsoft.com/en-gb/azure/azure-monitor/essentials/diagnostic-settings', apis: ['synapse:listWorkspaces', 'diagnosticSettings:listByWorkspaces'], @@ -24,7 +24,6 @@ module.exports = { if (!workspaces) return rcb(); - if (workspaces.err || !workspaces.data) { helpers.addResult(results, 3, 'Unable to query Synapse workspaces: ' + helpers.addError(workspaces), location); return rcb(); @@ -36,6 +35,7 @@ module.exports = { } for (let workspace of workspaces.data) { + var diagnosticSettings = helpers.addSource(cache, source, ['diagnosticSettings', 'listByWorkspaces', location, workspace.id]); From aacbb67b3b1f38d014a69df244731b6255ff1620 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 26 Aug 2024 14:42:05 +0500 Subject: [PATCH 49/91] update files --- plugins/aws/eks/eksKubernetesVersion.spec.js | 2 +- plugins/aws/qldb/ledgerDeletionProtection.js | 8 ++++---- plugins/aws/qldb/ledgerDeletionProtection.spec.js | 6 +++++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/plugins/aws/eks/eksKubernetesVersion.spec.js b/plugins/aws/eks/eksKubernetesVersion.spec.js index b53206f8d2..0997f85358 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.27", + "version": "1.29", } } ); diff --git a/plugins/aws/qldb/ledgerDeletionProtection.js b/plugins/aws/qldb/ledgerDeletionProtection.js index 586866037c..ad75bf96a7 100644 --- a/plugins/aws/qldb/ledgerDeletionProtection.js +++ b/plugins/aws/qldb/ledgerDeletionProtection.js @@ -6,7 +6,7 @@ module.exports = { category: 'QLDB', domain: 'Databases', severity: 'Medium', - description: 'Ensure that AWS QLDB ledger has deletion protection feature enabled.', + description: 'Ensures that AWS QLDB ledger has deletion protection feature enabled.', more_info: 'Enabling deletion protection feature for Amazon QLDB ledger acts as a safety net, preventing accidental database deletions or deletion by an unauthorized user. It ensures that the data stays secure and accessible at all times.', recommended_action: 'Modify QLDB ledger and enable deletion protection.', link: 'https://docs.aws.amazon.com/qldb/latest/developerguide/ledger-management.basics.html', @@ -30,12 +30,12 @@ module.exports = { if (listLedgers.err || !listLedgers.data) { helpers.addResult(results, 3, - 'Unable to query Ledgers: ' + helpers.addError(listLedgers), region); + 'Unable to query QLDB ledgers: ' + helpers.addError(listLedgers), region); return rcb(); } if (!listLedgers.data.length) { - helpers.addResult(results, 0, 'No Ledgers found', region); + helpers.addResult(results, 0, 'No QLDB ledgers found', region); return rcb(); } @@ -49,7 +49,7 @@ module.exports = { if (!describeLedger || describeLedger.err || !describeLedger.data ) { helpers.addResult(results, 3, - `Unable to get Ledgers description: ${helpers.addError(describeLedger)}`, + `Unable to get QLDB ledgers description: ${helpers.addError(describeLedger)}`, region, resource); continue; } diff --git a/plugins/aws/qldb/ledgerDeletionProtection.spec.js b/plugins/aws/qldb/ledgerDeletionProtection.spec.js index a22d30c62c..afa8a28222 100644 --- a/plugins/aws/qldb/ledgerDeletionProtection.spec.js +++ b/plugins/aws/qldb/ledgerDeletionProtection.spec.js @@ -58,6 +58,7 @@ describe('ledgerDeletionProtection', function () { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('QLDB ledger has deletion protection enabled'); done(); }); }); @@ -68,6 +69,7 @@ describe('ledgerDeletionProtection', function () { 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('QLDB ledger does not have deletion protection enabled'); done(); }); }); @@ -78,16 +80,18 @@ describe('ledgerDeletionProtection', function () { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('No QLDB ledgers found'); done(); }); }); - it('should UNKNOWN if unable to list QLDB ledgers', function (done) { + it('should UNKNOWN if unable to list QLDB ledgers', function (done) { const cache = createCache(null, null, null, { message: "Unable to list QLDB ledgers" }); ledgerDeletionProtection.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(3); expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('Unable to query QLDB ledgers'); done(); }); }); From 605098032e605741cbf0be11f896884af7621786 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 26 Aug 2024 14:42:40 +0500 Subject: [PATCH 50/91] update files --- plugins/aws/eks/eksKubernetesVersion.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/eks/eksKubernetesVersion.spec.js b/plugins/aws/eks/eksKubernetesVersion.spec.js index b53206f8d2..0997f85358 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.27", + "version": "1.29", } } ); From 5b753b5e1aadf105cc8130ca7be579c079204582 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 26 Aug 2024 14:43:15 +0500 Subject: [PATCH 51/91] update files --- plugins/aws/eks/eksKubernetesVersion.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/eks/eksKubernetesVersion.spec.js b/plugins/aws/eks/eksKubernetesVersion.spec.js index b53206f8d2..0997f85358 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.27", + "version": "1.29", } } ); From 255a0a48aa24e1972678a4924a86c618f4a3413d Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Mon, 26 Aug 2024 23:32:37 +0500 Subject: [PATCH 52/91] Update plugins/aws/qldb/ledgerHasTags.js --- plugins/aws/qldb/ledgerHasTags.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/qldb/ledgerHasTags.js b/plugins/aws/qldb/ledgerHasTags.js index eecd57c15e..f6973c2f73 100644 --- a/plugins/aws/qldb/ledgerHasTags.js +++ b/plugins/aws/qldb/ledgerHasTags.js @@ -6,7 +6,7 @@ module.exports = { category: 'QLDB', domain: 'Databases', severity: 'Low', - description: 'Ensure that AWS QLDB ledger has tags associated.', + description: 'Ensure that AWS QLDB ledgers have tags associated.', more_info: 'Tags help you to group resources together that are related to or associated with each other. It is a best practice to tag cloud resources to better organize and gain visibility into their usage.', recommended_action: 'Modify QLDB ledger and add tags.', link: 'https://docs.aws.amazon.com/qldb/latest/developerguide/tagging.html', From 81e38fc1abda5b7cadda04926837d21159696483 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 2 Sep 2024 15:54:39 +0500 Subject: [PATCH 53/91] Update plugins/aws/qldb/ledgerDeletionProtection.js Co-authored-by: alphadev4 <113519745+alphadev4@users.noreply.github.com> --- plugins/aws/qldb/ledgerDeletionProtection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/qldb/ledgerDeletionProtection.js b/plugins/aws/qldb/ledgerDeletionProtection.js index ad75bf96a7..b303a51e0e 100644 --- a/plugins/aws/qldb/ledgerDeletionProtection.js +++ b/plugins/aws/qldb/ledgerDeletionProtection.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Databases', severity: 'Medium', description: 'Ensures that AWS QLDB ledger has deletion protection feature enabled.', - more_info: 'Enabling deletion protection feature for Amazon QLDB ledger acts as a safety net, preventing accidental database deletions or deletion by an unauthorized user. It ensures that the data stays secure and accessible at all times.', + more_info: 'Enabling deletion protection for an Amazon QLDB ledger prevents accidental or unauthorized deletions, ensuring the ledger remains secure and accessible. It requires explicit action to disable this protection before the ledger can be deleted.', recommended_action: 'Modify QLDB ledger and enable deletion protection.', link: 'https://docs.aws.amazon.com/qldb/latest/developerguide/ledger-management.basics.html', apis: ['QLDB:listLedgers','QLDB:describeLedger','STS:getCallerIdentity'], From aed60c2b1619f1045241f74ecf003d8d7e4d7f4a Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Wed, 4 Sep 2024 13:28:47 +0500 Subject: [PATCH 54/91] Update plugins/azure/synapse/synapseWorkspaceHasTags.js Co-authored-by: alphadev4 <113519745+alphadev4@users.noreply.github.com> --- plugins/azure/synapse/synapseWorkspaceHasTags.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/synapse/synapseWorkspaceHasTags.js b/plugins/azure/synapse/synapseWorkspaceHasTags.js index a063e7f788..c9e6b35c01 100644 --- a/plugins/azure/synapse/synapseWorkspaceHasTags.js +++ b/plugins/azure/synapse/synapseWorkspaceHasTags.js @@ -6,7 +6,7 @@ module.exports = { category: 'AI & ML', domain: 'Machine Learning', severity: 'Low', - description: 'Ensures that Azure Synapse workspace has tags associated.', + description: 'Ensures that Azure Synapse workspaces have tags associated.', more_info: 'Tags help you to group resources together that are related to or associated with each other. It is a best practice to tag cloud resources to better organize and gain visibility into their usage.', recommended_action: 'Modify Synapse workspace and add tags.', link: 'https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources', From 45a2fed0d3b4b8875eef8de0913d25804de326b7 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:41:13 +0500 Subject: [PATCH 55/91] Update plugins/azure/synapse/synapseWorkspaceHasTags.js --- plugins/azure/synapse/synapseWorkspaceHasTags.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/synapse/synapseWorkspaceHasTags.js b/plugins/azure/synapse/synapseWorkspaceHasTags.js index c9e6b35c01..33a0cfa963 100644 --- a/plugins/azure/synapse/synapseWorkspaceHasTags.js +++ b/plugins/azure/synapse/synapseWorkspaceHasTags.js @@ -11,7 +11,7 @@ module.exports = { recommended_action: 'Modify Synapse workspace and add tags.', link: 'https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources', apis: ['synapse:listWorkspaces'], - realtime_triggers: ['microsoftsynapse:workspaces:write','microsoftsynapse:workspaces:delete'], + realtime_triggers: ['microsoftsynapse:workspaces:write','microsoftsynapse:workspaces:delete','microsoftresources:tags:write'], run: function(cache, settings, callback) { const results = []; From 425cf981ed5a82f383fbaaab22d4ff05f57f688f Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:46:13 +0500 Subject: [PATCH 56/91] Update plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js --- .../azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js b/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js index 6815ac07ae..cbd0a140ec 100644 --- a/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js +++ b/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js @@ -3,7 +3,7 @@ var mysqlFlexibleServerLoggingEnabled = require("./mysqlFlexibleServerLoggingEna const activityLogAlerts = [ { - "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourceGroups/Default-ActivityLogAlerts/providers/microsoft.insights/activityLogAlerts/NSG2", + "id": "/subscriptions/12345/resourceGroups/Default-ActivityLogAlerts/providers/microsoft.insights/activityLogAlerts/NSG2", "name": "NSG2", "type": "Microsoft.Insights/ActivityLogAlerts", "location": "global", From 3c41a68f84bfafe5209a039a495245e2783db340 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:46:21 +0500 Subject: [PATCH 57/91] Update plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js --- plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js b/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js index d164e6674d..dbc0ee75ca 100644 --- a/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js +++ b/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Databases', severity: 'High', description: 'Ensures that MySQL flexible servers are encrypted using CMK.', - more_info: 'MySQL flexible server allows you to encrypt data using customer-managed keys (CMK) instead of using platform-managed keys, which are enabled by default. Using CMK encryption offers enhanced security and compliance, allowing centralized management and control of encryption keys through Azure Key Vault.', + more_info: 'MySQL flexible server allows you to encrypt data using customer-managed keys (CMK) instead of using platform-managed keys, which are enabled by default. Using CMK encryption offers enhanced security and compliance, allowing centralized management and control of encryption keys through Azure Key Vault. It adds an extra layer of protection against unauthorized access to sensitive data stored in the database.', recommended_action: 'Modify MySQL flexible server and disable public network access.', link: 'https://learn.microsoft.com/en-us/azure/mysql/flexible-server/concepts-customer-managed-key', apis: ['servers:listMysqlFlexibleServer'], From cffd526ae361ced76075b64330096b0e3152cbf1 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:47:34 +0500 Subject: [PATCH 58/91] Update exports.js --- exports.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exports.js b/exports.js index 6523bdcd76..792959f017 100644 --- a/exports.js +++ b/exports.js @@ -733,7 +733,7 @@ module.exports = { 'containerAppVolumeMount' : require(__dirname + '/plugins/azure/containerapps/containerAppVolumeMount.js'), 'containerAppHttpsOnly' : require(__dirname + '/plugins/azure/containerapps/containerAppHttpsOnly.js'), 'containerAppHasTags' : require(__dirname + '/plugins/azure/containerapps/containerAppHasTags.js'), - 'containerAppIPRestriction' : require(__dirname + '/plugins/azure/containerapps/containerAppIPRestriction.js'), + 'containerAppIPRestriction' : require(__dirname + '/plugins/azure/containerapps/containerAppIPRestriction.js'), 'workspacePublicAccessDisabled' : require(__dirname + '/plugins/azure/machinelearning/workspacePublicAccessDisabled.js'), 'workspaceLoggingEnabled' : require(__dirname + '/plugins/azure/machinelearning/workspaceLoggingEnabled.js'), From ae13f9cf00bc64d6204228286d712bb645374bd9 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:47:42 +0500 Subject: [PATCH 59/91] Update plugins/azure/containerapps/containerAppIPRestriction.js --- plugins/azure/containerapps/containerAppIPRestriction.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/azure/containerapps/containerAppIPRestriction.js b/plugins/azure/containerapps/containerAppIPRestriction.js index a134c7e471..917d45ac84 100644 --- a/plugins/azure/containerapps/containerAppIPRestriction.js +++ b/plugins/azure/containerapps/containerAppIPRestriction.js @@ -19,7 +19,6 @@ module.exports = { var locations = helpers.locations(settings.govcloud); async.each(locations.containerApps, function(location, rcb) { - var containerApps = helpers.addSource(cache, source, ['containerApps', 'list', location]); From 854d0249c4015bdac88dbda3a7886b480e8aaf77 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:48:01 +0500 Subject: [PATCH 60/91] Update plugins/azure/containerapps/containerAppIPRestriction.js --- plugins/azure/containerapps/containerAppIPRestriction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/containerapps/containerAppIPRestriction.js b/plugins/azure/containerapps/containerAppIPRestriction.js index 917d45ac84..8a57d9decb 100644 --- a/plugins/azure/containerapps/containerAppIPRestriction.js +++ b/plugins/azure/containerapps/containerAppIPRestriction.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Containers', severity: 'Medium', description: 'Ensures that Container Apps are configured to allow only specific IP addresses.', - more_info: 'Azure Container Apps allows you to control inbound traffic by configuring IP ingress restrictions. You can specify rules to either allow traffic only from defined address ranges or deny traffic from specified ranges. Without any IP restriction rules, all inbound traffic is permitted, which may expose your application to security risks.', + more_info: 'Azure Container Apps provides IP ingress restrictions for controlling inbound traffic, enhancing application security. Allow or deny rules can be defined for specific IP ranges, enabling precise access management to container apps. This feature is crucial for reducing potential security vulnerabilities, as unrestricted configurations permit all inbound traffic by default.' recommended_action: 'Modify Container Apps and configure IP restriction.', link: 'https://learn.microsoft.com/en-us/azure/container-apps/ip-restrictions', apis: ['containerApps:list'], From 2412557c2a14917354acf6599d23b3cbabd4d46a Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:48:08 +0500 Subject: [PATCH 61/91] Update plugins/azure/containerapps/containerAppIPRestriction.js --- plugins/azure/containerapps/containerAppIPRestriction.js | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/azure/containerapps/containerAppIPRestriction.js b/plugins/azure/containerapps/containerAppIPRestriction.js index 8a57d9decb..8870f86b62 100644 --- a/plugins/azure/containerapps/containerAppIPRestriction.js +++ b/plugins/azure/containerapps/containerAppIPRestriction.js @@ -37,6 +37,7 @@ module.exports = { for (let container of containerApps.data) { if (!container.id) continue; + if (container.configuration && container.configuration.ingress && container.configuration.ingress.ipSecurityRestrictions && container.configuration.ingress.ipSecurityRestrictions.length) { helpers.addResult(results, 0, 'Container app has IP restrictions configured', location, container.id); From 150dd32f310b2ad9891a772b0393b04c53537c93 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:48:19 +0500 Subject: [PATCH 62/91] Update plugins/azure/containerapps/containerAppIPRestriction.js --- plugins/azure/containerapps/containerAppIPRestriction.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/azure/containerapps/containerAppIPRestriction.js b/plugins/azure/containerapps/containerAppIPRestriction.js index 8870f86b62..87f3ebfef2 100644 --- a/plugins/azure/containerapps/containerAppIPRestriction.js +++ b/plugins/azure/containerapps/containerAppIPRestriction.js @@ -38,7 +38,10 @@ module.exports = { for (let container of containerApps.data) { if (!container.id) continue; - if (container.configuration && container.configuration.ingress && container.configuration.ingress.ipSecurityRestrictions && container.configuration.ingress.ipSecurityRestrictions.length) { + if (container.configuration && + container.configuration.ingress && + container.configuration.ingress.ipSecurityRestrictions && + container.configuration.ingress.ipSecurityRestrictions.length) { helpers.addResult(results, 0, 'Container app has IP restrictions configured', location, container.id); From 69438e1dc1582cd73cba46364d6e92914dc2ac24 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 16 Sep 2024 13:58:19 +0500 Subject: [PATCH 63/91] fixed --- plugins/aws/eks/eksKubernetesVersion.spec.js | 2 +- .../mysqlserver/mysqlFlexibleServerCMKEncrypted.js | 10 +++++----- .../mysqlFlexibleServerCMKEncrypted.spec.js | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/aws/eks/eksKubernetesVersion.spec.js b/plugins/aws/eks/eksKubernetesVersion.spec.js index b53206f8d2..0997f85358 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.27", + "version": "1.29", } } ); diff --git a/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js b/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js index dbc0ee75ca..29b0b57100 100644 --- a/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js +++ b/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js @@ -2,13 +2,13 @@ const async = require('async'); const helpers = require('../../../helpers/azure'); module.exports = { - title: 'MySQL Flexible Server CMK Encrypted', + title: 'MySQL Flexible Server Data CMK Encrypted', category: 'MySQL Server', domain: 'Databases', severity: 'High', - description: 'Ensures that MySQL flexible servers are encrypted using CMK.', + description: 'Ensures that MySQL flexible servers data is encrypted using CMK.', more_info: 'MySQL flexible server allows you to encrypt data using customer-managed keys (CMK) instead of using platform-managed keys, which are enabled by default. Using CMK encryption offers enhanced security and compliance, allowing centralized management and control of encryption keys through Azure Key Vault. It adds an extra layer of protection against unauthorized access to sensitive data stored in the database.', - recommended_action: 'Modify MySQL flexible server and disable public network access.', + recommended_action: 'Ensure that MySQL flexible server have CMK encryption enabled.', link: 'https://learn.microsoft.com/en-us/azure/mysql/flexible-server/concepts-customer-managed-key', apis: ['servers:listMysqlFlexibleServer'], realtime_triggers: ['microsoftdbformysql:flexibleservers:write','microsoftdbformysql:flexibleservers:delete'], @@ -39,9 +39,9 @@ module.exports = { if (!flexibleServer.id) continue; if (flexibleServer.dataEncryption && flexibleServer.dataEncryption.primaryKeyURI ) { - helpers.addResult(results, 0, 'MySQL flexible server is encrypted using CMK', location, flexibleServer.id); + helpers.addResult(results, 0, 'MySQL flexible server data is encrypted using CMK', location, flexibleServer.id); } else { - helpers.addResult(results, 2, 'MySQL flexible server is not encrypted using CMK', location, flexibleServer.id); + helpers.addResult(results, 2, 'MySQL flexible server data is not encrypted using CMK', location, flexibleServer.id); } } rcb(); diff --git a/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.spec.js b/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.spec.js index 418c8a2f7a..17341ed4e1 100644 --- a/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.spec.js +++ b/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.spec.js @@ -39,7 +39,7 @@ describe('mysqlFlexibleServerManagedIdentity', function() { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('MySQL flexible server is not encrypted using CMK'); + expect(results[0].message).to.include('MySQL flexible server data is not encrypted using CMK'); expect(results[0].region).to.equal('eastus'); done() }; @@ -62,7 +62,7 @@ describe('mysqlFlexibleServerManagedIdentity', function() { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('MySQL flexible server is encrypted using CMK'); + expect(results[0].message).to.include('MySQL flexible server data is encrypted using CMK'); expect(results[0].region).to.equal('eastus'); done() }; From fc4bb924299a2edb60329e176ef590ce8d33b4cc Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:59:29 +0500 Subject: [PATCH 64/91] Update plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js --- plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js b/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js index 29b0b57100..d188ae81d3 100644 --- a/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js +++ b/plugins/azure/mysqlserver/mysqlFlexibleServerCMKEncrypted.js @@ -38,7 +38,7 @@ module.exports = { for (var flexibleServer of servers.data) { if (!flexibleServer.id) continue; - if (flexibleServer.dataEncryption && flexibleServer.dataEncryption.primaryKeyURI ) { + if (flexibleServer.dataEncryption && flexibleServer.dataEncryption.primaryKeyURI) { helpers.addResult(results, 0, 'MySQL flexible server data is encrypted using CMK', location, flexibleServer.id); } else { helpers.addResult(results, 2, 'MySQL flexible server data is not encrypted using CMK', location, flexibleServer.id); From 93db95dfb7bd92724b14f5dac9e2ac5cbbc03abb Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 16 Sep 2024 14:10:41 +0500 Subject: [PATCH 65/91] fix --- plugins/aws/eks/eksKubernetesVersion.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/eks/eksKubernetesVersion.spec.js b/plugins/aws/eks/eksKubernetesVersion.spec.js index b53206f8d2..0997f85358 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.27", + "version": "1.29", } } ); From 7ae52b2c53f7b24fa551cf9eb6bf906444be381d Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 16 Sep 2024 14:30:15 +0500 Subject: [PATCH 66/91] fix --- plugins/azure/containerapps/containerAppIPRestriction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/containerapps/containerAppIPRestriction.js b/plugins/azure/containerapps/containerAppIPRestriction.js index 87f3ebfef2..0a1f822e7c 100644 --- a/plugins/azure/containerapps/containerAppIPRestriction.js +++ b/plugins/azure/containerapps/containerAppIPRestriction.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Containers', severity: 'Medium', description: 'Ensures that Container Apps are configured to allow only specific IP addresses.', - more_info: 'Azure Container Apps provides IP ingress restrictions for controlling inbound traffic, enhancing application security. Allow or deny rules can be defined for specific IP ranges, enabling precise access management to container apps. This feature is crucial for reducing potential security vulnerabilities, as unrestricted configurations permit all inbound traffic by default.' + more_info: 'Azure Container Apps provides IP ingress restrictions for controlling inbound traffic, enhancing application security. Allow or deny rules can be defined for specific IP ranges, enabling precise access management to container apps. This feature is crucial for reducing potential security vulnerabilities, as unrestricted configurations permit all inbound traffic by default.', recommended_action: 'Modify Container Apps and configure IP restriction.', link: 'https://learn.microsoft.com/en-us/azure/container-apps/ip-restrictions', apis: ['containerApps:list'], From 51e6b54953da5270fa2bf1c551914baeb41e4b1d Mon Sep 17 00:00:00 2001 From: alphadev4 Date: Mon, 16 Sep 2024 19:30:15 +0500 Subject: [PATCH 67/91] syncing with saas --- collectors/aws/ecs/listContainerInstances.js | 6 +- collectors/aws/ecs/listServices.js | 5 +- collectors/aws/iam/getRole.js | 40 +++++ exports.js | 31 ++-- helpers/asl/asl-1.js | 39 +++- helpers/aws/api.js | 26 ++- helpers/aws/api_multipart.js | 25 ++- helpers/aws/functions.js | 170 ++++++++++++++++-- helpers/azure/functions.js | 65 ++++++- helpers/google/functions.js | 52 +++++- helpers/shared.js | 10 +- .../securitycenter/securityCenterEdition.js | 58 +++--- plugins/aws/ec2/ec2NetworkExposure.js | 61 +++++++ plugins/aws/eks/eksKubernetesVersion.spec.js | 2 +- plugins/aws/elbv2/elbv2UnhealthyInstance.js | 14 +- plugins/aws/elbv2/elbv2WafEnabled.js | 22 ++- plugins/aws/iam/iamMasterManagerRoles.js | 2 +- .../securityhub/securityHubActiveFindings.js | 6 +- .../securityHubActiveFindings.spec.js | 59 ++---- plugins/azure/appservice/authEnabled.js | 39 ++-- plugins/azure/appservice/authEnabled.spec.js | 37 +++- plugins/azure/appservice/httpsOnlyEnabled.js | 24 ++- .../azure/appservice/httpsOnlyEnabled.spec.js | 18 +- .../blobServiceLoggingEnabled.js | 3 + .../blobServiceLoggingEnabled.spec.js | 22 +++ .../queueServiceLoggingEnabled.js | 5 +- .../queueServiceLoggingEnabled.spec.js | 23 ++- .../storageaccounts/storageAccountsHttps.js | 1 - .../tableServiceLoggingEnabled.js | 3 + .../tableServiceLoggingEnabled.spec.js | 23 ++- .../virtualmachines/vmNetworkExposure.js | 99 ++++++++++ .../google/compute/instanceNetworkExposure.js | 108 +++++++++++ 32 files changed, 930 insertions(+), 168 deletions(-) create mode 100644 collectors/aws/iam/getRole.js create mode 100644 plugins/aws/ec2/ec2NetworkExposure.js create mode 100644 plugins/azure/virtualmachines/vmNetworkExposure.js create mode 100644 plugins/google/compute/instanceNetworkExposure.js diff --git a/collectors/aws/ecs/listContainerInstances.js b/collectors/aws/ecs/listContainerInstances.js index 987ca65d2b..c7b9eb175e 100644 --- a/collectors/aws/ecs/listContainerInstances.js +++ b/collectors/aws/ecs/listContainerInstances.js @@ -16,13 +16,13 @@ module.exports = function(AWSConfig, collection, retries, callback) { helpers.makeCustomCollectorCall(ecs, 'listContainerInstances', params, retries, null, null, null, function(err, data) { if (err) { collection.ecs.listContainerInstances[AWSConfig.region][cluster].err = err; + } else if (data && data.containerInstanceArns) { + collection.ecs.listContainerInstances[AWSConfig.region][cluster].data = data.containerInstanceArns; } - collection.ecs.listContainerInstances[AWSConfig.region][cluster].data = data.containerInstanceArns; - cb(); }); }, function(){ callback(); }); -}; \ No newline at end of file +}; diff --git a/collectors/aws/ecs/listServices.js b/collectors/aws/ecs/listServices.js index 916ab9002d..4898290ad1 100644 --- a/collectors/aws/ecs/listServices.js +++ b/collectors/aws/ecs/listServices.js @@ -19,12 +19,11 @@ module.exports = function(AWSConfig, collection, retries, callback) { if (err) { collection.ecs.listServices[AWSConfig.region][cluster].err = err; } - - collection.ecs.listServices[AWSConfig.region][cluster].data = data.serviceArns; + if (data && data.serviceArns) collection.ecs.listServices[AWSConfig.region][cluster].data = data.serviceArns; cb(); }); }, function(){ callback(); }); -}; \ No newline at end of file +}; diff --git a/collectors/aws/iam/getRole.js b/collectors/aws/iam/getRole.js new file mode 100644 index 0000000000..5ec172fe45 --- /dev/null +++ b/collectors/aws/iam/getRole.js @@ -0,0 +1,40 @@ +var AWS = require('aws-sdk'); +var async = require('async'); +var helpers = require(__dirname + '/../../../helpers/aws'); + +module.exports = function(AWSConfig, collection, retries, callback) { + var iam = new AWS.IAM(AWSConfig); + + if (!collection.iam || + !collection.iam.listRoles || + !collection.iam.listRoles[AWSConfig.region] || + !collection.iam.listRoles[AWSConfig.region].data) return callback(); + + async.eachLimit(collection.iam.listRoles[AWSConfig.region].data, 10, function(role, cb){ + if (!role.Arn || + !collection.iam.listRoles || + !collection.iam.listRoles[AWSConfig.region] || + !collection.iam.listRoles[AWSConfig.region].data) { + + return cb(); + } + + collection.iam.getRole[AWSConfig.region][role.RoleName] = {}; + + helpers.makeCustomCollectorCall(iam, 'getRole', {RoleName: role.RoleName}, retries, null, null, null, function(err, data) { + if (err) { + collection.iam.getRole[AWSConfig.region][role.RoleName].err = err; + } + if (data) { + delete data['ResponseMetadata']; + + data.Role.AssumeRolePolicyDocument = helpers.normalizePolicyDocument(data.Role.AssumeRolePolicyDocument); + collection.iam.getRole[AWSConfig.region][role.RoleName].data = data; + } + + cb(); + }); + }, function(){ + callback(); + }); +}; diff --git a/exports.js b/exports.js index dcbf2a3dbb..9364256d79 100644 --- a/exports.js +++ b/exports.js @@ -32,7 +32,7 @@ module.exports = { 'restrictExternalTraffic' : require(__dirname + '/plugins/aws/appmesh/restrictExternalTraffic.js'), 'appmeshTLSRequired' : require(__dirname + '/plugins/aws/appmesh/appmeshTLSRequired.js'), 'appmeshVGHealthChecks' : require(__dirname + '/plugins/aws/appmesh/appmeshVGHealthChecks.js'), - + 'asgMultiAz' : require(__dirname + '/plugins/aws/autoscaling/asgMultiAz.js'), 'asgActiveNotifications' : require(__dirname + '/plugins/aws/autoscaling/asgActiveNotifications.js'), @@ -242,6 +242,7 @@ module.exports = { 'ebsVolumeHasTags' : require(__dirname + '/plugins/aws/ec2/ebsVolumeHasTags.js'), 'openAllPortsProtocolsEgress' : require(__dirname + '/plugins/aws/ec2/openAllPortsProtocolsEgress.js'), 'defaultSecurityGroupInUse' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroupInUse.js'), + 'ec2NetworkExposure' : require(__dirname + '/plugins/aws/ec2/ec2NetworkExposure.js'), 'efsCmkEncrypted' : require(__dirname + '/plugins/aws/efs/efsCmkEncrypted.js'), 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), @@ -323,7 +324,7 @@ module.exports = { 'opensearchPublicEndpoint' : require(__dirname + '/plugins/aws/opensearch/opensearchPublicEndpoint.js'), 'opensearchRequireIAMAuth' : require(__dirname + '/plugins/aws/opensearch/opensearchRequireIAMAuth.js'), 'opensearchTlsVersion' : require(__dirname + '/plugins/aws/opensearch/opensearchTlsVersion.js'), - 'opensearchUpgradeAvailable' : require(__dirname + '/plugins/aws/opensearch/opensearchUpgradeAvailable.js'), + 'opensearchUpgradeAvailable' : require(__dirname + '/plugins/aws/opensearch/opensearchUpgradeAvailable.js'), 'opensearchVersion' : require(__dirname + '/plugins/aws/opensearch/opensearchVersion.js'), 'opensearchZoneAwarenessEnabled': require(__dirname + '/plugins/aws/opensearch/opensearchZoneAwarenessEnabled.js'), @@ -715,7 +716,7 @@ module.exports = { 'storageAccountHasTags' : require(__dirname + '/plugins/azure/storageaccounts/storageAccountHasTags.js'), 'storageAccountPrivateEndpoint' : require(__dirname + '/plugins/azure/storageaccounts/storageAccountPrivateEndpoint.js'), 'infrastructureEncryption' : require(__dirname + '/plugins/azure/storageaccounts/infrastructureEncryption.js'), - 'queueServiceLoggingEnabled' : require(__dirname + '/plugins/azure/storageaccounts/queueServiceLoggingEnabled.js'), + 'queueServiceLoggingEnabled' : require(__dirname + '/plugins/azure/storageaccounts/queueServiceLoggingEnabled.js'), 'tableServiceLoggingEnabled' : require(__dirname + '/plugins/azure/storageaccounts/tableServiceLoggingEnabled.js'), 'blobServiceLoggingEnabled' : require(__dirname + '/plugins/azure/storageaccounts/blobServiceLoggingEnabled.js'), @@ -725,8 +726,8 @@ module.exports = { 'fileServiceAllAccessAcl' : require(__dirname + '/plugins/azure/fileservice/fileServiceAllAccessAcl.js'), 'tableServiceAllAccessAcl' : require(__dirname + '/plugins/azure/tableservice/tableServiceAllAccessAcl.js'), - 'queueServiceAllAccessAcl' : require(__dirname + '/plugins/azure/queueservice/queueServiceAllAccessAcl.js'), - + 'queueServiceAllAccessAcl' : require(__dirname + '/plugins/azure/queueservice/queueServiceAllAccessAcl.js'), + 'externalNetworkAccess' : require(__dirname + '/plugins/azure/containerapps/externalNetworkAccess.js'), 'containerAppManagedIdentity' : require(__dirname + '/plugins/azure/containerapps/containerAppManagedIdentity.js'), 'containerAppAuthEnabled' : require(__dirname + '/plugins/azure/containerapps/containerAppAuthEnabled.js'), @@ -805,6 +806,7 @@ module.exports = { 'vmDiskCMKRotation' : require(__dirname + '/plugins/azure/virtualmachines/vmDiskCMKRotation.js'), 'vmDiskPublicAccess' : require(__dirname + '/plugins/azure/virtualmachines/vmDiskPublicAccess.js'), 'computeGalleryRbacSharing' : require(__dirname + '/plugins/azure/virtualmachines/computeGalleryRbacSharing.js'), + 'vmNetworkExposure' : require(__dirname + '/plugins/azure/virtualmachines/vmNetworkExposure.js'), 'bastionHostExists' : require(__dirname + '/plugins/azure/bastion/bastionHostExists.js'), 'bastionHostDiagnosticLogs' : require(__dirname + '/plugins/azure/bastion/bastionHostDiagnosticLogs.js'), @@ -815,7 +817,7 @@ module.exports = { 'monitorLogsEnabled' : require(__dirname + '/plugins/azure/monitor/monitorLogsEnabled.js'), 'diagnosticsCapturedCategories' : require(__dirname + '/plugins/azure/monitor/diagnosticsCapturedCategories.js'), 'diagnosticsSettingsEnabled' : require(__dirname + '/plugins/azure/monitor/diagnosticsSettingsEnabled.js'), - 'resourceAppropriateSKU' : require(__dirname + '/plugins/azure/monitor/monitorResourceSku.js'), + 'resourceAppropriateSKU' : require(__dirname + '/plugins/azure/monitor/monitorResourceSku.js'), 'securityPolicyAlertsEnabled' : require(__dirname + '/plugins/azure/logalerts/securityPolicyAlertsEnabled.js'), 'nsgLoggingEnabled' : require(__dirname + '/plugins/azure/logalerts/nsgLoggingEnabled.js'), @@ -966,7 +968,7 @@ module.exports = { 'sqlServerRecurringScans' : require(__dirname + '/plugins/azure/sqlserver/sqlServerRecurringScans.js'), 'sqlServerSendScanReports' : require(__dirname + '/plugins/azure/sqlserver/sqlServerSendScanReports.js'), 'sqlServerHasTags' : require(__dirname + '/plugins/azure/sqlserver/sqlServerHasTags.js'), - 'restrictOutboundNetworking' : require(__dirname + '/plugins/azure/sqlserver/restrictOutboundNetworking.js'), + 'restrictOutboundNetworking' : require(__dirname + '/plugins/azure/sqlserver/restrictOutboundNetworking.js'), 'auditOperationsEnabled' : require(__dirname + '/plugins/azure/sqlserver/auditOperationsEnabled.js'), 'serverConnectionPolicy' : require(__dirname + '/plugins/azure/sqlserver/serverConnectionPolicy.js'), 'auditStorageAuthType' : require(__dirname + '/plugins/azure/sqlserver/auditStorageAuthType.js'), @@ -1048,7 +1050,7 @@ module.exports = { 'dbLedgerEnabled' : require(__dirname + '/plugins/azure/sqldatabases/dbLedgerEnabled.js'), 'dbEnableSecureEnclaves' : require(__dirname + '/plugins/azure/sqldatabases/dbEnableSecureEnclaves.js'), 'dbDataDiscoveryClassification' : require(__dirname + '/plugins/azure/sqldatabases/dbDataDiscoveryClassification.js'), - + 'lbHttpsOnly' : require(__dirname + '/plugins/azure/loadbalancer/lbHttpsOnly.js'), 'lbNoInstances' : require(__dirname + '/plugins/azure/loadbalancer/lbNoInstances.js'), 'lbHasTags' : require(__dirname + '/plugins/azure/loadbalancer/lbHasTags.js'), @@ -1080,7 +1082,7 @@ module.exports = { 'cosmosdbHasTags' : require(__dirname + '/plugins/azure/cosmosdb/cosmosdbHasTags.js'), 'cosmosdbManagedIdentity' : require(__dirname + '/plugins/azure/cosmosdb/cosmosdbManagedIdentity.js'), 'cosmosdbLocalAuth' : require(__dirname + '/plugins/azure/cosmosdb/cosmosdbLocalAuth.js'), - + 'checkAdvisorRecommendations' : require(__dirname + '/plugins/azure/advisor/checkAdvisorRecommendations.js'), 'enableDefenderForStorage' : require(__dirname + '/plugins/azure/defender/enableDefenderForStorage.js'), @@ -1102,7 +1104,7 @@ module.exports = { 'applicationGatewayHasTags' : require(__dirname + '/plugins/azure/applicationGateway/applicationGatewayHasTags.js'), 'agSecurityLoggingEnabled' : require(__dirname + '/plugins/azure/applicationGateway/agSecurityLoggingEnabled.js'), 'agSslPolicy' : require(__dirname + '/plugins/azure/applicationGateway/agSslPolicy'), - 'agPreventionModeEnabled' : require(__dirname + '/plugins/azure/applicationGateway/agPreventionModeEnabled.js'), + 'agPreventionModeEnabled' : require(__dirname + '/plugins/azure/applicationGateway/agPreventionModeEnabled.js'), 'agRequestBodyInspection' : require(__dirname + '/plugins/azure/applicationGateway/agRequestBodyInspection'), 'agRequestBodySize' : require(__dirname + '/plugins/azure/applicationGateway/agRequestBodySize.js'), 'agHttpsListenerOnly' : require(__dirname + '/plugins/azure/applicationGateway/agHttpsListenerOnly.js'), @@ -1152,7 +1154,7 @@ module.exports = { 'namespaceLoggingEnabled' : require(__dirname + '/plugins/azure/servicebus/namespaceLoggingEnabled.js'), 'namespacePublicAccess' : require(__dirname + '/plugins/azure/servicebus/namespacePublicAccess.js'), 'namespaceInfraEncryption' : require(__dirname + '/plugins/azure/servicebus/namespaceInfraEncryption.js'), - + 'amsStorageAccountIdentity' : require(__dirname + '/plugins/azure/mediaServices/amsStorageAccountIdentity.js'), 'amsDiagnosticLogsEnabled' : require(__dirname + '/plugins/azure/mediaServices/amsDiagnosticLogsEnabled.js'), 'amsPublicAccessDisabled' : require(__dirname + '/plugins/azure/mediaServices/amsPublicAccessDisabled.js'), @@ -1177,7 +1179,7 @@ module.exports = { 'healthMonitoringExtensionHttps': require(__dirname + '/plugins/azure/virtualmachinescaleset/healthMonitoringExtensionHttps.js'), 'vmssBootDiagnosticsEnabled' : require(__dirname + '/plugins/azure/virtualmachinescaleset/vmssBootDiagnosticsEnabled'), 'vmssWindowsAntiMalwareExt' : require(__dirname + '/plugins/azure/virtualmachinescaleset/vmssWindowsAntiMalwareExt'), - + 'appConfigManagedIdentity' : require(__dirname + '/plugins/azure/appConfigurations/appConfigManagedIdentity.js'), 'appConfigurationDiagnosticLogs': require(__dirname + '/plugins/azure/appConfigurations/appConfigurationDiagnosticLogs.js'), 'appConfigurationPublicAccess' : require(__dirname + '/plugins/azure/appConfigurations/appConfigurationPublicAccess.js'), @@ -1187,7 +1189,7 @@ module.exports = { 'automationAcctDiagnosticLogs' : require(__dirname + '/plugins/azure/automationAccounts/automationAcctDiagnosticLogs.js'), 'automationAcctManagedIdentity' : require(__dirname + '/plugins/azure/automationAccounts/automationAcctManagedIdentity.js'), - 'automationAcctApprovedCerts' : require(__dirname + '/plugins/azure/automationAccounts/automationAcctApprovedCerts.js'), + 'automationAcctApprovedCerts' : require(__dirname + '/plugins/azure/automationAccounts/automationAcctApprovedCerts.js'), 'automationAcctEncryptedVars' : require(__dirname + '/plugins/azure/automationAccounts/automationAcctEncryptedVars.js'), 'automationAcctPublicAccess' : require(__dirname + '/plugins/azure/automationAccounts/automationAcctPublicAccess.js'), 'automationAcctExpiredWebhooks' : require(__dirname + '/plugins/azure/automationAccounts/automationAcctExpiredWebhooks.js'), @@ -1213,7 +1215,7 @@ module.exports = { 'workspaceManagedServicesCmk' : require(__dirname + '/plugins/azure/databricks/workspaceManagedServicesCmk.js'), 'workspaceManagedDiskCmk' : require(__dirname + '/plugins/azure/databricks/workspaceManagedDiskCmk.js'), 'workspaceHasTags' : require(__dirname + '/plugins/azure/databricks/workspaceHasTags.js'), - + 'workspaceManagedIdentity' : require(__dirname + '/plugins/azure/synapse/workspaceManagedIdentity.js'), 'synapseWorkspaceAdAuthEnabled' : require(__dirname + '/plugins/azure/synapse/synapseWorkspaceAdAuthEnabled.js'), 'synapseWorkspacPrivateEndpoint': require(__dirname + '/plugins/azure/synapse/synapseWorkspacPrivateEndpoint.js'), @@ -1436,6 +1438,7 @@ module.exports = { 'confidentialComputingEnabled' : require(__dirname + '/plugins/google/compute/confidentialComputingEnabled.js'), 'imagesCMKEncrypted' : require(__dirname + '/plugins/google/compute/imagesCMKEncrypted.js'), 'snapshotEncryption' : require(__dirname + '/plugins/google/compute/snapshotEncryption.js'), + 'instanceNetworkExposure' : require(__dirname + '/plugins/google/compute/instanceNetworkExposure.js'), 'keyRotation' : require(__dirname + '/plugins/google/cryptographickeys/keyRotation.js'), 'keyProtectionLevel' : require(__dirname + '/plugins/google/cryptographickeys/keyProtectionLevel.js'), diff --git a/helpers/asl/asl-1.js b/helpers/asl/asl-1.js index 55a68c39cc..06bfed0541 100644 --- a/helpers/asl/asl-1.js +++ b/helpers/asl/asl-1.js @@ -191,6 +191,30 @@ var validate = function(condition, conditionResult, inputResultsArr, message, pr message.push(`${condition.parsed} is not the right property type for this operation`); return 2; } + } else if (condition.op == 'NOTCONTAINS') { + var conditionStringified = JSON.stringify(condition.parsed); + if (condition.value && condition.value.includes(':')) { + + var conditionKey = condition.value.split(/:(?!.*:)/)[0]; + var conditionValue = condition.value.split(/:(?!.*:)/)[1]; + + if (conditionStringified.includes(conditionKey) && !conditionStringified.includes(conditionValue)){ + message.push(`${property}: ${condition.value} not found in ${conditionStringified}`); + return 0; + } else { + message.push(`${condition.value} found in ${conditionStringified}`); + return 2; + } + } else if (conditionStringified && !conditionStringified.includes(condition.value)) { + message.push(`${property}: ${condition.value} not found in ${conditionStringified}`); + return 0; + } else if (conditionStringified && conditionStringified.length){ + message.push(`${condition.value} found in ${conditionStringified}`); + return 2; + } else { + message.push(`${condition.parsed} is not the right property type for this operation`); + return 2; + } } else { // Recurse into the same function var subProcessed = []; @@ -280,6 +304,17 @@ var validate = function(condition, conditionResult, inputResultsArr, message, pr message.push(`${condition.parsed} is not the right property type for this operation`); return 2; } + } else if (condition.op == 'NOTCONTAINS') { + if (condition.parsed && condition.parsed.length && !condition.parsed.includes(condition.value)) { + message.push(`${property}: ${condition.value} not found in ${condition.parsed}`); + return 0; + } else if (condition.parsed && condition.parsed.length){ + message.push(`${condition.value} found in ${condition.parsed}`); + return 2; + } else { + message.push(`${condition.parsed} is not the right property type for this operation`); + return 2; + } } return conditionResult; } @@ -331,7 +366,7 @@ var runValidation = function(obj, condition, inputResultsArr, nestedResultArr) { propertyArr.shift(); property = propertyArr.join('.'); condition.property = property; - if (condition.op !== 'CONTAINS') { + if (condition.op !== 'CONTAINS' || condition.op !== 'NOTCONTAINS') { condition.parsed.forEach(parsed => { if (property.includes('[*]')) { runValidation(parsed, condition, inputResultsArr, nestedResultArr); @@ -567,4 +602,4 @@ var asl = function(source, input, resourceMap, cloud, accountId, callback) { callback(null, results, data); }; -module.exports = asl; \ No newline at end of file +module.exports = asl; diff --git a/helpers/aws/api.js b/helpers/aws/api.js index ee79979aaa..a0227ae405 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -1561,7 +1561,25 @@ var calls = { paginate: 'NextToken' }, getFindings: { - paginate: 'NextToken' + property: 'Findings', + paginate: 'NextToken', + params: { + MaxResults: 100, + Filters: { + RecordState: [ + { + Comparison: 'EQUALS', + Value: 'ACTIVE' + } + ], + WorkflowStatus: [ + { + Comparison: 'EQUALS', + Value: 'NEW' + } + ] + } + } } }, SageMaker: { @@ -2109,7 +2127,6 @@ var postcalls = [ filterKey: 'id', filterValue: 'projectId' }, - sendIntegration: serviceMap['CodeStar'] }, CustomerProfiles: { getDomain: { @@ -2175,7 +2192,7 @@ var postcalls = [ reliesOnService: 'docdb', reliesOnCall: 'describeDBClusters', filterKey: 'ResourceName', - filterValue: 'DBClusterArn' + filterValue: 'DBClusterArn' }, sendIntegration: serviceMap['DocumentDB'] }, @@ -3015,8 +3032,7 @@ var postcalls = [ getRole: { reliesOnService: 'iam', reliesOnCall: 'listRoles', - filterKey: 'RoleName', - filterValue: 'RoleName' + override: true }, getUser: { reliesOnService: 'iam', diff --git a/helpers/aws/api_multipart.js b/helpers/aws/api_multipart.js index 13d19bdb93..4590b8ffb0 100644 --- a/helpers/aws/api_multipart.js +++ b/helpers/aws/api_multipart.js @@ -1046,7 +1046,25 @@ var calls = [ paginate: 'NextToken' }, getFindings: { - paginate: 'NextToken' + property: 'Findings', + paginate: 'NextToken', + params: { + MaxResults: 100, + Filters: { + RecordState: [ + { + Comparison: 'EQUALS', + Value: 'ACTIVE' + } + ], + WorkflowStatus: [ + { + Comparison: 'EQUALS', + Value: 'NEW' + } + ] + } + } } }, Transfer: { @@ -1424,7 +1442,7 @@ var postcalls = [ reliesOnService: 'docdb', reliesOnCall: 'describeDBClusters', filterKey: 'ResourceName', - filterValue: 'DBClusterArn' + filterValue: 'DBClusterArn' }, }, DynamoDB: { @@ -2323,8 +2341,7 @@ var postcalls = [ getRole: { reliesOnService: 'iam', reliesOnCall: 'listRoles', - filterKey: 'RoleName', - filterValue: 'RoleName', + override: true, rateLimit: 500 }, listRolePolicies: { diff --git a/helpers/aws/functions.js b/helpers/aws/functions.js index b681ed5743..3b66ac6acf 100644 --- a/helpers/aws/functions.js +++ b/helpers/aws/functions.js @@ -174,15 +174,18 @@ function findOpenPorts(groups, ports, service, region, results, cache, config, c } } } - + return; } -function checkNetworkInterface(groupId, groupName, resultsString, region, results, resource, cache) { +function checkNetworkInterface(groupId, groupName, resultsString, region, results, resource, cache, bool = false) { const describeNetworkInterfaces = helpers.addSource(cache, {}, ['ec2', 'describeNetworkInterfaces', region]); if (!describeNetworkInterfaces || describeNetworkInterfaces.err || !describeNetworkInterfaces.data) { + if (bool) { + return false; + } helpers.addResult(results, 3, 'Unable to query for network interfaces: ' + helpers.addError(describeNetworkInterfaces), region); return; @@ -198,20 +201,28 @@ function checkNetworkInterface(groupId, groupName, resultsString, region, result } } } + if (bool && !networksWithSecurityGroup.length) { + return groupId; + } + let exposedENI; if (hasOpenSecurityGroup) { let hasPublicIp = false; for (var eni of networksWithSecurityGroup) { if (eni.Association && eni.Association.PublicIp) { hasPublicIp = true; + exposedENI = `sg ${groupId} > eni ${eni.NetworkInterfaceId}`; break; } } if (hasPublicIp) { + if (bool) return exposedENI; addResult(results, 2, `Security Group ${groupId}(${groupName}) is associated with an ENI that is publicly exposed`, region, resource); } else { + if (bool) return false; addResult(results, 0, `Security Group ${groupId} (${groupName}) is only exposed internally`, region, resource); } } else { + if (bool) return false; addResult(results, 2, resultsString, region, resource); } } @@ -291,7 +302,7 @@ function userGlobalAccess(statement, restrictedPermissions) { statement.Action && restrictedPermissions.some(permission=> statement.Action.includes(permission))) { return true; } - + return false; } @@ -324,7 +335,7 @@ function crossAccountPrincipal(principal, accountId, fetchPrincipals, settings={ } function hasFederatedUserRole(policyDocument) { - // true iff every statement refers to federated user access + // true iff every statement refers to federated user access for (let statement of policyDocument) { if (statement.Action && !statement.Action.includes('sts:AssumeRoleWithSAML') && @@ -339,13 +350,13 @@ function extractStatementPrincipals(statement) { let response = []; if (statement.Principal) { let principal = statement.Principal; - + if (typeof principal === 'string') { return [principal]; } if (!principal.AWS) return response; - + var awsPrincipals = principal.AWS; if (!Array.isArray(awsPrincipals)) { awsPrincipals = [awsPrincipals]; @@ -516,7 +527,7 @@ function getS3BucketLocation(cache, region, bucketName) { if (getBucketLocation.data.LocationConstraint && regions.all.includes(getBucketLocation.data.LocationConstraint)) return getBucketLocation.data.LocationConstraint; else if (getBucketLocation.data.LocationConstraint && - !regions.all.includes(getBucketLocation.data.LocationConstraint)) return 'global'; + !regions.all.includes(getBucketLocation.data.LocationConstraint)) return 'global'; else return 'us-east-1'; } @@ -893,7 +904,7 @@ function getOrganizationAccounts(listAccounts, accountId) { if (listAccounts.data && listAccounts.data.length){ listAccounts.data.forEach(account => { if (account.Id && account.Id !== accountId) orgAccountIds.push(account.Id); - }); + }); } return orgAccountIds; @@ -903,7 +914,7 @@ function getUsedSecurityGroups(cache, results, region) { let result = []; const describeNetworkInterfaces = helpers.addSource(cache, {}, ['ec2', 'describeNetworkInterfaces', region]); - + if (!describeNetworkInterfaces || describeNetworkInterfaces.err || !describeNetworkInterfaces.data) { helpers.addResult(results, 3, 'Unable to query for network interfaces: ' + helpers.addError(describeNetworkInterfaces), region); @@ -912,7 +923,7 @@ function getUsedSecurityGroups(cache, results, region) { const listFunctions = helpers.addSource(cache, {}, ['lambda', 'listFunctions', region]); - + if (!listFunctions || listFunctions.err || !listFunctions.data) { helpers.addResult(results, 3, 'Unable to list lambda functions: ' + helpers.addError(listFunctions), region); @@ -967,7 +978,7 @@ function getSubnetRTMap(subnets, routeTables) { }); } if (routeTable.VpcId && routeTable.RouteTableId && routeTable.Associations && - routeTable.Associations.find(association => association.Main) && !vpcRTMap[routeTable.VpcId]) vpcRTMap[routeTable.VpcId] = routeTable.RouteTableId; + routeTable.Associations.find(association => association.Main) && !vpcRTMap[routeTable.VpcId]) vpcRTMap[routeTable.VpcId] = routeTable.RouteTableId; }); subnets.forEach(subnet => { @@ -1023,6 +1034,7 @@ var debugApiCalls = function(call, service, debugMode, finished) { }; var logError = function(service, call, region, err, errorsLocal, apiCallErrorsLocal, apiCallTypeErrorsLocal, totalApiCallErrorsLocal, errorSummaryLocal, errorTypeSummaryLocal, debugMode) { + if (debugMode) console.log(`[INFO] ${service}:${call} returned error: ${err.message}`); totalApiCallErrorsLocal++; if (!errorSummaryLocal[service]) errorSummaryLocal[service] = {}; @@ -1112,7 +1124,7 @@ function processFieldSelectors(fieldSelectors,buckets ,startsWithBuckets,notEnds var checkTags = function(cache, resourceName, resourceList, region, results, settings={}) { const allResources = helpers.addSource(cache, {}, ['resourcegroupstaggingapi', 'getResources', region]); - + if (!allResources || allResources.err || !allResources.data) { helpers.addResult(results, 3, 'Unable to query all resources from group tagging api:' + helpers.addError(allResources), region); @@ -1128,7 +1140,7 @@ var checkTags = function(cache, resourceName, resourceList, region, results, set }); resourceList.map(arn => { - if (filteredResourceARN.includes(arn)) { + if (filteredResourceARN.includes(arn)) { helpers.addResult(results, 0, `${resourceName} has tags`, region, arn); } else { helpers.addResult(results, 2, `${resourceName} does not have any tags`, region, arn); @@ -1136,6 +1148,134 @@ var checkTags = function(cache, resourceName, resourceList, region, results, set }); }; +function checkSecurityGroup(securityGroup, cache, region) { + let allowsAllTraffic; + for (var p in securityGroup.IpPermissions) { + var permission = securityGroup.IpPermissions[p]; + + for (var k in permission.IpRanges) { + var range = permission.IpRanges[k]; + + if (range.CidrIp === '0.0.0.0/0') { + allowsAllTraffic = true; + } + } + + for (var l in permission.Ipv6Ranges) { + var rangeV6 = permission.Ipv6Ranges[l]; + + if (rangeV6.CidrIpv6 === '::/0') { + allowsAllTraffic = true; + } + } + } + + if (allowsAllTraffic) { + return checkNetworkInterface(securityGroup.GroupId, securityGroup.GroupName, '', region, null, securityGroup, cache, true); + } + return false; +} + +var checkNetworkExposure = function(cache, source, subnetId, securityGroups, region, results) { + + var internetExposed = ''; + + // Scenario 1: check if resource is in a private subnet + let subnetRouteTableMap, privateSubnets; + var describeSubnets = helpers.addSource(cache, source, + ['ec2', 'describeSubnets', region]); + var describeRouteTables = helpers.addSource(cache, {}, + ['ec2', 'describeRouteTables', region]); + + if (!describeRouteTables || describeRouteTables.err || !describeRouteTables.data) { + helpers.addResult(results, 3, + 'Unable to query for route tables: ' + helpers.addError(describeRouteTables), region); + } else if (!describeSubnets || describeSubnets.err || !describeSubnets.data) { + helpers.addResult(results, 3, + 'Unable to query for subnets: ' + helpers.addError(describeSubnets), region); + } else if (describeSubnets.data.length && subnetId) { + subnetRouteTableMap = getSubnetRTMap(describeSubnets.data, describeRouteTables.data); + privateSubnets = getPrivateSubnets(subnetRouteTableMap, describeSubnets.data, describeRouteTables.data); + if (privateSubnets && privateSubnets.length && privateSubnets.find(subnet => subnet === subnetId)) { + return ''; + } + // If the subnet is not private we will check if security groups and Network ACLs allow internal traffic + } + + // Scenario 2: check if security group allows all traffic + var describeSecurityGroups = helpers.addSource(cache, source, + ['ec2', 'describeSecurityGroups', region]); + + + if (!describeSecurityGroups || describeSecurityGroups.err || !describeSecurityGroups.data) { + helpers.addResult(results, 3, + 'Unable to query for security groups: ' + helpers.addError(describeSecurityGroups), region); + } else if (describeSecurityGroups.data.length && securityGroups && securityGroups.length) { + let instanceSGs = describeSecurityGroups.data.filter(sg => securityGroups.find(isg => isg.GroupId === sg.GroupId)); + for (var group of instanceSGs) { + let exposedSG = checkSecurityGroup(group, cache, region); + if (!exposedSG) { + return ''; + } else { + internetExposed += exposedSG; + } + } + } + + + + // Scenario 3: check if Network ACLs associated with the resource allow all traffic + var describeNetworkAcls = helpers.addSource(cache, source, + ['ec2', 'describeNetworkAcls', region]); + + if (!describeNetworkAcls || describeNetworkAcls.err || !describeNetworkAcls.data) { + helpers.addResult(results, 3, + `Unable to query for Network ACLs: ${helpers.addError(describeNetworkAcls)}`, region); + } else if (describeNetworkAcls.data.length && subnetId) { + let instanceACL = describeNetworkAcls.data.find(acl => acl.Associations.find(assoc => assoc.SubnetId === subnetId)); + if (instanceACL && instanceACL.Entries && instanceACL.Entries.length) { + + const allowRules = instanceACL.Entries.filter(entry => + entry.Egress === false && + entry.RuleAction === 'allow' && + (entry.CidrBlock === '0.0.0.0/0' || entry.Ipv6CidrBlock === '::/0') + ); + + + // Checking if there's a deny rule with lower rule number + let exposed = allowRules.some(allowRule => { + // Check if there's a deny with a lower rule number + return !instanceACL.Entries.some(denyRule => { + return ( + denyRule.Egress === false && + denyRule.RuleAction === 'deny' && + ( + (allowRule.CidrBlock && denyRule.CidrBlock === allowRule.CidrBlock) || + (allowRule.Ipv6CidrBlock && denyRule.Ipv6CidrBlock === allowRule.Ipv6CidrBlock) + ) && + denyRule.Protocol === allowRule.Protocol && + ( + denyRule.PortRange ? + (allowRule.PortRange && + denyRule.PortRange.From === allowRule.PortRange.From && + denyRule.PortRange.To === allowRule.PortRange.To) : true + ) && + denyRule.RuleNumber < allowRule.RuleNumber + ); + }); + }); + if (exposed) { + internetExposed += `> nacl ${instanceACL.NetworkAclId}`; + } else { + internetExposed = ''; + } + } + + } + + return internetExposed; +}; + module.exports = { addResult: addResult, findOpenPorts: findOpenPorts, @@ -1173,4 +1313,6 @@ module.exports = { checkConditions: checkConditions, processFieldSelectors: processFieldSelectors, checkNetworkInterface: checkNetworkInterface, -}; \ No newline at end of file + checkNetworkExposure: checkNetworkExposure, +}; + diff --git a/helpers/azure/functions.js b/helpers/azure/functions.js index 3b8261074f..66e7f488bd 100644 --- a/helpers/azure/functions.js +++ b/helpers/azure/functions.js @@ -392,16 +392,16 @@ function checkFlexibleServerConfigs(servers, cache, source, location, results, s } function checkMicrosoftDefender(pricings, serviceName, serviceDisplayName, results, location ) { - + let pricingData = pricings.data.find((pricing) => pricing.name.toLowerCase() === serviceName); if (pricingData) { if (pricingData.pricingTier.toLowerCase() === 'standard') { - addResult(results, 0, `Azure Defender is enabled for ${serviceDisplayName}`, location, pricingData.id); + addResult(results, 0, `Azure Defender is enabled for ${serviceDisplayName}`, location, pricingData.id); } else { - addResult(results, 2, `Azure Defender is not enabled for ${serviceDisplayName}`, location, pricingData.id); + addResult(results, 2, `Azure Defender is not enabled for ${serviceDisplayName}`, location, pricingData.id); } } else { - addResult(results, 2, `Azure Defender is not enabled for ${serviceDisplayName}`, location); + addResult(results, 2, `Azure Defender is not enabled for ${serviceDisplayName}`, location); } } @@ -612,12 +612,12 @@ function remediateOpenPorts(putCall, pluginName, protocol, port, config, cache, sourceAddressArr.push(settings.input[inputKey]); sourceAddressArr.splice(sourceAddressArr.indexOf(publicString), 1); - // this if the input specified already exists + // this if the input specified already exists } else if (settings.input && settings.input[inputKey] && sourceAddressArr.indexOf(settings.input[inputKey]) > -1) { ipType === 'ipv4' ? localIpExists = true : localIpV6Exists = true; sourceAddressArr.splice(sourceAddressArr.indexOf(publicString), 1); - // this is if there is no input and the failing port is in an array (destinationPortRanges). Will remove the port from the array + // this is if there is no input and the failing port is in an array (destinationPortRanges). Will remove the port from the array } else if ((!settings.input || !settings.input[inputKey]) && (failingRulePortIndex[failingPermission.name]) && !spliced) { spliced = true; failingPermission.properties['destinationPortRanges'].splice([failingRulePortIndex[failingPermission.name]], 1); @@ -741,6 +741,56 @@ function remediateOpenPorts(putCall, pluginName, protocol, port, config, cache, }); } +function checkSecurityGroup(securityGroups) { + var openPrefix = ['*', '0.0.0.0', '0.0.0.0/0', '', '/0', '::/0', 'internet']; + + const allRules = securityGroups.flatMap(nsg => + [ + ...nsg.securityRules?.map(rule => ({ + ...rule, + nsgName: nsg.name + })), + ...(nsg.defaultSecurityRules?.map(rule => ({ + ...rule, + nsgName: nsg.name + })) || []) + ] + ); + + // sorting by priority + const sortedRules = allRules.sort((a, b) => a.properties.priority - b.properties.priority); + + // The most restrictive rule takes precedence + for (const rule of sortedRules) { + if (rule.properties.direction === "Inbound" && openPrefix.includes(rule.properties.sourceAddressPrefix)) { + if (rule.properties.access === "Deny") { + return {exposed: false}; + } + if (rule.properties.access === "Allow") { + return {exposed: true, nsg: rule.nsgName}; + } + } + } + + return {exposed: true}; +} + +function checkNetworkExposure(cache, source, networkInterfaces, securityGroups, region, results) { + let exposedPath = ''; + + if (securityGroups && securityGroups.length) { + // Scenario 1: check if security group allow all inbound traffic + let exposedSG = checkSecurityGroup(securityGroups); + if (exposedSG && exposedSG.exposed) { + if (exposedSG.nsg) { + exposedPath += `nsg ${exposedSG.nsg}` + } + } + + return exposedPath + } +} + module.exports = { addResult: addResult, findOpenPorts: findOpenPorts, @@ -753,6 +803,7 @@ module.exports = { remediateOpenPorts: remediateOpenPorts, remediateOpenPortsHelper: remediateOpenPortsHelper, checkMicrosoftDefender: checkMicrosoftDefender, - checkFlexibleServerConfigs:checkFlexibleServerConfigs + checkFlexibleServerConfigs: checkFlexibleServerConfigs, + checkNetworkExposure: checkNetworkExposure, }; diff --git a/helpers/google/functions.js b/helpers/google/functions.js index ba1c667897..eb20486c7c 100644 --- a/helpers/google/functions.js +++ b/helpers/google/functions.js @@ -365,7 +365,7 @@ function checkOrgPolicy(orgPolicies, constraintName, constraintType, shouldBeEna } else { isEnabled = ifNotFound; } - } + } let successMessage = `"${displayName}" constraint is enforced at the organization level.`; let failureMessage = `"${displayName}" constraint is not enforced at the organization level.`; let status, message; @@ -402,6 +402,53 @@ function checkIAMRole(iamPolicy, roles, region, results, project, notFoundMessag } } +function checkFirewallRules(firewallRules) { + firewallRules.sort((a, b) => (a.priority || 1000) - (b.priority || 1000)); + + for (const firewallRule of firewallRules) { + if (firewallRule.direction !== 'INGRESS' || firewallRule.disabled) { + continue; + } + + const networkName = firewallRule.network ? firewallRule.network.split('/').pop() : ''; + + let allSources = firewallRule.sourceRanges?.some(sourceAddressPrefix => + sourceAddressPrefix === '*' || + sourceAddressPrefix === '0.0.0.0/0' || + sourceAddressPrefix === '::/0' || + sourceAddressPrefix.includes('/0') || + sourceAddressPrefix.toLowerCase() === 'internet' || + sourceAddressPrefix.includes('/0') + ); + + if (allSources && firewallRule.allowed?.some(allow => !!allow.IPProtocol)) { + return {exposed: true, networkName: `vpc ${networkName}`}; + } + + if (allSources && firewallRule.denied?.some(deny => deny.IPProtocol === 'all')) { + return {exposed: false}; + } + } + + return {exposed: true}; + + +} + +function checkNetworkExposure(cache, source, networks, firewallRules, region, results) { + let exposedPath = ''; + + if (firewallRules && firewallRules.length) { + // Scenario 1: check if any firewall rule allows all inbound traffic + let isExposed = checkFirewallRules(firewallRules); + if (isExposed.exposed) { + if (isExposed.networkName) { + return isExposed.networkName; + } + } + } + return exposedPath +} module.exports = { addResult: addResult, findOpenPorts: findOpenPorts, @@ -413,5 +460,6 @@ module.exports = { createResourceName: createResourceName, checkOrgPolicy: checkOrgPolicy, checkIAMRole: checkIAMRole, - findOpenAllPortsEgress: findOpenAllPortsEgress + findOpenAllPortsEgress: findOpenAllPortsEgress, + checkNetworkExposure: checkNetworkExposure }; diff --git a/helpers/shared.js b/helpers/shared.js index 6c2a4ca572..f230eb3c4f 100644 --- a/helpers/shared.js +++ b/helpers/shared.js @@ -92,14 +92,14 @@ var processIntegration = function(serviceName, settings, collection, calls, post }; var processIntegrationAdditionalData = function(serviceName, localSettings, localCollection, calls, postcalls, localEventCollection, callback){ - if (localCollection == undefined || - (localCollection && - (JSON.stringify(localCollection)==='{}' || - localCollection[serviceName.toLowerCase()] == undefined || - JSON.stringify(localCollection[serviceName.toLowerCase()])==='{}'))) { + if (!localCollection || + !Object.keys(localCollection).length || + !localCollection[serviceName.toLowerCase()] || + !Object.keys(localCollection[serviceName.toLowerCase()]).length) { return callback(null); } + let callsMap = calls[serviceName] ? Object.keys(calls[serviceName]) : null; let foundData=[]; diff --git a/plugins/alibaba/securitycenter/securityCenterEdition.js b/plugins/alibaba/securitycenter/securityCenterEdition.js index eaf4804d72..254d116da1 100644 --- a/plugins/alibaba/securitycenter/securityCenterEdition.js +++ b/plugins/alibaba/securitycenter/securityCenterEdition.js @@ -1,4 +1,5 @@ var helpers = require('../../../helpers/alibaba'); +const async = require('async'); module.exports = { title: 'Security Center Edition', @@ -6,7 +7,7 @@ module.exports = { domain: 'Management and Governance', severity: 'Medium', description: 'Ensure that your cloud Security Center edition is Advanced or plus.', - more_info: 'Premium Security Center editions like Advanced or Enterprise Edition provides crucial features liekthreat detection for network and endpoints, ' + + more_info: 'Premium Security Center editions like Advanced or Enterprise Edition provides crucial features liekthreat detection for network and endpoints, ' + 'providing malware detection, webshell detection and anomaly detection in Security Center.', link: 'https://www.alibabacloud.com/help/product/28498.htm', recommended_action: 'Upgrade your Security Center edition to at least Advanced.', @@ -15,7 +16,7 @@ module.exports = { run: function(cache, settings, callback) { var results = []; var source = {}; - var region = helpers.defaultRegion(settings); + var regions = helpers.regions(settings); // Below map might not be accurate as I checked with Anti-virus and Advanced editions and API is returning // 6 and 5 respectively against the version key. As it will be costly to try all editions to get the acrual @@ -29,29 +30,32 @@ module.exports = { 5: 'Advanced', 6: 'Anti-virus' }; - - var describeVersionConfig = helpers.addSource(cache, source, - ['tds', 'DescribeVersionConfig', region]); - - if (!describeVersionConfig) { - return callback(null, results, source); - } - - if (describeVersionConfig.err || !describeVersionConfig.data) { - helpers.addResult(results, 3, - `Unable to query Security Center version config: ${helpers.addError(describeVersionConfig)}`, - region); - return callback(null, results, source); - } - - let securityVersion = describeVersionConfig.data.Version ? describeVersionConfig.data.Version : 1; - - if (securityVersion == 1 || securityVersion == 6) { - helpers.addResult(results, 2, `Security Center edition is ${versionIdNameMap[securityVersion]}`, region); - } else { - helpers.addResult(results, 0, `Security Center edition is ${versionIdNameMap[securityVersion]}`, region); - } - - callback(null, results, source); + async.each(regions.tds, function(region, rcb) { + var describeVersionConfig = helpers.addSource(cache, source, + ['tds', 'DescribeVersionConfig', region]); + + if (!describeVersionConfig) { + return rcb(); + } + + if (describeVersionConfig.err || !describeVersionConfig.data) { + helpers.addResult(results, 3, + `Unable to query Security Center version config: ${helpers.addError(describeVersionConfig)}`, + region); + return rcb(); + } + + let securityVersion = describeVersionConfig.data.Version ? describeVersionConfig.data.Version : 1; + + if (securityVersion == 1 || securityVersion == 6) { + helpers.addResult(results, 2, `Security Center edition is ${versionIdNameMap[securityVersion]}`, region); + } else { + helpers.addResult(results, 0, `Security Center edition is ${versionIdNameMap[securityVersion]}`, region); + } + + rcb(); + }, function(){ + callback(null, results, source); + }); } -}; \ No newline at end of file +}; diff --git a/plugins/aws/ec2/ec2NetworkExposure.js b/plugins/aws/ec2/ec2NetworkExposure.js new file mode 100644 index 0000000000..c86c247c24 --- /dev/null +++ b/plugins/aws/ec2/ec2NetworkExposure.js @@ -0,0 +1,61 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'Network Exposure', + category: 'EC2', + domain: 'Compute', + severity: 'Info', + description: 'Check if EC2 instances are exposed to the internet.', + more_info: 'EC2 instances exposed to the internet are at a higher risk of unauthorized access, data breaches, and cyberattacks. It’s crucial to limit exposure by securing access through proper configuration of security groups, NACLs, and route tables.', + link: 'https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Security.html', + recommended_action: 'Secure EC2 instances by restricting access with properly configured security groups and NACLs.', + apis: ['EC2:describeInstances', 'EC2:describeNetworkAcls', 'EC2:describeSecurityGroups', 'EC2:describeNetworkInterfaces', 'EC2:describeSubnets', 'EC2:describeRouteTables'], + realtime_triggers: ['ec2:RunInstances','ec2:TerminateInstances', 'ec2:CreateNetworkAcl', 'ec2:ReplaceNetworkAclEntry', 'ec2:ReplaceNetworkAclAssociation', + 'ec2:DeleteNetworkAcl', 'ec2:CreateSecurityGroup', 'ec2:AuthorizeSecurityGroupIngress','ec2:ModifySecurityGroupRules','ec2:RevokeSecurityGroupIngress', + 'ec2:DeleteSecurityGroup', 'ec2:ModifyInstanceAttribute', 'ec2:ModifySubnetAttribute'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + var awsOrGov = helpers.defaultPartition(settings); + + async.each(regions.ec2, function(region, rcb){ + var describeInstances = helpers.addSource(cache, source, + ['ec2', 'describeInstances', region]); + + if (!describeInstances) return rcb(); + + if (describeInstances.err || !describeInstances.data) { + helpers.addResult(results, 3, + 'Unable to query for instances: ' + helpers.addError(describeInstances), region); + return rcb(); + } + + if (!describeInstances.data.length) { + helpers.addResult(results, 0, 'No instances found', region); + return rcb(); + } + + for (var instances of describeInstances.data){ + const { OwnerId } = instances; + for (var instance of instances.Instances) { + const { InstanceId } = instance; + const arn = `arn:${awsOrGov}:ec2:${region}:${OwnerId}:instance/${InstanceId}`; + + let internetExposed = helpers.checkNetworkExposure(cache, source, instance.SubnetId, instance.SecurityGroups, region, results); + if (internetExposed && internetExposed.length) { + helpers.addResult(results, 2, `EC2 instance is exposed to the internet through ${internetExposed}`, region, arn); + } else { + helpers.addResult(results, 0, 'EC2 instance is not exposed to the internet', region, arn); + } + } + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; diff --git a/plugins/aws/eks/eksKubernetesVersion.spec.js b/plugins/aws/eks/eksKubernetesVersion.spec.js index b53206f8d2..0997f85358 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.27", + "version": "1.29", } } ); diff --git a/plugins/aws/elbv2/elbv2UnhealthyInstance.js b/plugins/aws/elbv2/elbv2UnhealthyInstance.js index 3d7ff74573..e7b1acf66a 100644 --- a/plugins/aws/elbv2/elbv2UnhealthyInstance.js +++ b/plugins/aws/elbv2/elbv2UnhealthyInstance.js @@ -37,27 +37,27 @@ module.exports = { } describeLoadBalancers.data.forEach(function(lb) { - var resource = describeLoadBalancers.LoadBalancerArn; + var resource = lb.LoadBalancerArn; var unhealthyInstances = 0; var describeTargetGroups = helpers.addSource(cache, source, ['elbv2', 'describeTargetGroups', region, lb.DNSName]); - + if (!describeTargetGroups || describeTargetGroups.err || !describeTargetGroups.data) { helpers.addResult(results, 3, `Unable to query for Application/Network load balancer target groups: ${helpers.addError(describeTargetGroups)}`, region, resource); return; } - + if (!describeTargetGroups.data.TargetGroups || !describeTargetGroups.data.TargetGroups.length) { helpers.addResult(results, 2, 'No Application/Network load balancer target groups found', region, resource); return; } - + describeTargetGroups.data.TargetGroups.forEach(function(tg) { var describeTargetHealth = helpers.addSource(cache, source, ['elbv2', 'describeTargetHealth', region, tg.TargetGroupArn]); - + if (!describeTargetHealth || describeTargetHealth.err || !describeTargetHealth.data || !describeTargetHealth.data.TargetHealthDescriptions || !describeTargetHealth.data.TargetHealthDescriptions.length) { return; @@ -81,10 +81,10 @@ module.exports = { region, resource); } }); - + rcb(); }, function(){ callback(null, results, source); }); } -}; \ No newline at end of file +}; diff --git a/plugins/aws/elbv2/elbv2WafEnabled.js b/plugins/aws/elbv2/elbv2WafEnabled.js index d9f67c5ad1..f238e2805d 100644 --- a/plugins/aws/elbv2/elbv2WafEnabled.js +++ b/plugins/aws/elbv2/elbv2WafEnabled.js @@ -12,7 +12,7 @@ module.exports = { recommended_action: '1. Enter the WAF service. 2. Enter Web ACLs and filter by the region the Application Load Balancer is in. 3. If no Web ACL is found, Create a new Web ACL in the region the ALB resides and in Resource type to associate with web ACL, select the Load Balancer. ', apis: ['ELBv2:describeLoadBalancers', 'WAFV2:listWebACLs', 'WAFRegional:listWebACLs', 'WAFV2:listResourcesForWebACL', 'WAFRegional:listResourcesForWebACL'], realtime_triggers: ['elasticloadbalancing:CreateLoadBalancer', 'wafv2:CreateWebAcl', 'wafv2:UpdateWebAcl', 'wafregional:CreateWebAcl', 'wafregional:UpdateWebAcl', 'wafv2:DeleteWebAcl', 'wafregional:DeleteWebAcl'], - + run: function(cache, settings, callback) { var results = []; var source = {}; @@ -83,15 +83,25 @@ module.exports = { return lcb(); } + var appElbFound = false; + loadBalancers.data.forEach(loadBalancer => { - if (loadBalancer.LoadBalancerArn && (resourcesToCheck.indexOf(loadBalancer.LoadBalancerArn) > -1)) { - resourcesToCheck.splice(resourcesToCheck.indexOf(loadBalancer.LoadBalancerArn), 1); - helpers.addResult(results, 0, 'The Application Load Balancer has WAF enabled', loc, loadBalancer.LoadBalancerArn); - } else { - helpers.addResult(results, 2, 'The Application Load Balancer does not have WAF enabled', loc, loadBalancer.LoadBalancerArn); + if (loadBalancer.Type && + loadBalancer.Type.toLowerCase() === 'application') { + appElbFound = true; + if (loadBalancer.LoadBalancerArn && (resourcesToCheck.indexOf(loadBalancer.LoadBalancerArn) > -1)) { + resourcesToCheck.splice(resourcesToCheck.indexOf(loadBalancer.LoadBalancerArn), 1); + helpers.addResult(results, 0, 'The Application Load Balancer has WAF enabled', loc, loadBalancer.LoadBalancerArn); + } else { + helpers.addResult(results, 2, 'The Application Load Balancer does not have WAF enabled', loc, loadBalancer.LoadBalancerArn); + } } }); + if (!appElbFound) { + helpers.addResult(results, 0, 'No Application Load Balancers found', loc); + } + lcb(); }, function() { callback(null, results, source); diff --git a/plugins/aws/iam/iamMasterManagerRoles.js b/plugins/aws/iam/iamMasterManagerRoles.js index 153461e679..1bf9f4f532 100644 --- a/plugins/aws/iam/iamMasterManagerRoles.js +++ b/plugins/aws/iam/iamMasterManagerRoles.js @@ -202,7 +202,7 @@ module.exports = { var getRolePolicy = helpers.addSource(cache, source, ['iam', 'getRolePolicy', region, role.RoleName]); - if (listRolePolicies.err || !listRolePolicies.data || !listRolePolicies.data.PolicyNames) { + if (!listRolePolicies || listRolePolicies.err || !listRolePolicies.data || !listRolePolicies.data.PolicyNames) { helpers.addResult(results, 3, 'Unable to query for IAM role policy for role: ' + role.RoleName + ': ' + helpers.addError(listRolePolicies), 'global', role.Arn); return cb(); diff --git a/plugins/aws/securityhub/securityHubActiveFindings.js b/plugins/aws/securityhub/securityHubActiveFindings.js index 6c1cea3b12..30f9d165e4 100644 --- a/plugins/aws/securityhub/securityHubActiveFindings.js +++ b/plugins/aws/securityhub/securityHubActiveFindings.js @@ -46,13 +46,13 @@ module.exports = { if (!getFindings) { helpers.addResult(results, 0, 'No active findings available', region, resource); return rcb(); - } else if (getFindings.err || !getFindings.data || !getFindings.data.Findings) { + } else if (getFindings.err || !getFindings.data ) { helpers.addResult(results, 3, `Unable to get SecurityHub findings: ${helpers.addError(getFindings)}`, region, resource); - } else if (!getFindings.data.Findings.length) { + } else if (!getFindings.data.length) { helpers.addResult(results, 0, 'No active findings available', region, resource); return rcb(); } else { - let activeFindings = getFindings.data.Findings.filter(finding => finding.CreatedAt && + let activeFindings = getFindings.data.filter(finding => finding.CreatedAt && helpers.hoursBetween(new Date, finding.CreatedAt) > config.securityhub_findings_fail); let status = (activeFindings && activeFindings.length) ? 2 : 0; diff --git a/plugins/aws/securityhub/securityHubActiveFindings.spec.js b/plugins/aws/securityhub/securityHubActiveFindings.spec.js index bbbe5c55d2..7ddb72010c 100644 --- a/plugins/aws/securityhub/securityHubActiveFindings.spec.js +++ b/plugins/aws/securityhub/securityHubActiveFindings.spec.js @@ -12,51 +12,22 @@ const describeHub = { const getFindings = [ { - "Findings": [ - { - 'AwsAccountId':'123456', - 'CompanyName':'AWS', - 'CreatedAt': new Date(), - 'Description': 'Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Routing tables are used to route network traffic between subnets and to network gateways. It is recommended that a metric filter and alarm be established for changes to route tables.', - }, - { - 'AwsAccountId':'123456', - 'CompanyName':'AWS', - 'CreatedAt': failDate, - 'Description': 'Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Routing tables are used to route network traffic between subnets and to network gateways. It is recommended that a metric filter and alarm be established for changes to route tables.', - }, - { - 'AwsAccountId':'123456', - 'CompanyName':'AWS', - 'CreatedAt': new Date(), - 'Description': 'Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Routing tables are used to route network traffic between subnets and to network gateways. It is recommended that a metric filter and alarm be established for changes to route tables.', - } - ] + 'AwsAccountId':'123456', + 'CompanyName':'AWS', + 'CreatedAt': new Date(), + 'Description': 'Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Routing tables are used to route network traffic between subnets and to network gateways. It is recommended that a metric filter and alarm be established for changes to route tables.', }, { - "Findings": [ - { - 'AwsAccountId':'123456', - 'CompanyName':'AWS', - 'CreatedAt': new Date(), - 'Description': 'Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Routing tables are used to route network traffic between subnets and to network gateways. It is recommended that a metric filter and alarm be established for changes to route tables.', - }, - { - 'AwsAccountId':'123456', - 'CompanyName':'AWS', - 'CreatedAt': new Date(), - 'Description': 'Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Routing tables are used to route network traffic between subnets and to network gateways. It is recommended that a metric filter and alarm be established for changes to route tables.', - }, - { - 'AwsAccountId':'123456', - 'CompanyName':'AWS', - 'CreatedAt': new Date(), - 'Description': 'Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Routing tables are used to route network traffic between subnets and to network gateways. It is recommended that a metric filter and alarm be established for changes to route tables.', - } - ] + 'AwsAccountId':'123456', + 'CompanyName':'AWS', + 'CreatedAt': failDate, + 'Description': 'Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Routing tables are used to route network traffic between subnets and to network gateways. It is recommended that a metric filter and alarm be established for changes to route tables.', }, { - "Findings": [] + 'AwsAccountId':'123456', + 'CompanyName':'AWS', + 'CreatedAt': new Date(), + 'Description': 'Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms. Routing tables are used to route network traffic between subnets and to network gateways. It is recommended that a metric filter and alarm be established for changes to route tables.', } ] @@ -109,7 +80,7 @@ describe('securityHubActiveFindings', function () { }); it('should PASS if Security Hub has no active findings', function (done) { - const cache = createCache(describeHub, null, getFindings[2]); + const cache = createCache(describeHub, null, []); securityHubActiveFindings.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); @@ -120,7 +91,7 @@ describe('securityHubActiveFindings', function () { }); it('should PASS if Security Hub has zero active findings', function (done) { - const cache = createCache(describeHub, null, getFindings[1]); + const cache = createCache(describeHub, null, [getFindings[0]]); securityHubActiveFindings.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); @@ -131,7 +102,7 @@ describe('securityHubActiveFindings', function () { }); it('should FAIL if Security Hub has active findings', function (done) { - const cache = createCache(describeHub, null, getFindings[0]); + const cache = createCache(describeHub, null, [getFindings[1]]); securityHubActiveFindings.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); diff --git a/plugins/azure/appservice/authEnabled.js b/plugins/azure/appservice/authEnabled.js index e022e5713d..a50f69d139 100644 --- a/plugins/azure/appservice/authEnabled.js +++ b/plugins/azure/appservice/authEnabled.js @@ -22,12 +22,24 @@ module.exports = { 'for auditing and security controls.', pci: 'Access to system components must be restricted to known users.' }, + settings: { + whitelist_functions_for_auth_enabled: { + name: 'Whitelist Functions For Authentication Enabled', + description: 'List of comma separated functions which should be whitelisted to check', + regex: '^.*$', + default: 'aqua-agentless-scanner-continuous-onboarding', + } + }, run: function(cache, settings, callback) { const results = []; const source = {}; const locations = helpers.locations(settings.govcloud); + let config = { + whitelist_functions_for_auth_enabled: settings.whitelist_functions_for_auth_enabled || this.settings.whitelist_functions_for_auth_enabled.default + }; + async.each(locations.webApps, function(location, rcb) { const webApps = helpers.addSource( @@ -51,19 +63,24 @@ module.exports = { webApps.data.forEach(function(webApp) { if (webApp.kind && webApp.kind.includes('workflowapp')) return; - const authSettings = helpers.addSource( - cache, source, ['webApps', 'getAuthSettings', location, webApp.id] - ); - - if (!authSettings || authSettings.err || !authSettings.data) { - helpers.addResult(results, 3, - 'Unable to query App Service: ' + helpers.addError(authSettings), - location, webApp.id); + if (webApp.name.includes(config.whitelist_functions_for_auth_enabled)) { + helpers.addResult(results, 0, 'The App Service is whitelisted', location, webApp.id); } else { - if (authSettings.data.enabled) { - helpers.addResult(results, 0, 'App Service has App Service Authentication enabled', location, webApp.id); + + const authSettings = helpers.addSource( + cache, source, ['webApps', 'getAuthSettings', location, webApp.id] + ); + + if (!authSettings || authSettings.err || !authSettings.data) { + helpers.addResult(results, 3, + 'Unable to query App Service: ' + helpers.addError(authSettings), + location, webApp.id); } else { - helpers.addResult(results, 2, 'App Service does not have App Service Authentication enabled', location, webApp.id); + if (authSettings.data.enabled) { + helpers.addResult(results, 0, 'App Service has App Service Authentication enabled', location, webApp.id); + } else { + helpers.addResult(results, 2, 'App Service does not have App Service Authentication enabled', location, webApp.id); + } } } }); diff --git a/plugins/azure/appservice/authEnabled.spec.js b/plugins/azure/appservice/authEnabled.spec.js index f2b88ffc38..eeafd97039 100644 --- a/plugins/azure/appservice/authEnabled.spec.js +++ b/plugins/azure/appservice/authEnabled.spec.js @@ -71,6 +71,41 @@ describe('authEnabled', function() { auth.run(cache, {}, callback); }); + it('should give passing result if App Service is whitelisted', function(done) { + const callback = (err, results) => { + expect(results.length).to.equal(1) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('App Service is whitelisted') + expect(results[0].region).to.equal('eastus') + done() + }; + + const cache = createCache( + null, + [ + { + "id": "/subscriptions/abcdef-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/devresourcegroup/providers/Microsoft.Web/sites/aqua-agentless-scanner-continuous-onboarding-i2hxc3is", + "name": "aqua-agentless-scanner-continuous-onboarding-i2hxc3is", + "type": "Microsoft.Web/sites", + "kind": "app,linux,container", + "location": "East US", + "state": "Running" + } + ], + { + "/subscriptions/abcdef-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/devresourcegroup/providers/Microsoft.Web/sites/test-webapp": { + "data": { + "name": "authsettings", + "type": "Microsoft.Web/sites/config", + "enabled": false + } + } + } + ); + + auth.run(cache, {whitelist_functions_for_auth_enabled: 'aqua-agentless-scanner-continuous-onboarding'}, callback); + }); + it('should give passing result if enabled App Service', function(done) { const callback = (err, results) => { expect(results.length).to.equal(1) @@ -138,4 +173,4 @@ describe('authEnabled', function() { auth.run(cache, {}, callback); }); }) -}) \ No newline at end of file +}) diff --git a/plugins/azure/appservice/httpsOnlyEnabled.js b/plugins/azure/appservice/httpsOnlyEnabled.js index 2f15c12d17..eb9400604f 100644 --- a/plugins/azure/appservice/httpsOnlyEnabled.js +++ b/plugins/azure/appservice/httpsOnlyEnabled.js @@ -26,12 +26,24 @@ module.exports = { 'App Service HTTPS redirection should be used to ensure site visitors ' + 'are always connecting over a secure channel.' }, + settings: { + whitelist_functions_for_https_only: { + name: 'Whitelist Functions For HTTPS Only', + description: 'List of comma separated functions which should be whitelisted to check', + regex: '^.*$', + default: 'aqua-agentless-scanner-continuous-onboarding', + } + }, run: function(cache, settings, callback) { const results = []; const source = {}; const locations = helpers.locations(settings.govcloud); + let config = { + whitelist_functions_for_https_only: settings.whitelist_functions_for_https_only || this.settings.whitelist_functions_for_https_only.default + }; + async.each(locations.webApps, function(location, rcb) { const webApps = helpers.addSource( @@ -52,10 +64,16 @@ module.exports = { } webApps.data.forEach(function(webApp) { - if (webApp.httpsOnly) { - helpers.addResult(results, 0, 'The App Service has HTTPS Only enabled', location, webApp.id); + + if (webApp.name.includes(config.whitelist_functions_for_https_only)) { + helpers.addResult(results, 0, 'The App Service is whitelisted', location, webApp.id); } else { - helpers.addResult(results, 2, 'The App Service does not have HTTPS Only enabled', location, webApp.id); + + if (webApp.httpsOnly) { + helpers.addResult(results, 0, 'The App Service has HTTPS Only enabled', location, webApp.id); + } else { + helpers.addResult(results, 2, 'The App Service does not have HTTPS Only enabled', location, webApp.id); + } } }); diff --git a/plugins/azure/appservice/httpsOnlyEnabled.spec.js b/plugins/azure/appservice/httpsOnlyEnabled.spec.js index 79feef203f..3aed7bb557 100644 --- a/plugins/azure/appservice/httpsOnlyEnabled.spec.js +++ b/plugins/azure/appservice/httpsOnlyEnabled.spec.js @@ -11,6 +11,11 @@ const webApps = [ 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/app1', 'name': 'app1', 'httpsOnly': false + }, + { + 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/aqua-agentless-scanner-continuous-onboarding-i2hxc3is', + 'name': 'aqua-agentless-scanner-continuous-onboarding-i2hxc3is', + 'httpsOnly': false } ]; @@ -81,5 +86,16 @@ describe('httpsOnlyEnabled', function() { done(); }); }); + + it('should PASS if app service gets whitelisted', function (done) { + const cache = createCache([webApps[2]]); + httpsOnlyEnabled.run(cache, { whitelist_functions_for_https_only:'aqua-agentless-scanner-continuous-onboarding' }, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('The App Service is whitelisted'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); }); -}); \ No newline at end of file +}); diff --git a/plugins/azure/storageaccounts/blobServiceLoggingEnabled.js b/plugins/azure/storageaccounts/blobServiceLoggingEnabled.js index a1f6853f72..fc9278de8c 100644 --- a/plugins/azure/storageaccounts/blobServiceLoggingEnabled.js +++ b/plugins/azure/storageaccounts/blobServiceLoggingEnabled.js @@ -43,6 +43,9 @@ module.exports = { storageAccount.sku.tier && storageAccount.sku.tier.toLowerCase() == 'premium') { helpers.addResult(results, 0, 'Storage Account tier is premium', location, storageAccount.id); + } else if (storageAccount.kind && + storageAccount.kind.toLowerCase() != 'storagev2') { + helpers.addResult(results, 0, 'Storage Account kind is not StorageV2', location, storageAccount.id); } else { const diagnosticSettings = helpers.addSource(cache, source, diff --git a/plugins/azure/storageaccounts/blobServiceLoggingEnabled.spec.js b/plugins/azure/storageaccounts/blobServiceLoggingEnabled.spec.js index 4f4ae422c4..812ea23c0e 100644 --- a/plugins/azure/storageaccounts/blobServiceLoggingEnabled.spec.js +++ b/plugins/azure/storageaccounts/blobServiceLoggingEnabled.spec.js @@ -18,6 +18,16 @@ const storageAccounts = [ sku: { tier: 'Premium' } + }, + { + kind: 'BlobStorage', + id: '/subscriptions/1234/resourceGroups/cloud-shell-storage-eastus/providers/Microsoft.Storage/storageAccounts/csb100320011e293683', + name: 'csb100320011e293683', + type: 'Microsoft.Storage/storageAccounts', + location: 'eastus', + sku: { + tier: 'Standard' + } } ]; @@ -193,6 +203,18 @@ describe('blobServiceLoggingEnabled', function () { }); }); + it('should PASS if storage account kind in not StorageV2', function (done) { + const cache = createCache([storageAccounts[2]], []); + blobServiceLoggingEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('eastus'); + expect(results[0].message).to.equal('Storage Account kind is not StorageV2'); + + done(); + }); + }); + it('should UNKNOWN if Unable to query for for storage accounts', function (done) { const cache = createErrorCache('diagnostic'); blobServiceLoggingEnabled.run(cache, {}, (err, results) => { diff --git a/plugins/azure/storageaccounts/queueServiceLoggingEnabled.js b/plugins/azure/storageaccounts/queueServiceLoggingEnabled.js index a5eb3e0ca4..720a20f9b7 100644 --- a/plugins/azure/storageaccounts/queueServiceLoggingEnabled.js +++ b/plugins/azure/storageaccounts/queueServiceLoggingEnabled.js @@ -43,6 +43,9 @@ module.exports = { storageAccount.sku.tier && storageAccount.sku.tier.toLowerCase() == 'premium') { helpers.addResult(results, 0, 'Storage Account tier is premium', location, storageAccount.id); + } else if (storageAccount.kind && + storageAccount.kind.toLowerCase() != 'storagev2') { + helpers.addResult(results, 0, 'Storage Account kind is not StorageV2', location, storageAccount.id); } else { const diagnosticSettings = helpers.addSource(cache, source, @@ -75,4 +78,4 @@ module.exports = { callback(null, results, source); }); } -}; \ No newline at end of file +}; diff --git a/plugins/azure/storageaccounts/queueServiceLoggingEnabled.spec.js b/plugins/azure/storageaccounts/queueServiceLoggingEnabled.spec.js index 12c0b26261..d83e2cd773 100644 --- a/plugins/azure/storageaccounts/queueServiceLoggingEnabled.spec.js +++ b/plugins/azure/storageaccounts/queueServiceLoggingEnabled.spec.js @@ -28,6 +28,16 @@ const storageAccounts = [ sku: { tier: 'Premium' } + }, + { + kind: 'BlobStorage', + id: '/subscriptions/1234/resourceGroups/cloud-shell-storage-eastus/providers/Microsoft.Storage/storageAccounts/csb100320011e293683', + name: 'csb100320011e293683', + type: 'Microsoft.Storage/storageAccounts', + location: 'eastus', + sku: { + tier: 'Standard' + } } ]; @@ -205,6 +215,18 @@ describe('queueServiceLoggingEnabled', function () { }); }); + it('should PASS if storage account kind in not StorageV2', function (done) { + const cache = createCache([storageAccounts[2]], []); + queueServiceLoggingEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('eastus'); + expect(results[0].message).to.equal('Storage Account kind is not StorageV2'); + + done(); + }); + }); + it('should UNKNOWN if Unable to query for for storage accounts', function (done) { const cache = createErrorCache('storageAccounts'); queueServiceLoggingEnabled.run(cache, {}, (err, results) => { @@ -227,4 +249,3 @@ describe('queueServiceLoggingEnabled', function () { }); }); }); - diff --git a/plugins/azure/storageaccounts/storageAccountsHttps.js b/plugins/azure/storageaccounts/storageAccountsHttps.js index 9edaaff5dc..2e64c6db93 100644 --- a/plugins/azure/storageaccounts/storageAccountsHttps.js +++ b/plugins/azure/storageaccounts/storageAccountsHttps.js @@ -80,7 +80,6 @@ module.exports = { 'properties': { 'supportsHttpsTrafficOnly': true } - }; // logging diff --git a/plugins/azure/storageaccounts/tableServiceLoggingEnabled.js b/plugins/azure/storageaccounts/tableServiceLoggingEnabled.js index 074000d1a5..df0e56456d 100644 --- a/plugins/azure/storageaccounts/tableServiceLoggingEnabled.js +++ b/plugins/azure/storageaccounts/tableServiceLoggingEnabled.js @@ -42,6 +42,9 @@ module.exports = { storageAccount.sku.tier && storageAccount.sku.tier.toLowerCase() == 'premium') { helpers.addResult(results, 0, 'Storage Account tier is premium', location, storageAccount.id); + } else if (storageAccount.kind && + storageAccount.kind.toLowerCase() != 'storagev2') { + helpers.addResult(results, 0, 'Storage Account kind is not StorageV2', location, storageAccount.id); } else { const diagnosticSettings = helpers.addSource(cache, source, diff --git a/plugins/azure/storageaccounts/tableServiceLoggingEnabled.spec.js b/plugins/azure/storageaccounts/tableServiceLoggingEnabled.spec.js index c6da89bd60..a73c8c9127 100644 --- a/plugins/azure/storageaccounts/tableServiceLoggingEnabled.spec.js +++ b/plugins/azure/storageaccounts/tableServiceLoggingEnabled.spec.js @@ -28,6 +28,16 @@ const storageAccounts = [ sku: { tier: 'Premium' } + }, + { + kind: 'BlobStorage', + id: '/subscriptions/1234/resourceGroups/cloud-shell-storage-eastus/providers/Microsoft.Storage/storageAccounts/csb100320011e293683', + name: 'csb100320011e293683', + type: 'Microsoft.Storage/storageAccounts', + location: 'eastus', + sku: { + tier: 'Standard' + } } ]; @@ -205,6 +215,18 @@ describe('tableServiceLoggingEnabled', function () { }); }); + it('should PASS if storage account kind in not StorageV2', function (done) { + const cache = createCache([storageAccounts[2]], []); + tableServiceLoggingEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('eastus'); + expect(results[0].message).to.equal('Storage Account kind is not StorageV2'); + + done(); + }); + }); + it('should UNKNOWN if Unable to query for for storage accounts', function (done) { const cache = createErrorCache('storageAccounts'); tableServiceLoggingEnabled.run(cache, {}, (err, results) => { @@ -227,4 +249,3 @@ describe('tableServiceLoggingEnabled', function () { }); }); }); - diff --git a/plugins/azure/virtualmachines/vmNetworkExposure.js b/plugins/azure/virtualmachines/vmNetworkExposure.js new file mode 100644 index 0000000000..4258c9954f --- /dev/null +++ b/plugins/azure/virtualmachines/vmNetworkExposure.js @@ -0,0 +1,99 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Network Exposure', + category: 'Virtual Machines', + domain: 'Compute', + severity: 'Info', + description: 'Check if Azure virtual machines are exposed to the internet.', + more_info: 'Virtual machines exposed to the internet are at a higher risk of unauthorized access, data breaches, and cyberattacks. It’s crucial to limit exposure by securing access through proper configuration of security group and firewall rules.', + link: 'https://learn.microsoft.com/en-us/azure/security/fundamentals/virtual-machines-overview', + recommended_action: 'Secure VM instances by restricting access with properly configured security group and firewall rules.', + apis: ['virtualMachines:listAll', 'networkInterfaces:listAll', 'networkSecurityGroups:listAll', 'virtualNetworks:listAll'], + realtime_triggers: ['microsoftcompute:virtualmachines:write', 'microsoftnetwork:networkinterfaces:write', 'microsoftcompute:virtualmachines:delete', 'microsoftnetwork:networkinterfaces:delete', 'microsoftnetwork:networksecuritygroups:write','microsoftnetwork:networksecuritygroups:delete', 'microsoftnetwork:virtualnetworks:write','microsoftnetwork:virtualnetworks:delete'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.virtualMachines, function(location, rcb) { + var virtualMachines = helpers.addSource(cache, source, + ['virtualMachines', 'listAll', location]); + + if (!virtualMachines) return rcb(); + + if (virtualMachines.err || !virtualMachines.data) { + helpers.addResult(results, 3, 'Unable to query for virtualMachines: ' + helpers.addError(virtualMachines), location); + return rcb(); + } + + if (!virtualMachines.data.length) { + helpers.addResult(results, 0, 'No existing Virtual Machines found', location); + return rcb(); + } + + var networkInterfaces = helpers.addSource(cache, source, + ['networkInterfaces', 'listAll', location]); + + if (!networkInterfaces || networkInterfaces.err || !networkInterfaces.data || !networkInterfaces.data.length) { + helpers.addResult(results, 3, 'Unable to query for network interfaces: ' + helpers.addError(networkInterfaces), location); + return rcb(); + } + + let networkSecurityGroups = helpers.addSource(cache, source, + ['networkSecurityGroups', 'listAll', location]); + + + if (!networkSecurityGroups || networkSecurityGroups.err || !networkSecurityGroups.data) { + helpers.addResult(results, 3, 'Unable to query for Network Security Groups: ' + helpers.addError(networkSecurityGroups), location); + return rcb(); + } + + var virtualNetworks = helpers.addSource(cache, source, + ['virtualNetworks', 'listAll', location]); + + + virtualMachines.data.forEach(virtualMachine => { + let vm_interfaces = []; + let securityGroups = []; + if (virtualMachine.networkProfile && virtualMachine.networkProfile.networkInterfaces && + virtualMachine.networkProfile.networkInterfaces.length > 0) { + let interfaceIDs = virtualMachine.networkProfile.networkInterfaces.map(nic => nic.id); + vm_interfaces = networkInterfaces.data.filter(nic => interfaceIDs.includes(nic.id)); + if (networkSecurityGroups && networkSecurityGroups.data && networkSecurityGroups.data.length) { + let securityGroupIDs = vm_interfaces.filter(interface => interface.networkSecurityGroup && interface.networkSecurityGroup.id).map(nic => nic.networkSecurityGroup.id); + let allSubnetIDs = vm_interfaces.reduce((acc, nic) => { + let subnetIds = nic.ipConfigurations.map(ipConfig => ipConfig.properties.subnet.id); + return acc.concat(subnetIds); + }, []); + + if (virtualNetworks && !virtualNetworks.err && virtualNetworks.data && virtualNetworks.data.length) { + virtualNetworks.data.forEach(vnet => { + if (vnet.subnets && vnet.subnets.length) { + vnet.subnets.forEach(subnet => { + if (allSubnetIDs.includes(subnet.id) && subnet.properties && subnet.properties.networkSecurityGroup && subnet.properties.networkSecurityGroup.id) { + securityGroupIDs.push(subnet.properties.networkSecurityGroup.id); + } + }); + } + }); + + } + securityGroups = networkSecurityGroups.data.filter(nsg => securityGroupIDs.includes(nsg.id)); + } + } + let internetExposed = helpers.checkNetworkExposure(cache, source, vm_interfaces, securityGroups, location, results); + if (internetExposed && internetExposed.length) { + helpers.addResult(results, 2, `VM is exposed to the internet through ${internetExposed}`, location, virtualMachine.id); + } else { + helpers.addResult(results, 0, 'VM is not exposed to the internet', location, virtualMachine.id); + } + }); + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/google/compute/instanceNetworkExposure.js b/plugins/google/compute/instanceNetworkExposure.js new file mode 100644 index 0000000000..6e631c258f --- /dev/null +++ b/plugins/google/compute/instanceNetworkExposure.js @@ -0,0 +1,108 @@ +var async = require('async'); +var helpers = require('../../../helpers/google'); + +module.exports = { + title: 'Network Exposure', + category: 'Compute', + domain: 'Compute', + severity: 'Info', + description: 'Check if GCP virtual machines are exposed to the internet.', + more_info: 'Virtual machines exposed to the internet are at a higher risk of unauthorized access, data breaches, and cyberattacks. It’s crucial to limit exposure by securing access through proper configuration of network and firewall rules.', + link: 'https://cloud.google.com/firewall/docs/firewalls', + recommended_action: 'Secure VM instances by restricting access with properly configured security group and firewall rules.', + apis: ['compute:list', 'firewalls:list'], + realtime_triggers: ['compute.instances.insert', 'compute.instances.delete','compute.firewalls.insert', 'compute.firewalls.delete', 'compute.firewalls.patch'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(); + + let projects = helpers.addSource(cache, source, + ['projects','get', 'global']); + + if (!projects || projects.err || !projects.data || !projects.data.length) { + helpers.addResult(results, 3, + 'Unable to query for projects: ' + helpers.addError(projects), 'global', null, null, (projects) ? projects.err : null); + return callback(null, results, source); + } + + var project = projects.data[0].name; + + + async.each(regions.compute, (region, rcb) => { + var zones = regions.zones; + var noInstances = []; + + let firewalls = helpers.addSource( + cache, source, ['firewalls', 'list', 'global']); + + if (!firewalls) return rcb(); + + if (!firewalls || firewalls.err || !firewalls.data) { + helpers.addResult(results, 3, 'Unable to query firewall rules', region, null, null, firewalls.err); + return rcb(); + } + + if (!firewalls.data.length) { + helpers.addResult(results, 0, 'No firewall rules found', region); + return rcb(); + } + + async.each(zones[region], function(zone, zcb) { + var instances = helpers.addSource(cache, source, + ['compute','list', zone]); + + if (!instances) return zcb(); + + if (instances.err || !instances.data) { + helpers.addResult(results, 3, 'Unable to query compute instances', region, null, null, instances.err); + return zcb(); + } + + if (!instances.data.length) { + noInstances.push(zone); + return zcb(); + } + + instances.data.forEach(instance => { + let networks = instance.networkInterfaces.map(nic => nic.network); + let tags = instance.tags?.items || []; + let serviceAccount = instance.serviceAccounts[0]?.email || ''; + + let firewallRules = firewalls.data.filter(rule => { + let isNetworkMatch = networks.some(network => rule.network.endsWith(network)); + + let isTagMatch = rule.targetTags ? rule.targetTags.some(tag => tags.includes(tag)) : true; + + let isServiceAccountMatch = rule.targetServiceAccounts ? + rule.targetServiceAccounts.includes(serviceAccount) : true; + + return isNetworkMatch && isTagMatch && isServiceAccountMatch; + }); + + + networks = networks.map(network => network.split('/').pop()); + let internetExposed = helpers.checkNetworkExposure(cache, source, networks, firewallRules, region, results); + + let resource = helpers.createResourceName('instances', instance.name, project, 'zone', zone); + + if (internetExposed && internetExposed.length) { + helpers.addResult(results, 2, `VM is exposed to the internet through ${internetExposed}`, region, resource); + } else { + helpers.addResult(results, 0, 'VM is not exposed to the internet', region, resource); + } + + }); + zcb(); + }, function() { + if (noInstances.length) { + helpers.addResult(results, 0, `No instances found in following zones: ${noInstances.join(', ')}`, region); + } + rcb(); + }); + }, function() { + callback(null, results, source); + }); + } +}; From 6a26547c3237679e186c223fc8304972329bda04 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:16:57 +0500 Subject: [PATCH 68/91] Update instanceNetworkExposure.js --- plugins/google/compute/instanceNetworkExposure.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/google/compute/instanceNetworkExposure.js b/plugins/google/compute/instanceNetworkExposure.js index 6e631c258f..6a601b8c1a 100644 --- a/plugins/google/compute/instanceNetworkExposure.js +++ b/plugins/google/compute/instanceNetworkExposure.js @@ -67,7 +67,7 @@ module.exports = { instances.data.forEach(instance => { let networks = instance.networkInterfaces.map(nic => nic.network); - let tags = instance.tags?.items || []; + let tags = instance.tags && instance.tags.items ? instance.tags.items : []; let serviceAccount = instance.serviceAccounts[0]?.email || ''; let firewallRules = firewalls.data.filter(rule => { From 9968b5f811a67879178782e4ef1b597c3fbe89f2 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:24:11 +0500 Subject: [PATCH 69/91] Update instanceNetworkExposure.js --- plugins/google/compute/instanceNetworkExposure.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/google/compute/instanceNetworkExposure.js b/plugins/google/compute/instanceNetworkExposure.js index 6a601b8c1a..2b896162b2 100644 --- a/plugins/google/compute/instanceNetworkExposure.js +++ b/plugins/google/compute/instanceNetworkExposure.js @@ -68,7 +68,7 @@ module.exports = { instances.data.forEach(instance => { let networks = instance.networkInterfaces.map(nic => nic.network); let tags = instance.tags && instance.tags.items ? instance.tags.items : []; - let serviceAccount = instance.serviceAccounts[0]?.email || ''; + let serviceAccount = instance.serviceAccounts && instance.serviceAccounts[0] && instance.serviceAccounts[0].email ? instance.serviceAccounts[0].email : ''; let firewallRules = firewalls.data.filter(rule => { let isNetworkMatch = networks.some(network => rule.network.endsWith(network)); From a945cc8e39eef4aa27b5038d2ef898f678b9d597 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:38:04 +0500 Subject: [PATCH 70/91] Update functions.js --- helpers/azure/functions.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/helpers/azure/functions.js b/helpers/azure/functions.js index 66e7f488bd..3fdc0a5652 100644 --- a/helpers/azure/functions.js +++ b/helpers/azure/functions.js @@ -746,14 +746,14 @@ function checkSecurityGroup(securityGroups) { const allRules = securityGroups.flatMap(nsg => [ - ...nsg.securityRules?.map(rule => ({ + ...(nsg.securityRules ? nsg.securityRules.map(rule => ({ ...rule, nsgName: nsg.name - })), - ...(nsg.defaultSecurityRules?.map(rule => ({ + })) : []), + ...(nsg.defaultSecurityRules ? nsg.defaultSecurityRules.map(rule => ({ ...rule, nsgName: nsg.name - })) || []) + })) : []) ] ); From d738665e9eb238f8d2643df6b2201f23536de0d8 Mon Sep 17 00:00:00 2001 From: alphadev4 Date: Mon, 16 Sep 2024 21:48:25 +0500 Subject: [PATCH 71/91] fix lint issue --- helpers/google/functions.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/helpers/google/functions.js b/helpers/google/functions.js index eb20486c7c..f8b9367bef 100644 --- a/helpers/google/functions.js +++ b/helpers/google/functions.js @@ -412,7 +412,7 @@ function checkFirewallRules(firewallRules) { const networkName = firewallRule.network ? firewallRule.network.split('/').pop() : ''; - let allSources = firewallRule.sourceRanges?.some(sourceAddressPrefix => + let allSources = firewallRule.sourceRanges && firewallRule.sourceRanges.some(sourceAddressPrefix => sourceAddressPrefix === '*' || sourceAddressPrefix === '0.0.0.0/0' || sourceAddressPrefix === '::/0' || @@ -421,13 +421,14 @@ function checkFirewallRules(firewallRules) { sourceAddressPrefix.includes('/0') ); - if (allSources && firewallRule.allowed?.some(allow => !!allow.IPProtocol)) { - return {exposed: true, networkName: `vpc ${networkName}`}; + if (allSources && firewallRule.allowed && firewallRule.allowed.some(allow => !!allow.IPProtocol)) { + return { exposed: true, networkName: `vpc ${networkName}` }; } - - if (allSources && firewallRule.denied?.some(deny => deny.IPProtocol === 'all')) { - return {exposed: false}; + + if (allSources && firewallRule.denied && firewallRule.denied.some(deny => deny.IPProtocol === 'all')) { + return { exposed: false }; } + } return {exposed: true}; From c03eeb06f963a3ceebd85040af0a790ef893b47d Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:41:31 +0500 Subject: [PATCH 72/91] Apply suggestions from code review --- plugins/aws/guardduty/eksProtectionEnabled.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/aws/guardduty/eksProtectionEnabled.js b/plugins/aws/guardduty/eksProtectionEnabled.js index 757f6c68e7..c9eb7ea82c 100644 --- a/plugins/aws/guardduty/eksProtectionEnabled.js +++ b/plugins/aws/guardduty/eksProtectionEnabled.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Management and Governance', severity: 'Medium', description: 'Ensures GuardDuty protection is enabled for EKS' , - more_info: 'Enabling GuardDuty EKS Protection helps detect potential security threats in your EKS clusters by monitoring audit logs, user activities, and control plane operations. It provides enhanced security by offering proactive threat detection and automated alerting for suspicious activities and security issues within your AWS environment.', + more_info: 'Enabling GuardDuty EKS protection helps detect potential security threats in your EKS clusters by monitoring audit logs, user activities, and control plane operations. It provides enhanced security by offering proactive threat detection and automated alerting for suspicious activities and security issues within your AWS environment.', recommended_action: 'Enable GuardDuty EKS protection for all AWS accounts.', link: 'https://docs.aws.amazon.com/guardduty/latest/ug/kubernetes-protection.html', apis: ['GuardDuty:listDetectors', 'GuardDuty:getDetector', 'STS:getCallerIdentity'], @@ -52,7 +52,11 @@ module.exports = { var detector = getDetector.data; var resource = 'arn:' + awsOrGov + ':guardduty:' + region + ':' + accountId + ':detector/' + detector.detectorId; - if ( detector.DataSources && detector.DataSources.Kubernetes && detector.DataSources.Kubernetes.AuditLogs && detector.DataSources.Kubernetes.AuditLogs.Status === 'DISABLED'){ + if (detector.DataSources && + detector.DataSources.Kubernetes && + detector.DataSources.Kubernetes.AuditLogs && + detector.DataSources.Kubernetes.AuditLogs.Status + detector.DataSources.Kubernetes.AuditLogs.Status.toLowerCase() === 'disabled'){ helpers.addResult(results, 2, 'GuardDuty EKS protection is disabled', region, resource); } else { helpers.addResult(results, 0, 'GuardDuty EKS protection is enabled', region, resource); From 75603119f9284cdae6441447803bfd2878a2abe2 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:41:38 +0500 Subject: [PATCH 73/91] Update plugins/aws/guardduty/eksProtectionEnabled.js --- plugins/aws/guardduty/eksProtectionEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/guardduty/eksProtectionEnabled.js b/plugins/aws/guardduty/eksProtectionEnabled.js index c9eb7ea82c..17127d4335 100644 --- a/plugins/aws/guardduty/eksProtectionEnabled.js +++ b/plugins/aws/guardduty/eksProtectionEnabled.js @@ -6,7 +6,7 @@ module.exports = { category: 'GuardDuty', domain: 'Management and Governance', severity: 'Medium', - description: 'Ensures GuardDuty protection is enabled for EKS' , + description: 'Ensures that GuardDuty protection is enabled for EKS clusters.' , more_info: 'Enabling GuardDuty EKS protection helps detect potential security threats in your EKS clusters by monitoring audit logs, user activities, and control plane operations. It provides enhanced security by offering proactive threat detection and automated alerting for suspicious activities and security issues within your AWS environment.', recommended_action: 'Enable GuardDuty EKS protection for all AWS accounts.', link: 'https://docs.aws.amazon.com/guardduty/latest/ug/kubernetes-protection.html', From 3b896fb8cbf0c2256a22fc0133f3d43eacb37258 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:42:10 +0500 Subject: [PATCH 74/91] Update plugins/aws/guardduty/eksProtectionEnabled.js --- plugins/aws/guardduty/eksProtectionEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/guardduty/eksProtectionEnabled.js b/plugins/aws/guardduty/eksProtectionEnabled.js index 17127d4335..6961b75b03 100644 --- a/plugins/aws/guardduty/eksProtectionEnabled.js +++ b/plugins/aws/guardduty/eksProtectionEnabled.js @@ -33,7 +33,7 @@ module.exports = { return rcb(); } - if (!listDetectors.data || !listDetectors.data.length) { + if (!listDetectors.data || !listDetectors.data.length) { helpers.addResult(results, 0, 'No GuardDuty detectors found', region); return rcb(); } From 1a621b330c1251aa74aac2b3d52af08d3fee80f5 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:44:46 +0500 Subject: [PATCH 75/91] Update plugins/aws/guardduty/eksProtectionEnabled.js --- plugins/aws/guardduty/eksProtectionEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/guardduty/eksProtectionEnabled.js b/plugins/aws/guardduty/eksProtectionEnabled.js index 6961b75b03..ba6b5a713b 100644 --- a/plugins/aws/guardduty/eksProtectionEnabled.js +++ b/plugins/aws/guardduty/eksProtectionEnabled.js @@ -55,7 +55,7 @@ module.exports = { if (detector.DataSources && detector.DataSources.Kubernetes && detector.DataSources.Kubernetes.AuditLogs && - detector.DataSources.Kubernetes.AuditLogs.Status + detector.DataSources.Kubernetes.AuditLogs.Status && detector.DataSources.Kubernetes.AuditLogs.Status.toLowerCase() === 'disabled'){ helpers.addResult(results, 2, 'GuardDuty EKS protection is disabled', region, resource); } else { From ef14a89b19544f3d8a3957c00110eea07cec2d34 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:52:06 +0500 Subject: [PATCH 76/91] Update plugins/azure/machinelearning/mlRegistryPublicAccess.js --- plugins/azure/machinelearning/mlRegistryPublicAccess.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/machinelearning/mlRegistryPublicAccess.js b/plugins/azure/machinelearning/mlRegistryPublicAccess.js index a2a7073313..db08920738 100644 --- a/plugins/azure/machinelearning/mlRegistryPublicAccess.js +++ b/plugins/azure/machinelearning/mlRegistryPublicAccess.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Machine Learning', severity: 'Medium', description: 'Ensures that Azure Machine Learning registries are not publicly accessible.', - more_info: 'Disabling public network access for Azure Machine Learning registries helps prevent data leakage risks by ensuring that your registries are not accessible over the public internet. Instead, private endpoints provide network isolation, securing connections within a virtual network (VNet) and preventing exposure of sensitive data.', + more_info: 'Disabling public network access for Azure Machine Learning registries helps prevent data leakage risks by ensuring that your registries are not accessible over the public internet. Configuring network isolation with private endpoints prevents the network traffic from going over the public internet and brings Azure Machine Learning registry service to your Virtual network preventing exposure of sensitive data.', recommended_action: 'Ensure that Azure Machine Learning registries have public network access disabled.', link: 'https://learn.microsoft.com/en-us/azure/machine-learning/how-to-registry-network-isolation', apis: ['machineLearning:listRegistries'], From 511c30d53fc10643086ac6f684cc48072a6ba1c3 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Tue, 17 Sep 2024 20:14:04 +0500 Subject: [PATCH 77/91] Apply suggestions from code review --- .../mysqlFlexibleServerLoggingEnabled.spec.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js b/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js index cbd0a140ec..bc1a9b9142 100644 --- a/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js +++ b/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js @@ -9,7 +9,7 @@ const activityLogAlerts = [ "location": "global", "tags": {}, "scopes": [ - "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a" + "/subscriptions/123456" ], "enabled": true, "condition": { @@ -27,20 +27,20 @@ const activityLogAlerts = [ "actions": { "actionGroups": [ { - "actionGroupId": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourcegroups/default-activitylogalerts/providers/microsoft.insights/actiongroups/testactiong", + "actionGroupId": "/subscriptions/123456/resourcegroups/default-activitylogalerts/providers/microsoft.insights/actiongroups/testactiong", "webhookProperties": {} } ] } }, { - "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourceGroups/Default-ActivityLogAlerts/providers/microsoft.insights/activityLogAlerts/NSG2", + "id": "/subscriptions/123456/resourceGroups/Default-ActivityLogAlerts/providers/microsoft.insights/activityLogAlerts/NSG2", "name": "NSG2", "type": "Microsoft.Insights/ActivityLogAlerts", "location": "global", "tags": {}, "scopes": [ - "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a" + "/subscriptions/123456" ], "enabled": true, "condition": { @@ -62,20 +62,20 @@ const activityLogAlerts = [ "actions": { "actionGroups": [ { - "actionGroupId": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourcegroups/default-activitylogalerts/providers/microsoft.insights/actiongroups/testactiong", + "actionGroupId": "/subscriptions/123456/resourcegroups/default-activitylogalerts/providers/microsoft.insights/actiongroups/testactiong", "webhookProperties": {} } ] } }, { - "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourceGroups/Default-ActivityLogAlerts/providers/microsoft.insights/activityLogAlerts/NSG2", + "id": "/subscriptions/123456/resourceGroups/Default-ActivityLogAlerts/providers/microsoft.insights/activityLogAlerts/NSG2", "name": "NSG2", "type": "Microsoft.Insights/ActivityLogAlerts", "location": "global", "tags": {}, "scopes": [ - "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a" + "/subscriptions/123456" ], "enabled": true, "condition": { @@ -93,20 +93,20 @@ const activityLogAlerts = [ "actions": { "actionGroups": [ { - "actionGroupId": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourcegroups/default-activitylogalerts/providers/microsoft.insights/actiongroups/testactiong", + "actionGroupId": "/subscriptions/123456/resourcegroups/default-activitylogalerts/providers/microsoft.insights/actiongroups/testactiong", "webhookProperties": {} } ] } }, { - "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourceGroups/Default-ActivityLogAlerts/providers/microsoft.insights/activityLogAlerts/NSG2", + "id": "/subscriptions/123456/resourceGroups/Default-ActivityLogAlerts/providers/microsoft.insights/activityLogAlerts/NSG2", "name": "NSG2", "type": "Microsoft.Insights/ActivityLogAlerts", "location": "global", "tags": {}, "scopes": [ - "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a" + "/subscriptions/123456" ], "enabled": true, "condition": { @@ -124,7 +124,7 @@ const activityLogAlerts = [ "actions": { "actionGroups": [ { - "actionGroupId": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/resourcegroups/default-activitylogalerts/providers/microsoft.insights/actiongroups/testactiong", + "actionGroupId": "/subscriptions/123456/resourcegroups/default-activitylogalerts/providers/microsoft.insights/actiongroups/testactiong", "webhookProperties": {} } ] From 0b56fc277e06e9a5aaf6a7ad37b65a968c25857a Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Tue, 17 Sep 2024 20:22:08 +0500 Subject: [PATCH 78/91] Update plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js Co-authored-by: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> --- plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js b/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js index 617ed20dfe..981e9a0ad8 100644 --- a/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js +++ b/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Databases', severity: 'High', description: 'Ensures that Machine Learning Workspaces are encrypted using CMK.', - more_info: 'Azure Machine Learning allows you to encrypt workspces using customer-managed keys (CMK) instead of using platform-managed keys, which are enabled by default. Using CMK encryption offers enhanced security and compliance, allowing centralized management and control of encryption keys through Azure Key Vault.', + more_info: 'Azure Machine Learning allows you to encrypt workspaces using customer-managed keys (CMK) instead of using platform-managed keys, which are enabled by default. Using CMK encryption offers enhanced security and compliance, allowing centralized management and control of encryption keys through Azure Key Vault.', recommended_action: 'Ensure that Machine Learning Workspaces are encrypted using CMK.', link: 'https://learn.microsoft.com/en-us/azure/machine-learning/concept-customer-managed-keys', apis: ['machineLearning:listWorkspaces'], From 8187653d3e1542746a66d5fd1e4a3c44fab3f79c Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Tue, 17 Sep 2024 20:22:15 +0500 Subject: [PATCH 79/91] Update plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js --- plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js b/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js index 981e9a0ad8..291d436a01 100644 --- a/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js +++ b/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js @@ -19,7 +19,6 @@ module.exports = { const locations = helpers.locations(settings.govcloud); async.each(locations.machineLearning, function(location, rcb) { - var machineLearningWorkspaces = helpers.addSource(cache, source, ['machineLearning', 'listWorkspaces', location]); From 8ec13352fb01033a2299c0559b8d8bd66489c878 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Wed, 18 Sep 2024 12:59:58 +0500 Subject: [PATCH 80/91] updated the link --- plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js b/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js index 34748a2305..df0f737c10 100644 --- a/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js +++ b/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js @@ -9,7 +9,7 @@ module.exports = { description: 'Ensures that diagnostic logging is enabled for Synapse workspace.', more_info: 'Enabling diagnostic logs in Azure Synapse workspace is important for monitoring, troubleshooting, and optimizing performance. These logs provide detailed insights into resource usage, query execution, and potential issues, allowing administrators to identify bottlenecks, track errors, and improve the overall efficiency and reliability of the workspace.', recommended_action: 'Enable diagnostic logging for all Synapse workspaces.', - link: 'https://learn.microsoft.com/en-gb/azure/azure-monitor/essentials/diagnostic-settings', + link: 'https://learn.microsoft.com/en-us/azure/synapse-analytics/monitor-synapse-analytics', apis: ['synapse:listWorkspaces', 'diagnosticSettings:listByWorkspaces'], realtime_triggers: ['microsoftsynapse:workspaces:write','microsoftsynapse:workspaces:delete','microsoftinsights:diagnosticSettings:delete','microsoftinsights:diagnosticSettings:write'], From bd578d330a7a6861cfdc81a24dba634bf9f50c17 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Wed, 18 Sep 2024 13:01:31 +0500 Subject: [PATCH 81/91] fixed --- plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js b/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js index df0f737c10..a9beb8a458 100644 --- a/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js +++ b/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js @@ -35,6 +35,7 @@ module.exports = { } for (let workspace of workspaces.data) { + if (!workspace.id) continue; var diagnosticSettings = helpers.addSource(cache, source, ['diagnosticSettings', 'listByWorkspaces', location, workspace.id]); From 1aa337c4a0dd116b426c6ffe09707596287b8ce3 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Wed, 18 Sep 2024 13:21:45 +0500 Subject: [PATCH 82/91] fix --- exports.js | 2 +- plugins/azure/machinelearning/mlWorkspaceHBI.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/exports.js b/exports.js index b1e2515be1..3132e52ac1 100644 --- a/exports.js +++ b/exports.js @@ -735,7 +735,7 @@ module.exports = { 'containerAppHasTags' : require(__dirname + '/plugins/azure/containerapps/containerAppHasTags.js'), - 'mlRegistryPublicAccess' : require(__dirname + '/plugins/azure/machinelearning/mlWorkspaceHBI.js'), + 'mlWorkspaceHBI' : require(__dirname + '/plugins/azure/machinelearning/mlWorkspaceHBI.js'), 'workspacePublicAccessDisabled' : require(__dirname + '/plugins/azure/machinelearning/workspacePublicAccessDisabled.js'), 'workspaceLoggingEnabled' : require(__dirname + '/plugins/azure/machinelearning/workspaceLoggingEnabled.js'), 'mlWorkspaceHasTags' : require(__dirname + '/plugins/azure/machinelearning/mlWorkspaceHasTags.js'), diff --git a/plugins/azure/machinelearning/mlWorkspaceHBI.js b/plugins/azure/machinelearning/mlWorkspaceHBI.js index e2535cd1d7..de1135ed55 100644 --- a/plugins/azure/machinelearning/mlWorkspaceHBI.js +++ b/plugins/azure/machinelearning/mlWorkspaceHBI.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Machine Learning', severity: 'Medium', description: 'Ensures that Machine Learning workspaces have High Business Impact (HBI) feature enabled.', - more_info: 'Enabling a high business impact workspace controls the data Microsoft collects for diagnostics and prevents sending confidential telemetry data to Microsoft, ensuring security measures, compliance, and risk management protocols are in place to protect sensitive data.', + more_info: 'Enabling the High Business Impact (HBI) feature in Machine Learning workspaces controls the data Microsoft collects for diagnostics, prevents the transmission of confidential telemetry, and enhances encryption to protect sensitive business information while ensuring compliance with security protocols.', recommended_action: 'Ensures that High Business Impact (HBI) feature enabled for Machine Learning workspace.', link: 'https://learn.microsoft.com/en-us/azure/machine-learning/concept-data-encryption', apis: ['machineLearning:listWorkspaces'], @@ -19,7 +19,6 @@ module.exports = { const locations = helpers.locations(settings.govcloud); async.each(locations.machineLearning, function(location, rcb) { - var machineLearningWorkspaces = helpers.addSource(cache, source, ['machineLearning', 'listWorkspaces', location]); From ccfc3d97b3dca9cea5a12c7d1d2c9b169817c422 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Wed, 18 Sep 2024 13:54:52 +0500 Subject: [PATCH 83/91] Update plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js --- plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js b/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js index deae8931e2..4790a09e43 100644 --- a/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js +++ b/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Content Delivery', severity: 'Medium', description: 'Ensure that Amazon Managed Blockchain members have CloudWatch logs enabled.', - more_info: 'Enabling CloudWatch Logs for Amazon Managed Blockchain helps troubleshoot chaincode development, monitor network activity, and identify errors by publishing peer node, chaincode, and certificate authority (CA) logs.', + more_info: 'Enabling CloudWatch Logs for Amazon Managed Blockchain members is essential for monitoring certificate authority (CA) activity, ensuring proper identity management, and troubleshooting any access-related issues by publishing CA logs.', link: 'https://docs.aws.amazon.com/managed-blockchain/latest/hyperledger-fabric-dev/monitoring-cloudwatch-logs.html', recommended_action: 'Modify Managed Blockchain members to enable CloudWatch Logs', apis: ['ManagedBlockchain:listMembers', 'ManagedBlockchain:listNetworks', 'ManagedBlockchain:getMember'], From 1fb5a8e914ffab463bac164f8874f11129447b3f Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:24:35 +0500 Subject: [PATCH 84/91] Update plugins/azure/synapse/synapseWorkspaceHasTags.js --- plugins/azure/synapse/synapseWorkspaceHasTags.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/azure/synapse/synapseWorkspaceHasTags.js b/plugins/azure/synapse/synapseWorkspaceHasTags.js index 33a0cfa963..05f4053752 100644 --- a/plugins/azure/synapse/synapseWorkspaceHasTags.js +++ b/plugins/azure/synapse/synapseWorkspaceHasTags.js @@ -45,7 +45,6 @@ module.exports = { helpers.addResult(results, 2, 'Synapse workspace does not have tags', location, workspace.id); } } - rcb(); }, function() { // Global checking goes here From d15fc1a9e0bea70ecdb5e8c1c8576977ea593953 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:27:31 +0500 Subject: [PATCH 85/91] Update exports.js --- exports.js | 1 - 1 file changed, 1 deletion(-) diff --git a/exports.js b/exports.js index 2af7ee0fe7..725e0d0871 100644 --- a/exports.js +++ b/exports.js @@ -1225,7 +1225,6 @@ module.exports = { 'workspaceDiagnosticLogsEnabled': require(__dirname + '/plugins/azure/synapse/workspaceDiagnosticLogsEnabled.js'), 'workspaceDoubleEncryption' : require(__dirname + '/plugins/azure/synapse/workspaceDoubleEncryption.js'), - 'apiInstanceManagedIdentity' : require(__dirname + '/plugins/azure/apiManagement/apiInstanceManagedIdentity.js'), 'apiInstanceHasTags' : require(__dirname + '/plugins/azure/apiManagement/apiInstanceHasTags.js'), From 4ad942bf1fa030d8a0c88afa9f9db5d2fb7d70e2 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:30:55 +0500 Subject: [PATCH 86/91] Update exports.js --- exports.js | 1 - 1 file changed, 1 deletion(-) diff --git a/exports.js b/exports.js index 3132e52ac1..a829ddabf4 100644 --- a/exports.js +++ b/exports.js @@ -734,7 +734,6 @@ module.exports = { 'containerAppHttpsOnly' : require(__dirname + '/plugins/azure/containerapps/containerAppHttpsOnly.js'), 'containerAppHasTags' : require(__dirname + '/plugins/azure/containerapps/containerAppHasTags.js'), - 'mlWorkspaceHBI' : require(__dirname + '/plugins/azure/machinelearning/mlWorkspaceHBI.js'), 'workspacePublicAccessDisabled' : require(__dirname + '/plugins/azure/machinelearning/workspacePublicAccessDisabled.js'), 'workspaceLoggingEnabled' : require(__dirname + '/plugins/azure/machinelearning/workspaceLoggingEnabled.js'), From dde1e8860d75702332ae1e4999545bd7c2337569 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:36:16 +0500 Subject: [PATCH 87/91] Update exports.js --- exports.js | 1 - 1 file changed, 1 deletion(-) diff --git a/exports.js b/exports.js index 13046ff016..e557fbe6a7 100644 --- a/exports.js +++ b/exports.js @@ -639,7 +639,6 @@ module.exports = { 'networkMemberDataEncrypted' : require(__dirname + '/plugins/aws/managedblockchain/networkMemberDataEncrypted.js'), 'networkMemberCloudwatchLogs' : require(__dirname + '/plugins/aws/managedblockchain/networkMemberCloudwatchLogs.js'), - 'docdbClusterEncrypted' : require(__dirname + '/plugins/aws/documentDB/docdbClusterEncrypted.js'), 'docDbHasTags' : require(__dirname + '/plugins/aws/documentDB/docDbHasTags.js'), 'docdbDeletionProtectionEnabled': require(__dirname + '/plugins/aws/documentDB/docdbDeletionProtectionEnabled.js'), From 761e8820e4d79ebf21a25577f6627c6d7f103234 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:37:12 +0500 Subject: [PATCH 88/91] Update plugins/aws/guardduty/eksProtectionEnabled.js --- plugins/aws/guardduty/eksProtectionEnabled.js | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/aws/guardduty/eksProtectionEnabled.js b/plugins/aws/guardduty/eksProtectionEnabled.js index ba6b5a713b..05f7daa5e2 100644 --- a/plugins/aws/guardduty/eksProtectionEnabled.js +++ b/plugins/aws/guardduty/eksProtectionEnabled.js @@ -61,6 +61,7 @@ module.exports = { } else { helpers.addResult(results, 0, 'GuardDuty EKS protection is enabled', region, resource); } + }); rcb(); From 11c9770d337221b3b516151ddfc260e2bc0a84c9 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:37:43 +0500 Subject: [PATCH 89/91] Update exports.js --- exports.js | 1 - 1 file changed, 1 deletion(-) diff --git a/exports.js b/exports.js index 81848cc733..441094faf1 100644 --- a/exports.js +++ b/exports.js @@ -740,7 +740,6 @@ module.exports = { 'mlRegistryPublicAccess' : require(__dirname + '/plugins/azure/machinelearning/mlRegistryPublicAccess.js'), - 'minimumTlsVersion' : require(__dirname + '/plugins/azure/redisCache/minimumTlsVersion.js'), 'sslAccessOnlyEnabled' : require(__dirname + '/plugins/azure/redisCache/sslAccessOnlyEnabled.js'), 'redisCacheHasTags' : require(__dirname + '/plugins/azure/redisCache/redisCacheHasTags.js'), From 2788119505133e7b53c8aa87b2bfa774f16136b0 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:38:09 +0500 Subject: [PATCH 90/91] Update plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js --- plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js b/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js index 291d436a01..efc8dd25bd 100644 --- a/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js +++ b/plugins/azure/machinelearning/mlWorkspaceCMKEncrypted.js @@ -44,7 +44,6 @@ module.exports = { helpers.addResult(results, 2, 'Machine Learning workspace is not encrypted using CMK', location, workspace.id); } } - rcb(); }, function() { // Global checking goes here From 584d723f53d4d1e06e1a88aa4c14b36f316b9b19 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:41:59 +0500 Subject: [PATCH 91/91] Update plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js --- .../azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js b/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js index bc1a9b9142..85b1f94552 100644 --- a/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js +++ b/plugins/azure/logalerts/mysqlFlexibleServerLoggingEnabled.spec.js @@ -64,7 +64,8 @@ const activityLogAlerts = [ { "actionGroupId": "/subscriptions/123456/resourcegroups/default-activitylogalerts/providers/microsoft.insights/actiongroups/testactiong", "webhookProperties": {} - } + + } ] } },