From 82c76a191e2fc3a066fdef8b3f3ae8a957743b24 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 5 Dec 2021 14:06:20 -0800 Subject: [PATCH 001/350] Added spec for rdsAutomatedBackups plugin --- plugins/aws/rds/rdsAutomatedBackups.spec.js | 414 ++++++++++++++++++++ 1 file changed, 414 insertions(+) create mode 100644 plugins/aws/rds/rdsAutomatedBackups.spec.js diff --git a/plugins/aws/rds/rdsAutomatedBackups.spec.js b/plugins/aws/rds/rdsAutomatedBackups.spec.js new file mode 100644 index 0000000000..37f6cffc03 --- /dev/null +++ b/plugins/aws/rds/rdsAutomatedBackups.spec.js @@ -0,0 +1,414 @@ +var expect = require('chai').expect; +var rdsAutomatedBackups = require('./rdsAutomatedBackups'); + +const describeDBInstances = [ + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "postgres", + "DBInstanceStatus": "creating", + "MasterUsername": "postgres", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "BackupRetentionPeriod": 7, + "DBSecurityGroups": [], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-aa941691", + "Status": "active" + } + ], + "DBParameterGroups": [ + { + "DBParameterGroupName": "default.postgres12", + "ParameterApplyStatus": "in-sync" + } + ], + "AvailabilityZone": "us-east-1f", + "DBSubnetGroup": { + "DBSubnetGroupName": "default-vpc-99de2fe4", + "DBSubnetGroupDescription": "Created from the RDS Management Console", + "VpcId": "vpc-99de2fe4", + "SubnetGroupStatus": "Complete", + "Subnets": [ + { + "SubnetIdentifier": "subnet-aac6b3e7", + "SubnetAvailabilityZone": { + "Name": "us-east-1c" + }, + "SubnetOutpost": {}, + "SubnetStatus": "Active" + } + ] + }, + "PreferredMaintenanceWindow": "fri:10:05-fri:10:35", + "PendingModifiedValues": { + "MasterUserPassword": "****", + "ProcessorFeatures": [] + }, + "MultiAZ": false, + "EngineVersion": "12.3", + "AutoMinorVersionUpgrade": false, + "ReadReplicaDBInstanceIdentifiers": [], + "ReadReplicaDBClusterIdentifiers": [], + "LicenseModel": "postgresql-license", + "OptionGroupMemberships": [ + { + "OptionGroupName": "default:postgres-12", + "Status": "in-sync" + } + ], + "PubliclyAccessible": false, + "StatusInfos": [], + "StorageType": "gp2", + "DbInstancePort": 0, + "StorageEncrypted": true, + "KmsKeyId": "arn:aws:kms:us-east-1:012345678910:key/abcdef10-1517-49d8-b085-77c50b904149", + "DbiResourceId": "db-ZLVMKFR7AS6SJYTQPXZ4SUH5ZU", + "CACertificateIdentifier": "rds-ca-2019", + "DomainMemberships": [], + "CopyTagsToSnapshot": false, + "MonitoringInterval": 0, + "DBInstanceArn": "arn:aws:rds:us-east-1:111122223333:db:test-db-115", + "IAMDatabaseAuthenticationEnabled": false, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [], + "ProcessorFeatures": [], + "DeletionProtection": false, + "AssociatedRoles": [] + }, + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "postgres", + "DBInstanceStatus": "creating", + "MasterUsername": "postgres", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "BackupRetentionPeriod": 2, + "DBSecurityGroups": [], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-aa941691", + "Status": "active" + } + ], + "DBParameterGroups": [ + { + "DBParameterGroupName": "default.postgres12", + "ParameterApplyStatus": "in-sync" + } + ], + "AvailabilityZone": "us-east-1f", + "DBSubnetGroup": { + "DBSubnetGroupName": "default-vpc-99de2fe4", + "DBSubnetGroupDescription": "Created from the RDS Management Console", + "VpcId": "vpc-99de2fe4", + "SubnetGroupStatus": "Complete", + "Subnets": [ + { + "SubnetIdentifier": "subnet-aac6b3e7", + "SubnetAvailabilityZone": { + "Name": "us-east-1c" + }, + "SubnetOutpost": {}, + "SubnetStatus": "Active" + } + ] + }, + "PreferredMaintenanceWindow": "fri:10:05-fri:10:35", + "PendingModifiedValues": { + "MasterUserPassword": "****", + "ProcessorFeatures": [] + }, + "MultiAZ": false, + "EngineVersion": "12.3", + "AutoMinorVersionUpgrade": false, + "ReadReplicaDBInstanceIdentifiers": [], + "ReadReplicaDBClusterIdentifiers": [], + "LicenseModel": "postgresql-license", + "OptionGroupMemberships": [ + { + "OptionGroupName": "default:postgres-12", + "Status": "in-sync" + } + ], + "PubliclyAccessible": false, + "StatusInfos": [], + "StorageType": "gp2", + "DbInstancePort": 0, + "StorageEncrypted": true, + "KmsKeyId": "arn:aws:kms:us-east-1:012345678910:key/88888828-1517-49d8-b085-77c50b904149", + "DbiResourceId": "db-ZLVMKFR7AS6SJYTQPXZ4SUH5ZU", + "CACertificateIdentifier": "rds-ca-2019", + "DomainMemberships": [], + "CopyTagsToSnapshot": false, + "MonitoringInterval": 0, + "DBInstanceArn": "arn:aws:rds:us-east-1:111122223333:db:test-db-115", + "IAMDatabaseAuthenticationEnabled": false, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [], + "ProcessorFeatures": [], + "DeletionProtection": false, + "AssociatedRoles": [] + }, + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "postgres", + "DBInstanceStatus": "creating", + "MasterUsername": "postgres", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "DBSecurityGroups": [], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-aa941691", + "Status": "active" + } + ], + "DBParameterGroups": [ + { + "DBParameterGroupName": "default.postgres12", + "ParameterApplyStatus": "in-sync" + } + ], + "AvailabilityZone": "us-east-1f", + "DBSubnetGroup": { + "DBSubnetGroupName": "default-vpc-99de2fe4", + "DBSubnetGroupDescription": "Created from the RDS Management Console", + "VpcId": "vpc-99de2fe4", + "SubnetGroupStatus": "Complete", + "Subnets": [ + { + "SubnetIdentifier": "subnet-aac6b3e7", + "SubnetAvailabilityZone": { + "Name": "us-east-1c" + }, + "SubnetOutpost": {}, + "SubnetStatus": "Active" + } + ] + }, + "PreferredMaintenanceWindow": "fri:10:05-fri:10:35", + "PendingModifiedValues": { + "MasterUserPassword": "****", + "ProcessorFeatures": [] + }, + "MultiAZ": false, + "EngineVersion": "12.3", + "AutoMinorVersionUpgrade": false, + "ReadReplicaDBInstanceIdentifiers": [], + "ReadReplicaDBClusterIdentifiers": [], + "LicenseModel": "postgresql-license", + "OptionGroupMemberships": [ + { + "OptionGroupName": "default:postgres-12", + "Status": "in-sync" + } + ], + "PubliclyAccessible": false, + "StatusInfos": [], + "StorageType": "gp2", + "DbInstancePort": 0, + "StorageEncrypted": false, + "DbiResourceId": "db-ZLVMKFR7AS6SJYTQPXZ4SUH5ZU", + "CACertificateIdentifier": "rds-ca-2019", + "DomainMemberships": [], + "CopyTagsToSnapshot": false, + "MonitoringInterval": 0, + "DBInstanceArn": "arn:aws:rds:us-east-1:111122223333:db:test-db-115", + "IAMDatabaseAuthenticationEnabled": false, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [], + "ProcessorFeatures": [], + "DeletionProtection": false, + "AssociatedRoles": [] + }, + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "postgresql", + "ReadReplicaSourceDBInstanceIdentifier": "test-db-115", + "DBInstanceStatus": "creating", + "MasterUsername": "postgres", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "BackupRetentionPeriod": 7, + "DBSecurityGroups": [], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-aa941691", + "Status": "active" + } + ], + "DBParameterGroups": [ + { + "DBParameterGroupName": "default.postgres12", + "ParameterApplyStatus": "in-sync" + } + ], + "AvailabilityZone": "us-east-1f", + "DBSubnetGroup": { + "DBSubnetGroupName": "default-vpc-99de2fe4", + "DBSubnetGroupDescription": "Created from the RDS Management Console", + "VpcId": "vpc-99de2fe4", + "SubnetGroupStatus": "Complete", + "Subnets": [ + { + "SubnetIdentifier": "subnet-aac6b3e7", + "SubnetAvailabilityZone": { + "Name": "us-east-1c" + }, + "SubnetOutpost": {}, + "SubnetStatus": "Active" + } + ] + }, + "PreferredMaintenanceWindow": "fri:10:05-fri:10:35", + "PendingModifiedValues": { + "MasterUserPassword": "****", + "ProcessorFeatures": [] + }, + "MultiAZ": false, + "EngineVersion": "12.3", + "AutoMinorVersionUpgrade": false, + "ReadReplicaDBInstanceIdentifiers": [], + "ReadReplicaDBClusterIdentifiers": [], + "LicenseModel": "postgresql-license", + "OptionGroupMemberships": [ + { + "OptionGroupName": "default:postgres-12", + "Status": "in-sync" + } + ], + "PubliclyAccessible": false, + "StatusInfos": [], + "StorageType": "gp2", + "DbInstancePort": 0, + "StorageEncrypted": true, + "KmsKeyId": "arn:aws:kms:us-east-1:012345678910:key/abcdef10-1517-49d8-b085-77c50b904149", + "DbiResourceId": "db-ZLVMKFR7AS6SJYTQPXZ4SUH5ZU", + "CACertificateIdentifier": "rds-ca-2019", + "DomainMemberships": [], + "CopyTagsToSnapshot": false, + "MonitoringInterval": 0, + "DBInstanceArn": "arn:aws:rds:us-east-1:111122223333:db:test-db-115", + "IAMDatabaseAuthenticationEnabled": false, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [], + "ProcessorFeatures": [], + "DeletionProtection": false, + "AssociatedRoles": [] + } +]; + +const createCache = (rdsInstances) => { + return { + rds: { + describeDBInstances: { + 'us-east-1': { + err: null, + data: rdsInstances + }, + }, + } + }; +}; + +const createErrorCache = () => { + return { + rds: { + describeDBInstances: { + 'us-east-1': { + err: { + message: 'error while describing RDS instances' + }, + }, + }, + } + }; +}; + +const createNullCache = () => { + return { + rds: { + describeDBInstances: { + 'us-east-1': null, + }, + } + }; +}; + +describe('rdsAutomatedBackups', function () { + describe('run', function () { + it('should PASS if no RDS DB instance is found', function (done) { + const cache = createCache([]); + rdsAutomatedBackups.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).includes('No RDS instances found'); + done(); + }); + }); + + it('should PASS if automated backups are enabled and retention period is greater than 6 days', function (done) { + const cache = createCache([describeDBInstances[0]]); + rdsAutomatedBackups.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).includes('Automated backups are enabled with sufficient retention'); + done(); + }); + }); + + it('should PASS if automated backups are enabled and retention period is less than 6 days', function (done) { + const cache = createCache([describeDBInstances[1]]); + rdsAutomatedBackups.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(1); + expect(results[0].message).includes('Automated backups are enabled but do not have sufficient retention'); + done(); + }); + }); + + it('should FAIL if automated backups are not enabled', function (done) { + const cache = createCache([describeDBInstances[2]]); + rdsAutomatedBackups.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).includes('Automated backups are not enabled'); + done(); + }); + }); + + it('should not return anything if the instance is a read only replica Source Identifier for PostgreSQL', function (done) { + const cache = createCache([describeDBInstances[3]]); + rdsAutomatedBackups.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + + it('should UNKNOWN if error while describing RDS DB instances', function (done) { + const cache = createErrorCache(); + rdsAutomatedBackups.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should not return anything if unable to describe RDS DB instances', function (done) { + const cache = createNullCache(); + rdsAutomatedBackups.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + }); +}); From c88aa2b8240cb9be04614602738f061a8198e863 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 12 Dec 2021 06:47:01 -0800 Subject: [PATCH 002/350] Added spec for rdsLoggingEnabled plugin --- plugins/aws/rds/rdsLoggingEnabled.spec.js | 531 ++++++++++++++++++++++ 1 file changed, 531 insertions(+) create mode 100644 plugins/aws/rds/rdsLoggingEnabled.spec.js diff --git a/plugins/aws/rds/rdsLoggingEnabled.spec.js b/plugins/aws/rds/rdsLoggingEnabled.spec.js new file mode 100644 index 0000000000..0f1c3c6548 --- /dev/null +++ b/plugins/aws/rds/rdsLoggingEnabled.spec.js @@ -0,0 +1,531 @@ +var expect = require('chai').expect; +var rdsLoggingEnabled = require('./rdsLoggingEnabled'); + +const describeDBInstances = [ + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "postgres", + "DBInstanceStatus": "creating", + "MasterUsername": "postgres", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "BackupRetentionPeriod": 7, + "DBSecurityGroups": [], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-aa941691", + "Status": "active" + } + ], + "DBParameterGroups": [ + { + "DBParameterGroupName": "default.postgres12", + "ParameterApplyStatus": "in-sync" + } + ], + "AvailabilityZone": "us-east-1f", + "DBSubnetGroup": { + "DBSubnetGroupName": "default-vpc-99de2fe4", + "DBSubnetGroupDescription": "Created from the RDS Management Console", + "VpcId": "vpc-99de2fe4", + "SubnetGroupStatus": "Complete", + "Subnets": [ + { + "SubnetIdentifier": "subnet-aac6b3e7", + "SubnetAvailabilityZone": { + "Name": "us-east-1c" + }, + "SubnetOutpost": {}, + "SubnetStatus": "Active" + } + ] + }, + "PreferredMaintenanceWindow": "fri:10:05-fri:10:35", + "PendingModifiedValues": { + "MasterUserPassword": "****", + "ProcessorFeatures": [] + }, + "MultiAZ": false, + "EngineVersion": "12.3", + "AutoMinorVersionUpgrade": false, + "ReadReplicaDBInstanceIdentifiers": [], + "ReadReplicaDBClusterIdentifiers": [], + "LicenseModel": "postgresql-license", + "OptionGroupMemberships": [ + { + "OptionGroupName": "default:postgres-12", + "Status": "in-sync" + } + ], + "PubliclyAccessible": false, + "StatusInfos": [], + "StorageType": "gp2", + "DbInstancePort": 0, + "StorageEncrypted": true, + "KmsKeyId": "arn:aws:kms:us-east-1:012345678910:key/abcdef10-1517-49d8-b085-77c50b904149", + "DbiResourceId": "db-ZLVMKFR7AS6SJYTQPXZ4SUH5ZU", + "CACertificateIdentifier": "rds-ca-2019", + "DomainMemberships": [], + "CopyTagsToSnapshot": false, + "MonitoringInterval": 0, + "DBInstanceArn": "arn:aws:rds:us-east-1:111122223333:db:test-db-115", + "IAMDatabaseAuthenticationEnabled": false, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [ "postgresql" ], + "ProcessorFeatures": [], + "DeletionProtection": false, + "AssociatedRoles": [] + }, + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "postgres", + "DBInstanceStatus": "creating", + "MasterUsername": "postgres", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "BackupRetentionPeriod": 2, + "DBSecurityGroups": [], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-aa941691", + "Status": "active" + } + ], + "DBParameterGroups": [ + { + "DBParameterGroupName": "default.postgres12", + "ParameterApplyStatus": "in-sync" + } + ], + "AvailabilityZone": "us-east-1f", + "DBSubnetGroup": { + "DBSubnetGroupName": "default-vpc-99de2fe4", + "DBSubnetGroupDescription": "Created from the RDS Management Console", + "VpcId": "vpc-99de2fe4", + "SubnetGroupStatus": "Complete", + "Subnets": [ + { + "SubnetIdentifier": "subnet-aac6b3e7", + "SubnetAvailabilityZone": { + "Name": "us-east-1c" + }, + "SubnetOutpost": {}, + "SubnetStatus": "Active" + } + ] + }, + "PreferredMaintenanceWindow": "fri:10:05-fri:10:35", + "PendingModifiedValues": { + "MasterUserPassword": "****", + "ProcessorFeatures": [] + }, + "MultiAZ": false, + "EngineVersion": "12.3", + "AutoMinorVersionUpgrade": false, + "ReadReplicaDBInstanceIdentifiers": [], + "ReadReplicaDBClusterIdentifiers": [], + "LicenseModel": "postgresql-license", + "OptionGroupMemberships": [ + { + "OptionGroupName": "default:postgres-12", + "Status": "in-sync" + } + ], + "PubliclyAccessible": false, + "StatusInfos": [], + "StorageType": "gp2", + "DbInstancePort": 0, + "StorageEncrypted": true, + "KmsKeyId": "arn:aws:kms:us-east-1:012345678910:key/88888828-1517-49d8-b085-77c50b904149", + "DbiResourceId": "db-ZLVMKFR7AS6SJYTQPXZ4SUH5ZU", + "CACertificateIdentifier": "rds-ca-2019", + "DomainMemberships": [], + "CopyTagsToSnapshot": false, + "MonitoringInterval": 0, + "DBInstanceArn": "arn:aws:rds:us-east-1:111122223333:db:test-db-115", + "IAMDatabaseAuthenticationEnabled": false, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [], + "ProcessorFeatures": [], + "DeletionProtection": false, + "AssociatedRoles": [] + }, + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "postgres", + "DBInstanceStatus": "creating", + "MasterUsername": "postgres", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "DBSecurityGroups": [], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-aa941691", + "Status": "active" + } + ], + "DBParameterGroups": [ + { + "DBParameterGroupName": "default.postgres12", + "ParameterApplyStatus": "in-sync" + } + ], + "AvailabilityZone": "us-east-1f", + "DBSubnetGroup": { + "DBSubnetGroupName": "default-vpc-99de2fe4", + "DBSubnetGroupDescription": "Created from the RDS Management Console", + "VpcId": "vpc-99de2fe4", + "SubnetGroupStatus": "Complete", + "Subnets": [ + { + "SubnetIdentifier": "subnet-aac6b3e7", + "SubnetAvailabilityZone": { + "Name": "us-east-1c" + }, + "SubnetOutpost": {}, + "SubnetStatus": "Active" + } + ] + }, + "PreferredMaintenanceWindow": "fri:10:05-fri:10:35", + "PendingModifiedValues": { + "MasterUserPassword": "****", + "ProcessorFeatures": [] + }, + "MultiAZ": false, + "EngineVersion": "12.3", + "AutoMinorVersionUpgrade": false, + "ReadReplicaDBInstanceIdentifiers": [], + "ReadReplicaDBClusterIdentifiers": [], + "LicenseModel": "postgresql-license", + "OptionGroupMemberships": [ + { + "OptionGroupName": "default:postgres-12", + "Status": "in-sync" + } + ], + "PubliclyAccessible": false, + "StatusInfos": [], + "StorageType": "gp2", + "DbInstancePort": 0, + "StorageEncrypted": false, + "DbiResourceId": "db-ZLVMKFR7AS6SJYTQPXZ4SUH5ZU", + "CACertificateIdentifier": "rds-ca-2019", + "DomainMemberships": [], + "CopyTagsToSnapshot": false, + "MonitoringInterval": 0, + "DBInstanceArn": "arn:aws:rds:us-east-1:111122223333:db:test-db-115", + "IAMDatabaseAuthenticationEnabled": false, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [], + "ProcessorFeatures": [], + "DeletionProtection": false, + "AssociatedRoles": [] + }, + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "postgresql", + "ReadReplicaSourceDBInstanceIdentifier": "test-db-115", + "DBInstanceStatus": "creating", + "MasterUsername": "postgres", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "BackupRetentionPeriod": 7, + "DBSecurityGroups": [], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-aa941691", + "Status": "active" + } + ], + "DBParameterGroups": [ + { + "DBParameterGroupName": "default.postgres12", + "ParameterApplyStatus": "in-sync" + } + ], + "AvailabilityZone": "us-east-1f", + "DBSubnetGroup": { + "DBSubnetGroupName": "default-vpc-99de2fe4", + "DBSubnetGroupDescription": "Created from the RDS Management Console", + "VpcId": "vpc-99de2fe4", + "SubnetGroupStatus": "Complete", + "Subnets": [ + { + "SubnetIdentifier": "subnet-aac6b3e7", + "SubnetAvailabilityZone": { + "Name": "us-east-1c" + }, + "SubnetOutpost": {}, + "SubnetStatus": "Active" + } + ] + }, + "PreferredMaintenanceWindow": "fri:10:05-fri:10:35", + "PendingModifiedValues": { + "MasterUserPassword": "****", + "ProcessorFeatures": [] + }, + "MultiAZ": false, + "EngineVersion": "12.3", + "AutoMinorVersionUpgrade": false, + "ReadReplicaDBInstanceIdentifiers": [], + "ReadReplicaDBClusterIdentifiers": [], + "LicenseModel": "postgresql-license", + "OptionGroupMemberships": [ + { + "OptionGroupName": "default:postgres-12", + "Status": "in-sync" + } + ], + "PubliclyAccessible": false, + "StatusInfos": [], + "StorageType": "gp2", + "DbInstancePort": 0, + "StorageEncrypted": true, + "KmsKeyId": "arn:aws:kms:us-east-1:012345678910:key/abcdef10-1517-49d8-b085-77c50b904149", + "DbiResourceId": "db-ZLVMKFR7AS6SJYTQPXZ4SUH5ZU", + "CACertificateIdentifier": "rds-ca-2019", + "DomainMemberships": [], + "CopyTagsToSnapshot": false, + "MonitoringInterval": 0, + "DBInstanceArn": "arn:aws:rds:us-east-1:111122223333:db:test-db-115", + "IAMDatabaseAuthenticationEnabled": false, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [], + "ProcessorFeatures": [], + "DeletionProtection": false, + "AssociatedRoles": [] + } +]; + +const describeDBEngineVersions = [ + { + "Engine": "postgres", + "EngineVersion": "12.3", + "DBParameterGroupFamily": "postgres9.6", + "DBEngineDescription": "PostgreSQL", + "DBEngineVersionDescription": "PostgreSQL 9.6.1-R1", + "ValidUpgradeTarget": [ + { + "Engine": "postgres", + "EngineVersion": "10.18", + "Description": "PostgreSQL 10.18-R1", + "AutoUpgrade": false, + "IsMajorVersionUpgrade": true + } + ], + "SupportsLogExportsToCloudwatchLogs": true, + "SupportsReadReplica": true, + "SupportedFeatureNames": [], + "Status": "available", + "SupportsParallelQuery": false, + "SupportsGlobalDatabases": false, + "MajorEngineVersion": "9.6" + }, + { + "Engine": "postgres", + "EngineVersion": "9.6.2", + "DBParameterGroupFamily": "postgres9.6", + "DBEngineDescription": "PostgreSQL", + "DBEngineVersionDescription": "PostgreSQL 9.6.2-R1", + "ValidUpgradeTarget": [ + { + "Engine": "postgres", + "EngineVersion": "10.18", + "Description": "PostgreSQL 10.18-R1", + "AutoUpgrade": false, + "IsMajorVersionUpgrade": true + } + ], + "SupportsReadReplica": true, + "SupportedFeatureNames": [], + "Status": "available", + "SupportsParallelQuery": false, + "SupportsGlobalDatabases": false, + "MajorEngineVersion": "9.6" + }, + { + "Engine": "postgres", + "EngineVersion": "9.6.6", + "DBParameterGroupFamily": "postgres9.6", + "DBEngineDescription": "PostgreSQL", + "DBEngineVersionDescription": "PostgreSQL 9.6.6-R1", + "ValidUpgradeTarget": [ + { + "Engine": "postgres", + "EngineVersion": "9.6.8", + "Description": "PostgreSQL 9.6.8-R1", + "AutoUpgrade": false, + "IsMajorVersionUpgrade": false + } + ], + "ExportableLogTypes": [ + "postgresql", + "upgrade" + ], + "SupportsLogExportsToCloudwatchLogs": true, + "SupportsReadReplica": true, + "SupportedFeatureNames": [], + "Status": "available", + "SupportsParallelQuery": false, + "SupportsGlobalDatabases": false, + "MajorEngineVersion": "9.6" + }, + { + "Engine": "postgres", + "EngineVersion": "9.6.16", + "DBParameterGroupFamily": "postgres9.6", + "DBEngineDescription": "PostgreSQL", + "DBEngineVersionDescription": "PostgreSQL 9.6.16-R1", + "ValidUpgradeTarget": [ + { + "Engine": "postgres", + "EngineVersion": "9.6.17", + "Description": "PostgreSQL 9.6.17-R1", + "AutoUpgrade": false, + "IsMajorVersionUpgrade": false + }, + { + "Engine": "postgres", + "EngineVersion": "9.6.18", + "Description": "PostgreSQL 9.6.18-R1", + "AutoUpgrade": false, + "IsMajorVersionUpgrade": false + } + ], + "ExportableLogTypes": [ + "postgresql", + "upgrade" + ], + "SupportsLogExportsToCloudwatchLogs": true, + "SupportsReadReplica": true, + "SupportedFeatureNames": [], + "Status": "available", + "SupportsParallelQuery": false, + "SupportsGlobalDatabases": false, + "MajorEngineVersion": "9.6" + } +] + +const createCache = (rdsInstances, dbEngineVersions) => { + return { + rds: { + describeDBInstances: { + 'us-east-1': { + err: null, + data: rdsInstances + }, + }, + describeDBEngineVersions: { + 'us-east-1': { + err: null, + data: dbEngineVersions + }, + } + } + }; +}; + +const createErrorCache = () => { + return { + rds: { + describeDBInstances: { + 'us-east-1': { + err: { + message: 'error while describing RDS instances' + }, + }, + }, + describeDBEngineVersions: { + 'us-east-1': { + err: { + message: 'error while describing RDS instances' + }, + }, + }, + } + }; +}; + +const createNullCache = () => { + return { + rds: { + describeDBInstances: { + 'us-east-1': null, + }, + describeDBEngineVersions: { + 'us-east-1': null, + } + } + }; +}; + +describe('rdsLoggingEnabled', function () { + describe('run', function () { + it('should PASS if no RDS DB instance is found', function (done) { + const cache = createCache([]); + rdsLoggingEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).includes('No RDS instances found'); + done(); + }); + }); + + it('should PASS if RDS Logging is enabled', function (done) { + const cache = createCache([describeDBInstances[0]], [describeDBEngineVersions[0]]); + rdsLoggingEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).includes('Logging is enabled'); + done(); + }); + }); + + it('should PASS if RDS logging is not enabled and cannot be enabled', function (done) { + const cache = createCache([describeDBInstances[2]], [describeDBEngineVersions[1]]); + rdsLoggingEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).includes('Logging is not enabled, but cannot be enabled'); + done(); + }); + }); + + it('should FAIL if RDS logging is not enabled', function (done) { + const cache = createCache([describeDBInstances[2]], [describeDBEngineVersions[0]]); + rdsLoggingEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).includes('Logging is not enabled'); + done(); + }); + }); + + it('should UNKNOWN if error while describing RDS DB instances or engines', function (done) { + const cache = createErrorCache(); + rdsLoggingEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should not return anything if unable to describe RDS DB instances', function (done) { + const cache = createNullCache(); + rdsLoggingEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + }); +}); From 7ffefbbf2c66dabbcbea66564c9fe485ed4f0686 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 12 Dec 2021 07:13:27 -0800 Subject: [PATCH 003/350] Added spec for rdsPubliclyAccessible plugin --- plugins/aws/rds/rdsPubliclyAccessible.spec.js | 245 ++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 plugins/aws/rds/rdsPubliclyAccessible.spec.js diff --git a/plugins/aws/rds/rdsPubliclyAccessible.spec.js b/plugins/aws/rds/rdsPubliclyAccessible.spec.js new file mode 100644 index 0000000000..eedfdfd47c --- /dev/null +++ b/plugins/aws/rds/rdsPubliclyAccessible.spec.js @@ -0,0 +1,245 @@ +var expect = require('chai').expect; +var rdsPuliclyAccessible = require('./rdsPubliclyAccessible'); + +const describeDBInstances = [ + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "postgres", + "DBInstanceStatus": "creating", + "MasterUsername": "postgres", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "BackupRetentionPeriod": 7, + "DBSecurityGroups": [], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-aa941691", + "Status": "active" + } + ], + "DBParameterGroups": [ + { + "DBParameterGroupName": "default.postgres12", + "ParameterApplyStatus": "in-sync" + } + ], + "AvailabilityZone": "us-east-1f", + "DBSubnetGroup": { + "DBSubnetGroupName": "default-vpc-99de2fe4", + "DBSubnetGroupDescription": "Created from the RDS Management Console", + "VpcId": "vpc-99de2fe4", + "SubnetGroupStatus": "Complete", + "Subnets": [ + { + "SubnetIdentifier": "subnet-aac6b3e7", + "SubnetAvailabilityZone": { + "Name": "us-east-1c" + }, + "SubnetOutpost": {}, + "SubnetStatus": "Active" + } + ] + }, + "PreferredMaintenanceWindow": "fri:10:05-fri:10:35", + "PendingModifiedValues": { + "MasterUserPassword": "****", + "ProcessorFeatures": [] + }, + "MultiAZ": false, + "EngineVersion": "12.3", + "AutoMinorVersionUpgrade": false, + "ReadReplicaDBInstanceIdentifiers": [], + "ReadReplicaDBClusterIdentifiers": [], + "LicenseModel": "postgresql-license", + "OptionGroupMemberships": [ + { + "OptionGroupName": "default:postgres-12", + "Status": "in-sync" + } + ], + "PubliclyAccessible": false, + "StatusInfos": [], + "StorageType": "gp2", + "DbInstancePort": 0, + "StorageEncrypted": true, + "KmsKeyId": "arn:aws:kms:us-east-1:012345678910:key/abcdef10-1517-49d8-b085-77c50b904149", + "DbiResourceId": "db-ZLVMKFR7AS6SJYTQPXZ4SUH5ZU", + "CACertificateIdentifier": "rds-ca-2019", + "DomainMemberships": [], + "CopyTagsToSnapshot": false, + "MonitoringInterval": 0, + "DBInstanceArn": "arn:aws:rds:us-east-1:111122223333:db:test-db-115", + "IAMDatabaseAuthenticationEnabled": false, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [], + "ProcessorFeatures": [], + "DeletionProtection": false, + "AssociatedRoles": [] + }, + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "postgres", + "DBInstanceStatus": "creating", + "MasterUsername": "postgres", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "BackupRetentionPeriod": 2, + "DBSecurityGroups": [], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-aa941691", + "Status": "active" + } + ], + "DBParameterGroups": [ + { + "DBParameterGroupName": "default.postgres12", + "ParameterApplyStatus": "in-sync" + } + ], + "AvailabilityZone": "us-east-1f", + "DBSubnetGroup": { + "DBSubnetGroupName": "default-vpc-99de2fe4", + "DBSubnetGroupDescription": "Created from the RDS Management Console", + "VpcId": "vpc-99de2fe4", + "SubnetGroupStatus": "Complete", + "Subnets": [ + { + "SubnetIdentifier": "subnet-aac6b3e7", + "SubnetAvailabilityZone": { + "Name": "us-east-1c" + }, + "SubnetOutpost": {}, + "SubnetStatus": "Active" + } + ] + }, + "PreferredMaintenanceWindow": "fri:10:05-fri:10:35", + "PendingModifiedValues": { + "MasterUserPassword": "****", + "ProcessorFeatures": [] + }, + "MultiAZ": false, + "EngineVersion": "12.3", + "AutoMinorVersionUpgrade": false, + "ReadReplicaDBInstanceIdentifiers": [], + "ReadReplicaDBClusterIdentifiers": [], + "LicenseModel": "postgresql-license", + "OptionGroupMemberships": [ + { + "OptionGroupName": "default:postgres-12", + "Status": "in-sync" + } + ], + "PubliclyAccessible": true, + "StatusInfos": [], + "StorageType": "gp2", + "DbInstancePort": 0, + "StorageEncrypted": true, + "KmsKeyId": "arn:aws:kms:us-east-1:012345678910:key/88888828-1517-49d8-b085-77c50b904149", + "DbiResourceId": "db-ZLVMKFR7AS6SJYTQPXZ4SUH5ZU", + "CACertificateIdentifier": "rds-ca-2019", + "DomainMemberships": [], + "CopyTagsToSnapshot": false, + "MonitoringInterval": 0, + "DBInstanceArn": "arn:aws:rds:us-east-1:111122223333:db:test-db-115", + "IAMDatabaseAuthenticationEnabled": false, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [], + "ProcessorFeatures": [], + "DeletionProtection": false, + "AssociatedRoles": [] + } +]; + +const createCache = (rdsInstances) => { + return { + rds: { + describeDBInstances: { + 'us-east-1': { + err: null, + data: rdsInstances + }, + }, + } + }; +}; + +const createErrorCache = () => { + return { + rds: { + describeDBInstances: { + 'us-east-1': { + err: { + message: 'error while describing RDS instances' + }, + }, + }, + } + }; +}; + +const createNullCache = () => { + return { + rds: { + describeDBInstances: { + 'us-east-1': null, + }, + } + }; +}; + +describe('rdsPuliclyAccessible', function () { + describe('run', function () { + it('should PASS if no RDS instance is found', function (done) { + const cache = createCache([]); + rdsPuliclyAccessible.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).includes('No RDS instances found'); + done(); + }); + }); + + it('should PASS if RDS instance is not publicly accessible', function (done) { + const cache = createCache([describeDBInstances[0]]); + rdsPuliclyAccessible.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).includes('RDS instance is not publicly accessible'); + done(); + }); + }); + + it('should FAIL if RDS instance is publicly accessible', function (done) { + const cache = createCache([describeDBInstances[1]]); + rdsPuliclyAccessible.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).includes('RDS instance is publicly accessible'); + done(); + }); + }); + + it('should UNKNOWN if error while describing RDS DB instances', function (done) { + const cache = createErrorCache(); + rdsPuliclyAccessible.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should not return anything if unable to describe RDS DB instances', function (done) { + const cache = createNullCache(); + rdsPuliclyAccessible.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + }); +}); From 4dae48660ab2c64766f6214a8c260a371f854fbb Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 12 Dec 2021 10:53:15 -0800 Subject: [PATCH 004/350] Added spec for rdsRestorable plugin --- plugins/aws/rds/rdsRestorable.js | 4 +- plugins/aws/rds/rdsRestorable.spec.js | 634 ++++++++++++++++++++++++++ 2 files changed, 636 insertions(+), 2 deletions(-) create mode 100644 plugins/aws/rds/rdsRestorable.spec.js diff --git a/plugins/aws/rds/rdsRestorable.js b/plugins/aws/rds/rdsRestorable.js index 6b62c8562c..60c2862532 100644 --- a/plugins/aws/rds/rdsRestorable.js +++ b/plugins/aws/rds/rdsRestorable.js @@ -73,7 +73,7 @@ module.exports = { var dbResource = db.DBInstanceArn; if (db.LatestRestorableTime) { - var difference = helpers.daysAgo(db.LatestRestorableTime); + var difference = helpers.hoursBetween(new Date().toISOString(), db.LatestRestorableTime); var returnMsg = 'RDS instance restorable time is ' + difference + ' hours old'; if (difference > 24) { @@ -116,7 +116,7 @@ module.exports = { var dbResourceCluster = dbCluster.DBClusterArn; if (dbCluster.LatestRestorableTime) { - var differenceCluster = helpers.daysAgo(dbCluster.LatestRestorableTime); + var differenceCluster = helpers.hoursBetween(new Date().toISOString(), dbCluster.LatestRestorableTime); var returnMsgCluster = 'RDS cluster restorable time is ' + differenceCluster + ' hours old'; if (differenceCluster > config.rds_restorable_fail) { diff --git a/plugins/aws/rds/rdsRestorable.spec.js b/plugins/aws/rds/rdsRestorable.spec.js new file mode 100644 index 0000000000..18e963c2c5 --- /dev/null +++ b/plugins/aws/rds/rdsRestorable.spec.js @@ -0,0 +1,634 @@ +var expect = require('chai').expect; +var rdsRestorable = require('./rdsRestorable'); + +const describeDBInstances = [ + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "postgres", + "DBInstanceStatus": "creating", + "MasterUsername": "postgres", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "LatestRestorableTime": new Date(new Date().setHours(new Date().getHours() - 2)).toISOString(), + "BackupRetentionPeriod": 7, + "DBSecurityGroups": [], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-aa941691", + "Status": "active" + } + ], + "DBParameterGroups": [ + { + "DBParameterGroupName": "default.postgres12", + "ParameterApplyStatus": "in-sync" + } + ], + "AvailabilityZone": "us-east-1f", + "DBSubnetGroup": { + "DBSubnetGroupName": "default-vpc-99de2fe4", + "DBSubnetGroupDescription": "Created from the RDS Management Console", + "VpcId": "vpc-99de2fe4", + "SubnetGroupStatus": "Complete", + "Subnets": [ + { + "SubnetIdentifier": "subnet-aac6b3e7", + "SubnetAvailabilityZone": { + "Name": "us-east-1c" + }, + "SubnetOutpost": {}, + "SubnetStatus": "Active" + } + ] + }, + "PreferredMaintenanceWindow": "fri:10:05-fri:10:35", + "PendingModifiedValues": { + "MasterUserPassword": "****", + "ProcessorFeatures": [] + }, + "MultiAZ": false, + "EngineVersion": "12.3", + "AutoMinorVersionUpgrade": false, + "ReadReplicaDBInstanceIdentifiers": [], + "ReadReplicaDBClusterIdentifiers": [], + "LicenseModel": "postgresql-license", + "OptionGroupMemberships": [ + { + "OptionGroupName": "default:postgres-12", + "Status": "in-sync" + } + ], + "PubliclyAccessible": false, + "StatusInfos": [], + "StorageType": "gp2", + "DbInstancePort": 0, + "StorageEncrypted": true, + "KmsKeyId": "arn:aws:kms:us-east-1:012345678910:key/abcdef10-1517-49d8-b085-77c50b904149", + "DbiResourceId": "db-ZLVMKFR7AS6SJYTQPXZ4SUH5ZU", + "CACertificateIdentifier": "rds-ca-2019", + "DomainMemberships": [], + "CopyTagsToSnapshot": false, + "MonitoringInterval": 0, + "DBInstanceArn": "arn:aws:rds:us-east-1:111122223333:db:test-db-115", + "IAMDatabaseAuthenticationEnabled": false, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [], + "ProcessorFeatures": [], + "DeletionProtection": false, + "AssociatedRoles": [] + }, + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "postgres", + "DBInstanceStatus": "creating", + "MasterUsername": "postgres", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "LatestRestorableTime": new Date(new Date().setHours(new Date().getHours() - 7)).toISOString(), + "BackupRetentionPeriod": 7, + "DBSecurityGroups": [], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-aa941691", + "Status": "active" + } + ], + "DBParameterGroups": [ + { + "DBParameterGroupName": "default.postgres12", + "ParameterApplyStatus": "in-sync" + } + ], + "AvailabilityZone": "us-east-1f", + "DBSubnetGroup": { + "DBSubnetGroupName": "default-vpc-99de2fe4", + "DBSubnetGroupDescription": "Created from the RDS Management Console", + "VpcId": "vpc-99de2fe4", + "SubnetGroupStatus": "Complete", + "Subnets": [ + { + "SubnetIdentifier": "subnet-aac6b3e7", + "SubnetAvailabilityZone": { + "Name": "us-east-1c" + }, + "SubnetOutpost": {}, + "SubnetStatus": "Active" + } + ] + }, + "PreferredMaintenanceWindow": "fri:10:05-fri:10:35", + "PendingModifiedValues": { + "MasterUserPassword": "****", + "ProcessorFeatures": [] + }, + "MultiAZ": false, + "EngineVersion": "12.3", + "AutoMinorVersionUpgrade": false, + "ReadReplicaDBInstanceIdentifiers": [], + "ReadReplicaDBClusterIdentifiers": [], + "LicenseModel": "postgresql-license", + "OptionGroupMemberships": [ + { + "OptionGroupName": "default:postgres-12", + "Status": "in-sync" + } + ], + "PubliclyAccessible": false, + "StatusInfos": [], + "StorageType": "gp2", + "DbInstancePort": 0, + "StorageEncrypted": true, + "KmsKeyId": "arn:aws:kms:us-east-1:012345678910:key/abcdef10-1517-49d8-b085-77c50b904149", + "DbiResourceId": "db-ZLVMKFR7AS6SJYTQPXZ4SUH5ZU", + "CACertificateIdentifier": "rds-ca-2019", + "DomainMemberships": [], + "CopyTagsToSnapshot": false, + "MonitoringInterval": 0, + "DBInstanceArn": "arn:aws:rds:us-east-1:111122223333:db:test-db-115", + "IAMDatabaseAuthenticationEnabled": false, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [], + "ProcessorFeatures": [], + "DeletionProtection": false, + "AssociatedRoles": [] + }, + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "postgres", + "DBInstanceStatus": "creating", + "MasterUsername": "postgres", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "LatestRestorableTime": new Date(new Date().setHours(new Date().getHours() - 25)).toISOString(), + "BackupRetentionPeriod": 2, + "DBSecurityGroups": [], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-aa941691", + "Status": "active" + } + ], + "DBParameterGroups": [ + { + "DBParameterGroupName": "default.postgres12", + "ParameterApplyStatus": "in-sync" + } + ], + "AvailabilityZone": "us-east-1f", + "DBSubnetGroup": { + "DBSubnetGroupName": "default-vpc-99de2fe4", + "DBSubnetGroupDescription": "Created from the RDS Management Console", + "VpcId": "vpc-99de2fe4", + "SubnetGroupStatus": "Complete", + "Subnets": [ + { + "SubnetIdentifier": "subnet-aac6b3e7", + "SubnetAvailabilityZone": { + "Name": "us-east-1c" + }, + "SubnetOutpost": {}, + "SubnetStatus": "Active" + } + ] + }, + "PreferredMaintenanceWindow": "fri:10:05-fri:10:35", + "PendingModifiedValues": { + "MasterUserPassword": "****", + "ProcessorFeatures": [] + }, + "MultiAZ": false, + "EngineVersion": "12.3", + "AutoMinorVersionUpgrade": false, + "ReadReplicaDBInstanceIdentifiers": [], + "ReadReplicaDBClusterIdentifiers": [], + "LicenseModel": "postgresql-license", + "OptionGroupMemberships": [ + { + "OptionGroupName": "default:postgres-12", + "Status": "in-sync" + } + ], + "PubliclyAccessible": true, + "StatusInfos": [], + "StorageType": "gp2", + "DbInstancePort": 0, + "StorageEncrypted": true, + "KmsKeyId": "arn:aws:kms:us-east-1:012345678910:key/88888828-1517-49d8-b085-77c50b904149", + "DbiResourceId": "db-ZLVMKFR7AS6SJYTQPXZ4SUH5ZU", + "CACertificateIdentifier": "rds-ca-2019", + "DomainMemberships": [], + "CopyTagsToSnapshot": false, + "MonitoringInterval": 0, + "DBInstanceArn": "arn:aws:rds:us-east-1:111122223333:db:test-db-115", + "IAMDatabaseAuthenticationEnabled": false, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [], + "ProcessorFeatures": [], + "DeletionProtection": false, + "AssociatedRoles": [] + }, + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "postgres", + "DBInstanceStatus": "creating", + "MasterUsername": "postgres", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "BackupRetentionPeriod": 2, + "AvailabilityZone": "us-east-1f", + "EngineVersion": "12.3", + "PubliclyAccessible": true, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [] + }, + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "docdb", + "DBInstanceStatus": "creating", + "MasterUsername": "docdb", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "BackupRetentionPeriod": 2, + "AvailabilityZone": "us-east-1f", + "EngineVersion": "12.3", + "PubliclyAccessible": true, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [] + }, + { + "DBInstanceIdentifier": "test-db-115", + "DBInstanceClass": "db.m4.large", + "Engine": "aurora-mysql", + "DBInstanceStatus": "creating", + "MasterUsername": "aurora-mysql", + "DBName": "cloudsploit", + "AllocatedStorage": 20, + "PreferredBackupWindow": "09:07-09:37", + "BackupRetentionPeriod": 2, + "AvailabilityZone": "us-east-1f", + "EngineVersion": "5.7.mysql_aurora.2.07.2", + "PubliclyAccessible": true, + "PerformanceInsightsEnabled": false, + "EnabledCloudwatchLogsExports": [] + } +]; + +const describeDBClusters = [ + { + "AllocatedStorage": 1, + "AvailabilityZones": [ + "us-east-1a", + "us-east-1f", + "us-east-1c" + ], + "BackupRetentionPeriod": 1, + "DBClusterIdentifier": "database-2", + "DBClusterParameterGroup": "default.neptune1", + "DBSubnetGroup": "default-vpc-0f4f4575a74fac014", + "Status": "available", + "EarliestRestorableTime": "2021-11-16T09:01:51.536000+00:00", + "Endpoint": "database-2.cluster-cscif9l5pu36.us-east-1.neptune.amazonaws.com", + "ReaderEndpoint": "database-2.cluster-ro-cscif9l5pu36.us-east-1.neptune.amazonaws.com", + "MultiAZ": false, + "Engine": "neptune", + "EngineVersion": "1.0.5.1", + "LatestRestorableTime": new Date(new Date().setHours(new Date().getHours() - 2)).toISOString(), + "Port": 8182, + "MasterUsername": "admin", + "PreferredBackupWindow": "03:20-03:50", + "PreferredMaintenanceWindow": "fri:09:21-fri:09:51", + "ReadReplicaIdentifiers": [], + "DBClusterMembers": [ + { + "DBInstanceIdentifier": "database-2-instance-1", + "IsClusterWriter": true, + "DBClusterParameterGroupStatus": "in-sync", + "PromotionTier": 1 + } + ], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-0cb6c99daaa6b73c5", + "Status": "active" + } + ], + "HostedZoneId": "ZUFXD4SLT2LS7", + "StorageEncrypted": true, + "KmsKeyId": "arn:aws:kms:us-east-1:000111222333:key/ad013a33-b01d-4d88-ac97-127399c18b3e", + "DbClusterResourceId": "cluster-WNY2ZTZWH4RQ2CTKEEP4GVCPU4", + "DBClusterArn": "arn:aws:rds:us-east-1:000111222333:cluster:database-2", + "AssociatedRoles": [], + }, + { + "AllocatedStorage": 1, + "AvailabilityZones": [ + "us-east-1a", + "us-east-1f", + "us-east-1c" + ], + "BackupRetentionPeriod": 1, + "DBClusterIdentifier": "database-2", + "DBClusterParameterGroup": "default.neptune1", + "DBSubnetGroup": "default-vpc-0f4f4575a74fac014", + "Status": "available", + "EarliestRestorableTime": "2021-11-16T09:01:51.536000+00:00", + "Endpoint": "database-2.cluster-cscif9l5pu36.us-east-1.neptune.amazonaws.com", + "ReaderEndpoint": "database-2.cluster-ro-cscif9l5pu36.us-east-1.neptune.amazonaws.com", + "MultiAZ": false, + "Engine": "neptune", + "EngineVersion": "1.0.5.1", + "LatestRestorableTime": new Date(new Date().setHours(new Date().getHours() - 7)).toISOString(), + "Port": 8182, + "MasterUsername": "admin", + "PreferredBackupWindow": "03:20-03:50", + "PreferredMaintenanceWindow": "fri:09:21-fri:09:51", + "DBClusterMembers": [ + { + "DBInstanceIdentifier": "database-2-instance-1", + "IsClusterWriter": true, + "DBClusterParameterGroupStatus": "in-sync", + "PromotionTier": 1 + } + ], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-0cb6c99daaa6b73c5", + "Status": "active" + } + ], + "HostedZoneId": "ZUFXD4SLT2LS7", + "StorageEncrypted": true, + "KmsKeyId": "arn:aws:kms:us-east-1:000111222333:key/ad013a33-b01d-4d88-ac97-127399c18b3e", + "DbClusterResourceId": "cluster-WNY2ZTZWH4RQ2CTKEEP4GVCPU4", + "DBClusterArn": "arn:aws:rds:us-east-1:000111222333:cluster:database-2", + }, + { + "AllocatedStorage": 1, + "AvailabilityZones": [ + "us-east-1a", + "us-east-1f", + "us-east-1c" + ], + "BackupRetentionPeriod": 1, + "DBClusterIdentifier": "database-2", + "DBClusterParameterGroup": "default.neptune1", + "DBSubnetGroup": "default-vpc-0f4f4575a74fac014", + "Status": "available", + "EarliestRestorableTime": "2021-11-16T09:01:51.536000+00:00", + "Endpoint": "database-2.cluster-cscif9l5pu36.us-east-1.neptune.amazonaws.com", + "ReaderEndpoint": "database-2.cluster-ro-cscif9l5pu36.us-east-1.neptune.amazonaws.com", + "MultiAZ": false, + "Engine": "neptune", + "EngineVersion": "1.0.5.1", + "LatestRestorableTime": new Date(new Date().setHours(new Date().getHours() - 25)).toISOString(), + "Port": 8182, + "MasterUsername": "admin", + "PreferredBackupWindow": "03:20-03:50", + "PreferredMaintenanceWindow": "fri:09:21-fri:09:51", + "DBClusterMembers": [ + { + "DBInstanceIdentifier": "database-2-instance-1", + "IsClusterWriter": true, + "DBClusterParameterGroupStatus": "in-sync", + "PromotionTier": 1 + } + ], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-0cb6c99daaa6b73c5", + "Status": "active" + } + ], + "HostedZoneId": "ZUFXD4SLT2LS7", + "StorageEncrypted": true, + "KmsKeyId": "arn:aws:kms:us-east-1:000111222333:key/ad013a33-b01d-4d88-ac97-127399c18b3e", + "DbClusterResourceId": "cluster-WNY2ZTZWH4RQ2CTKEEP4GVCPU4", + "DBClusterArn": "arn:aws:rds:us-east-1:000111222333:cluster:database-2", + }, + { + "AllocatedStorage": 1, + "AvailabilityZones": [ + "us-east-1a", + "us-east-1f", + "us-east-1c" + ], + "BackupRetentionPeriod": 1, + "DBClusterIdentifier": "database-2", + "DBClusterParameterGroup": "default.neptune1", + "DBSubnetGroup": "default-vpc-0f4f4575a74fac014", + "Status": "available", + "EarliestRestorableTime": "2021-11-16T09:01:51.536000+00:00", + "Endpoint": "database-2.cluster-cscif9l5pu36.us-east-1.neptune.amazonaws.com", + "ReaderEndpoint": "database-2.cluster-ro-cscif9l5pu36.us-east-1.neptune.amazonaws.com", + "MultiAZ": false, + "Engine": "neptune", + "EngineVersion": "1.0.5.1", + "Port": 8182, + "MasterUsername": "admin", + "PreferredBackupWindow": "03:20-03:50", + "PreferredMaintenanceWindow": "fri:09:21-fri:09:51", + "DBClusterMembers": [ + { + "DBInstanceIdentifier": "database-2-instance-1", + "IsClusterWriter": true, + "DBClusterParameterGroupStatus": "in-sync", + "PromotionTier": 1 + } + ], + "VpcSecurityGroups": [ + { + "VpcSecurityGroupId": "sg-0cb6c99daaa6b73c5", + "Status": "active" + } + ], + "HostedZoneId": "ZUFXD4SLT2LS7", + "StorageEncrypted": true, + "KmsKeyId": "arn:aws:kms:us-east-1:000111222333:key/ad013a33-b01d-4d88-ac97-127399c18b3e", + "DbClusterResourceId": "cluster-WNY2ZTZWH4RQ2CTKEEP4GVCPU4", + "DBClusterArn": "arn:aws:rds:us-east-1:000111222333:cluster:database-2", + }, +]; + +const createCache = (rdsInstances, dBClusters) => { + return { + rds: { + describeDBInstances: { + 'us-east-1': { + err: null, + data: rdsInstances + }, + }, + describeDBClusters: { + 'us-east-1': { + err: null, + data: dBClusters + }, + }, + } + }; +}; + +const createErrorCache = () => { + return { + rds: { + describeDBInstances: { + 'us-east-1': { + err: { + message: 'error while describing RDS instances' + }, + }, + }, + describeDBClusters: { + 'us-east-1': { + err: { + message: 'error while describing RDS instances' + }, + }, + }, + } + }; +}; + +const createNullCache = () => { + return { + rds: { + describeDBInstances: { + 'us-east-1': null, + }, + describeDBClusters: { + 'us-east-1': null, + } + } + }; +}; + +describe('rdsRestorable', function () { + describe('run', function () { + it('should PASS if no RDS instance is found', function (done) { + const cache = createCache([]); + rdsRestorable.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).includes('No RDS instances found'); + done(); + }); + }); + + it('should PASS if RDS instance\'s restorable time is less than 6 hours', function (done) { + const cache = createCache([describeDBInstances[0]]); + rdsRestorable.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).includes('RDS instance restorable time is'); + done(); + }); + }); + + it('should PASS with warning if RDS instance have a restorable time of greater than 6 hours but less then 24 hours', function (done) { + const cache = createCache([describeDBInstances[1]]); + rdsRestorable.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(1); + expect(results[0].message).includes('RDS instance restorable time is'); + done(); + }); + }); + + it('should PASS if the db instance is of type docDB', function (done) { + const cache = createCache([describeDBInstances[4]]); + rdsRestorable.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).includes('DocumentDB engine uses incremental backups'); + done(); + }); + }); + + it('should PASS if RDS cluster\'s restorable time is less than 6 hours', function (done) { + const cache = createCache([describeDBInstances[5]], [describeDBClusters[0]]); + rdsRestorable.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).includes('RDS cluster restorable time is'); + done(); + }); + }); + + it('should PASS with warning if RDS cluster have a restorable time of greater than 6 hours but less then 24 hours', function (done) { + const cache = createCache([describeDBInstances[5]], [describeDBClusters[1]]); + rdsRestorable.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(1); + expect(results[0].message).includes('RDS cluster restorable time is'); + done(); + }); + }); + + it('should FAIL if RDS instance have a restorable time of greater than 24 hours', function (done) { + const cache = createCache([describeDBInstances[2]]); + rdsRestorable.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).includes('RDS instance restorable time is'); + done(); + }); + }); + + it('should FAIL if RDS instance does not have a restorable time', function (done) { + const cache = createCache([describeDBInstances[3]]); + rdsRestorable.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).includes('RDS instance does not have a restorable time'); + done(); + }); + }); + + it('should FAIL if RDS db cluster have a restorable time of greater than 24 hours', function (done) { + const cache = createCache([describeDBInstances[5]], [describeDBClusters[2]]); + rdsRestorable.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).includes('RDS cluster restorable time is'); + done(); + }); + }); + + it('should FAIL if RDS db cluster does not have a restorable time', function (done) { + const cache = createCache([describeDBInstances[5]], [describeDBClusters[3]]); + rdsRestorable.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).includes('RDS cluster does not have a restorable time'); + done(); + }); + }); + + it('should UNKNOWN if error while describing RDS instances/clusters', function (done) { + const cache = createErrorCache(); + rdsRestorable.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should not return anything if unable to describe RDS instances/clusters', function (done) { + const cache = createNullCache(); + rdsRestorable.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + }); +}); From 7273e090d9d3fda2764ccfd3b0d1d16bfa7ccd22 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 12 Dec 2021 11:10:32 -0800 Subject: [PATCH 005/350] Added spec for rdsSnapshotEncryption plugin --- plugins/aws/rds/rdsSnapshotEncryption.spec.js | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 plugins/aws/rds/rdsSnapshotEncryption.spec.js diff --git a/plugins/aws/rds/rdsSnapshotEncryption.spec.js b/plugins/aws/rds/rdsSnapshotEncryption.spec.js new file mode 100644 index 0000000000..0b98c3ba47 --- /dev/null +++ b/plugins/aws/rds/rdsSnapshotEncryption.spec.js @@ -0,0 +1,145 @@ +var expect = require('chai').expect; +var rdsSnapshotEncryption = require('./rdsSnapshotEncryption'); + +const describeDBSnapshots = [ + { + "DBSnapshotIdentifier": "rds:database-1-2021-12-12-15-38", + "DBInstanceIdentifier": "database-1", + "SnapshotCreateTime": "2021-12-12T15:39:59.704000+00:00", + "Engine": "mysql", + "AllocatedStorage": 20, + "Status": "available", + "Port": 3306, + "AvailabilityZone": "us-east-1b", + "VpcId": "vpc-0f4f4575a74fac014", + "InstanceCreateTime": "2021-12-12T15:38:41.792000+00:00", + "MasterUsername": "admin", + "EngineVersion": "8.0.23", + "LicenseModel": "general-public-license", + "SnapshotType": "automated", + "OptionGroupName": "default:mysql-8-0", + "PercentProgress": 100, + "StorageType": "gp2", + "Encrypted": true, + "DBSnapshotArn": "arn:aws:rds:us-east-1:101363889637:snapshot:rds:database-1-2021-12-12-15-38", + "IAMDatabaseAuthenticationEnabled": false, + "ProcessorFeatures": [], + "DbiResourceId": "db-SADO63QHGOLHYRTFW57ESZV3YY", + "TagList": [], + "OriginalSnapshotCreateTime": "2021-12-12T15:39:59.704000+00:00", + }, + { + "DBSnapshotIdentifier": "rds:database-1-2021-12-12-15-38", + "DBInstanceIdentifier": "database-1", + "SnapshotCreateTime": "2021-12-12T15:39:59.704000+00:00", + "Engine": "mysql", + "AllocatedStorage": 20, + "Status": "available", + "Port": 3306, + "AvailabilityZone": "us-east-1b", + "VpcId": "vpc-0f4f4575a74fac014", + "InstanceCreateTime": "2021-12-12T15:38:41.792000+00:00", + "MasterUsername": "admin", + "EngineVersion": "8.0.23", + "LicenseModel": "general-public-license", + "SnapshotType": "automated", + "OptionGroupName": "default:mysql-8-0", + "PercentProgress": 100, + "StorageType": "gp2", + "Encrypted": false, + "DBSnapshotArn": "arn:aws:rds:us-east-1:101363889637:snapshot:rds:database-1-2021-12-12-15-38", + "IAMDatabaseAuthenticationEnabled": false, + "ProcessorFeatures": [], + "DbiResourceId": "db-SADO63QHGOLHYRTFW57ESZV3YY", + "TagList": [], + "OriginalSnapshotCreateTime": "2021-12-12T15:39:59.704000+00:00" + } +]; + +const createCache = (dbSnapshots) => { + return { + rds: { + describeDBSnapshots: { + 'us-east-1': { + err: null, + data: dbSnapshots + }, + }, + } + }; +}; + +const createErrorCache = () => { + return { + rds: { + describeDBSnapshots: { + 'us-east-1': { + err: { + message: 'error while describing RDS snapshots' + }, + }, + }, + } + }; +}; + +const createNullCache = () => { + return { + rds: { + describeDBSnapshots: { + 'us-east-1': null, + }, + } + }; +}; + +describe('rdsSnapshotEncryption', function () { + describe('run', function () { + it('should PASS if no RDS instance is found', function (done) { + const cache = createCache([]); + rdsSnapshotEncryption.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).includes('No RDS snapshots found'); + done(); + }); + }); + + it('should PASS if RDS snapshot encryption is enabled', function (done) { + const cache = createCache([describeDBSnapshots[0]]); + rdsSnapshotEncryption.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).includes('Snapshot encryption is enabled via KMS key'); + done(); + }); + }); + + it('should FAIL if RDS snapshot encryption is not enabled', function (done) { + const cache = createCache([describeDBSnapshots[1]]); + rdsSnapshotEncryption.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).includes('Snapshot encryption not enabled'); + done(); + }); + }); + + it('should UNKNOWN if error while describing RDS DB snapshots', function (done) { + const cache = createErrorCache(); + rdsSnapshotEncryption.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should not return anything if unable to describe RDS DB snapshots', function (done) { + const cache = createNullCache(); + rdsSnapshotEncryption.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + }); +}); From a0cd8c96931b92ee22c53e28eec018f5f511a4e1 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Thu, 23 Dec 2021 07:40:26 -0800 Subject: [PATCH 006/350] Incorporated feedback changes --- plugins/aws/rds/rdsSnapshotEncryption.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/aws/rds/rdsSnapshotEncryption.spec.js b/plugins/aws/rds/rdsSnapshotEncryption.spec.js index 0b98c3ba47..070ed6bc97 100644 --- a/plugins/aws/rds/rdsSnapshotEncryption.spec.js +++ b/plugins/aws/rds/rdsSnapshotEncryption.spec.js @@ -21,7 +21,7 @@ const describeDBSnapshots = [ "PercentProgress": 100, "StorageType": "gp2", "Encrypted": true, - "DBSnapshotArn": "arn:aws:rds:us-east-1:101363889637:snapshot:rds:database-1-2021-12-12-15-38", + "DBSnapshotArn": "arn:aws:rds:us-east-1:112233445566:snapshot:rds:database-1-2021-12-12-15-38", "IAMDatabaseAuthenticationEnabled": false, "ProcessorFeatures": [], "DbiResourceId": "db-SADO63QHGOLHYRTFW57ESZV3YY", @@ -47,7 +47,7 @@ const describeDBSnapshots = [ "PercentProgress": 100, "StorageType": "gp2", "Encrypted": false, - "DBSnapshotArn": "arn:aws:rds:us-east-1:101363889637:snapshot:rds:database-1-2021-12-12-15-38", + "DBSnapshotArn": "arn:aws:rds:us-east-1:112233445566:snapshot:rds:database-1-2021-12-12-15-38", "IAMDatabaseAuthenticationEnabled": false, "ProcessorFeatures": [], "DbiResourceId": "db-SADO63QHGOLHYRTFW57ESZV3YY", From e4eb73eea8631bbabcd0486a536cb525f0049ddc Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 16 Jan 2022 02:24:32 -0800 Subject: [PATCH 007/350] Added specs for Azure Network Security Groups plugins --- .../defaultSecurityGroup.spec.js | 217 +++++++++ .../excessiveSecurityGroups.spec.js | 134 +++++ .../networkWatcherEnabled.js | 4 +- .../networkWatcherEnabled.spec.js | 168 +++++++ .../openAllPorts.spec.js | 456 +++++++++++++++++ .../networksecuritygroups/openCIFS.spec.js | 456 +++++++++++++++++ .../networksecuritygroups/openDNS.spec.js | 457 ++++++++++++++++++ .../networksecuritygroups/openDocker.spec.js | 455 +++++++++++++++++ .../networksecuritygroups/openFTP.spec.js | 455 +++++++++++++++++ .../openHadoopNameNode.spec.js | 454 +++++++++++++++++ .../openHadoopNameNodeWebUI.spec.js | 439 +++++++++++++++++ .../networksecuritygroups/openKibana.spec.js | 438 +++++++++++++++++ .../networksecuritygroups/openMySQL.spec.js | 439 +++++++++++++++++ .../networksecuritygroups/openNetBIOS.spec.js | 439 +++++++++++++++++ .../networksecuritygroups/openOracle.spec.js | 438 +++++++++++++++++ .../openOracleAutoDataWarehouse.spec.js | 438 +++++++++++++++++ .../openPostgreSQL.spec.js | 438 +++++++++++++++++ .../networksecuritygroups/openRDP.spec.js | 438 +++++++++++++++++ .../networksecuritygroups/openRPC.spec.js | 438 +++++++++++++++++ .../networksecuritygroups/openSMBoTCP.spec.js | 438 +++++++++++++++++ .../networksecuritygroups/openSMTP.spec.js | 438 +++++++++++++++++ .../openSQLServer.spec.js | 439 +++++++++++++++++ .../networksecuritygroups/openSSH.spec.js | 438 +++++++++++++++++ .../networksecuritygroups/openSalt.spec.js | 439 +++++++++++++++++ .../networksecuritygroups/openTelnet.spec.js | 438 +++++++++++++++++ .../openVNCClient.spec.js | 438 +++++++++++++++++ .../openVNCServer.spec.js | 438 +++++++++++++++++ 27 files changed, 10705 insertions(+), 2 deletions(-) create mode 100644 plugins/azure/networksecuritygroups/defaultSecurityGroup.spec.js create mode 100644 plugins/azure/networksecuritygroups/excessiveSecurityGroups.spec.js create mode 100644 plugins/azure/networksecuritygroups/networkWatcherEnabled.spec.js create mode 100644 plugins/azure/networksecuritygroups/openAllPorts.spec.js create mode 100644 plugins/azure/networksecuritygroups/openCIFS.spec.js create mode 100644 plugins/azure/networksecuritygroups/openDNS.spec.js create mode 100644 plugins/azure/networksecuritygroups/openDocker.spec.js create mode 100644 plugins/azure/networksecuritygroups/openFTP.spec.js create mode 100644 plugins/azure/networksecuritygroups/openHadoopNameNode.spec.js create mode 100644 plugins/azure/networksecuritygroups/openHadoopNameNodeWebUI.spec.js create mode 100644 plugins/azure/networksecuritygroups/openKibana.spec.js create mode 100644 plugins/azure/networksecuritygroups/openMySQL.spec.js create mode 100644 plugins/azure/networksecuritygroups/openNetBIOS.spec.js create mode 100644 plugins/azure/networksecuritygroups/openOracle.spec.js create mode 100644 plugins/azure/networksecuritygroups/openOracleAutoDataWarehouse.spec.js create mode 100644 plugins/azure/networksecuritygroups/openPostgreSQL.spec.js create mode 100644 plugins/azure/networksecuritygroups/openRDP.spec.js create mode 100644 plugins/azure/networksecuritygroups/openRPC.spec.js create mode 100644 plugins/azure/networksecuritygroups/openSMBoTCP.spec.js create mode 100644 plugins/azure/networksecuritygroups/openSMTP.spec.js create mode 100644 plugins/azure/networksecuritygroups/openSQLServer.spec.js create mode 100644 plugins/azure/networksecuritygroups/openSSH.spec.js create mode 100644 plugins/azure/networksecuritygroups/openSalt.spec.js create mode 100644 plugins/azure/networksecuritygroups/openTelnet.spec.js create mode 100644 plugins/azure/networksecuritygroups/openVNCClient.spec.js create mode 100644 plugins/azure/networksecuritygroups/openVNCServer.spec.js diff --git a/plugins/azure/networksecuritygroups/defaultSecurityGroup.spec.js b/plugins/azure/networksecuritygroups/defaultSecurityGroup.spec.js new file mode 100644 index 0000000000..a01005bece --- /dev/null +++ b/plugins/azure/networksecuritygroups/defaultSecurityGroup.spec.js @@ -0,0 +1,217 @@ +var expect = require('chai').expect; +var defaultSecurityGroup = require('./defaultSecurityGroup'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/dce9d1sa-ebf6-437f-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [], + "defaultSecurityRules": [ + { + "name": "DenyAllInBound", + "id": "/subscriptions/dce9d1sa-ebf6-437f-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/dce9d1sa-ebf6-437f-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/dce9d1sa-ebf6-437f-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-7dd8-4d9e-aa71-99cdc67b4506", + "securityRules": [], + "defaultSecurityRules": [ + { + "name": "DenyAllInBound", + "id": "/subscriptions/dce9d1sa-ebf6-437f-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/dce9d1sa-ebf6-437f-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/dce9d1sa-ebf6-437f-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/dce9d1sa-ebf6-437f-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-7dd8-4d9e-aa71-99cdc67b4506", + "securityRules": [], + "defaultSecurityRules": [], + "networkInterfaces": [ + { + "id": "/subscriptions/dce9d1sa-ebf6-437f-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('defaultSecurityGroup', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + defaultSecurityGroup.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + defaultSecurityGroup.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if the Network Security Group has all required default inbound and outbound rules', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + defaultSecurityGroup.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('has all required default inbound and outbound rules'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if Network Security Group does not have required default inbound and outbound rules', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + defaultSecurityGroup.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('does not have required default inbound and outbound rules:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if Network Security Group is missing one or more default inbound or outbound rules', function(done) { + const cache = createCache([networkSecurityGroups[2]]); + defaultSecurityGroup.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('is missing one or more default inbound or outbound rules'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/excessiveSecurityGroups.spec.js b/plugins/azure/networksecuritygroups/excessiveSecurityGroups.spec.js new file mode 100644 index 0000000000..c7995641da --- /dev/null +++ b/plugins/azure/networksecuritygroups/excessiveSecurityGroups.spec.js @@ -0,0 +1,134 @@ +var expect = require('chai').expect; +var excessiveSecurityGroups = require('./excessiveSecurityGroups'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [], + "defaultSecurityRules": [], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [], + "defaultSecurityRules": [], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [], + "defaultSecurityRules": [], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('excessiveSecurityGroups', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + excessiveSecurityGroups.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + excessiveSecurityGroups.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if the count of Network Security Group is Acceptable', function(done) { + const cache = createCache(networkSecurityGroups); + excessiveSecurityGroups.run(cache, { excessive_security_groups_fail: 5, excessive_security_groups_warn: 4 }, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Acceptable number of security groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if the count of Network Security Group is Excessive', function(done) { + const cache = createCache(networkSecurityGroups); + excessiveSecurityGroups.run(cache, { excessive_security_groups_fail: 2, excessive_security_groups_warn: 1 }, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Excessive number of security groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give warning result if the count of Network Security Group is Large', function(done) { + const cache = createCache(networkSecurityGroups); + excessiveSecurityGroups.run(cache, { excessive_security_groups_fail: 3, excessive_security_groups_warn: 2 }, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(1); + expect(results[0].message).to.include('Large number of security groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/networkWatcherEnabled.js b/plugins/azure/networksecuritygroups/networkWatcherEnabled.js index f867deb4d6..6ef9c22d37 100644 --- a/plugins/azure/networksecuritygroups/networkWatcherEnabled.js +++ b/plugins/azure/networksecuritygroups/networkWatcherEnabled.js @@ -44,8 +44,8 @@ module.exports = { } networkWatchers.data.forEach((networkWatcher) => { - if (networkWatcher.provisioningState && - networkWatcher.provisioningState.toLowerCase() == 'succeeded') { + if (networkWatcher.properties.provisioningState && + networkWatcher.properties.provisioningState.toLowerCase() == 'succeeded') { helpers.addResult(results, 0, 'Network Watcher is enabled', location, networkWatcher.id); } else { helpers.addResult(results, 2, 'Network Watcher is not successfully provisioned for the region', location, networkWatcher.id); diff --git a/plugins/azure/networksecuritygroups/networkWatcherEnabled.spec.js b/plugins/azure/networksecuritygroups/networkWatcherEnabled.spec.js new file mode 100644 index 0000000000..54fa27000a --- /dev/null +++ b/plugins/azure/networksecuritygroups/networkWatcherEnabled.spec.js @@ -0,0 +1,168 @@ +var expect = require('chai').expect; +var networkWatcherEnabled = require('./networkWatcherEnabled'); + +const networkWatchers = [ + { + "name": "NetworkWatcher_eastus", + "id": "/subscriptions/def1d0ac-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/NetworkWatcherRG/providers/Microsoft.Network/networkWatchers/NetworkWatcher_eastus", + "etag": "W/\"a12bcd34-5333-4361-a645-0f110712c17e\"", + "type": "Microsoft.Network/networkWatchers", + "location": "eastus", + "properties": { + "provisioningState": "Succeeded", + "runningOperationIds": [] + } + }, + { + "name": "NetworkWatcher_eastus2", + "id": "/subscriptions/def1d0ac-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/NetworkWatcherRG/providers/Microsoft.Network/networkWatchers/NetworkWatcher_eastus2", + "etag": "W/\"s31sde21-686a-449e-b678-1eb7bc38310e\"", + "type": "Microsoft.Network/networkWatchers", + "location": "eastus2", + "properties": { + "provisioningState": "Failed", + "runningOperationIds": [] + } + } +]; + +const virtualNetworks = [ + { + "name": "aadds-vnet", + "id": "/subscriptions/dce7d0ad-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/akhtar-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet", + "etag": "W/\"9647a968-4864-4a13-a916-5cf7dd6fabff\"", + "type": "Microsoft.Network/virtualNetworks", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "e9502313-7cdc-400b-bd64-d97e361e63a4", + "addressSpace": { + "addressPrefixes": [ + "10.0.6.0/24" + ] + }, + "subnets": [ + { + "name": "aadds-subnet", + "id": "/subscriptions/dce7d0ad-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/akhtar-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet", + "etag": "W/\"9647a968-4864-4a13-a916-5cf7dd6fabff\"", + "properties": { + "provisioningState": "Succeeded", + "addressPrefix": "10.0.6.0/24", + "networkSecurityGroup": { + "id": "/subscriptions/dce7d0ad-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/akhtar-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg" + }, + "delegations": [], + "privateEndpointNetworkPolicies": "Enabled", + "privateLinkServiceNetworkPolicies": "Enabled" + }, + "type": "Microsoft.Network/virtualNetworks/subnets" + } + ], + "virtualNetworkPeerings": [], + "enableDdosProtection": false + } +]; + +const createCache = (watchers, virtualNetworks) => { + return { + networkWatchers: { + listAll: { + 'eastus': { + data: watchers + } + } + }, + virtualNetworks: { + listAll: { + 'eastus': { + data: virtualNetworks + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkWatchers: { + listAll: { + 'eastus': {} + } + }, + virtualNetworks: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('networkWatcherEnabled', function() { + describe('run', function() { + it('should give passing result if no Virtual Networks or Network Watchers found', function(done) { + const cache = createCache([], []); + networkWatcherEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No Virtual Networks or Network Watchers in the region'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Watchers', function(done) { + const cache = createErrorCache(); + networkWatcherEnabled.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 Network Watchers:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Virtual Networks', function(done) { + const cache = createCache([], null); + networkWatcherEnabled.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 Virtual Networks:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if no Network Watchers found', function(done) { + const cache = createCache([], [virtualNetworks[0]]); + networkWatcherEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Network Watcher is not enabled in the region'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if Network Watcher is enabled', function(done) { + const cache = createCache([networkWatchers[0]], [virtualNetworks[0]]); + networkWatcherEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Network Watcher is enabled'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if Network Watcher is not enabled', function(done) { + const cache = createCache([networkWatchers[1]], [virtualNetworks[0]]); + networkWatcherEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Network Watcher is not successfully provisioned for the region'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openAllPorts.spec.js b/plugins/azure/networksecuritygroups/openAllPorts.spec.js new file mode 100644 index 0000000000..37cc89334b --- /dev/null +++ b/plugins/azure/networksecuritygroups/openAllPorts.spec.js @@ -0,0 +1,456 @@ +var expect = require('chai').expect; +var openAllPorts = require('./openAllPorts'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "5986", + "5987", + "*" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [], + "defaultSecurityRules": [], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openAllPorts', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openAllPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openAllPorts.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if the Network Security Group has no public open ports found', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openAllPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if the Network Security Group has some public open ports', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openAllPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openCIFS.spec.js b/plugins/azure/networksecuritygroups/openCIFS.spec.js new file mode 100644 index 0000000000..363539e006 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openCIFS.spec.js @@ -0,0 +1,456 @@ +var expect = require('chai').expect; +var openCIFS = require('./openCIFS'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "5986", + "5987", + "445" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [], + "defaultSecurityRules": [], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openCIFS', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openCIFS.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openCIFS.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if the UDP port 445 for CIFS is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openCIFS.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if the UDP port 445 for CIFS is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openCIFS.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openDNS.spec.js b/plugins/azure/networksecuritygroups/openDNS.spec.js new file mode 100644 index 0000000000..45ca5cffcc --- /dev/null +++ b/plugins/azure/networksecuritygroups/openDNS.spec.js @@ -0,0 +1,457 @@ +var expect = require('chai').expect; +var openDNS = require('./openDNS'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "5986", + "5987", + "445", + "53" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [], + "defaultSecurityRules": [], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openDNS', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openDNS.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openDNS.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if the TCP or UDP port 53 for DNS is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openDNS.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if the TCP or UDP port 53 for DNS is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openDNS.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openDocker.spec.js b/plugins/azure/networksecuritygroups/openDocker.spec.js new file mode 100644 index 0000000000..e295daa456 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openDocker.spec.js @@ -0,0 +1,455 @@ +var expect = require('chai').expect; +var openDocker = require('./openDocker'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "2375", + "2376" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [], + "defaultSecurityRules": [], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openDocker', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openDocker.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openDocker.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if Docker port 2375 or 2376 is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openDocker.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if Docker port 2375 or 2376 is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openDocker.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openFTP.spec.js b/plugins/azure/networksecuritygroups/openFTP.spec.js new file mode 100644 index 0000000000..2e21588956 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openFTP.spec.js @@ -0,0 +1,455 @@ +var expect = require('chai').expect; +var openFTP = require('./openFTP'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "20", + "21" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [], + "defaultSecurityRules": [], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openFTP', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openFTP.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openFTP.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 20 or 21 for FTP is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openFTP.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 20 or 21 for FTP is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openFTP.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openHadoopNameNode.spec.js b/plugins/azure/networksecuritygroups/openHadoopNameNode.spec.js new file mode 100644 index 0000000000..fc9fb9a733 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openHadoopNameNode.spec.js @@ -0,0 +1,454 @@ +var expect = require('chai').expect; +var openHadoopNameNode = require('./openHadoopNameNode'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "8020" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [], + "defaultSecurityRules": [], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openHadoopNameNode', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openHadoopNameNode.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openHadoopNameNode.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 8020 for HDFS NameNode metadata service is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openHadoopNameNode.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 8020 for HDFS NameNode metadata service is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openHadoopNameNode.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openHadoopNameNodeWebUI.spec.js b/plugins/azure/networksecuritygroups/openHadoopNameNodeWebUI.spec.js new file mode 100644 index 0000000000..b5a7473708 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openHadoopNameNodeWebUI.spec.js @@ -0,0 +1,439 @@ +var expect = require('chai').expect; +var openHadoopNameNodeWebUI = require('./openHadoopNameNodeWebUI'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "50070", + "50470" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openHadoopNameNodeWebUI', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openHadoopNameNodeWebUI.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openHadoopNameNodeWebUI.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 50070 and 50470 for Hadoop/HDFS NameNode WebUI service is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openHadoopNameNodeWebUI.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 50070 and 50470 for Hadoop/HDFS NameNode WebUI service is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openHadoopNameNodeWebUI.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openKibana.spec.js b/plugins/azure/networksecuritygroups/openKibana.spec.js new file mode 100644 index 0000000000..8757678ff4 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openKibana.spec.js @@ -0,0 +1,438 @@ +var expect = require('chai').expect; +var openKibana = require('./openKibana'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "5601" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openKibana', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openKibana.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openKibana.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 5601 for Kibana is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openKibana.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 5601 for Kibana is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openKibana.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openMySQL.spec.js b/plugins/azure/networksecuritygroups/openMySQL.spec.js new file mode 100644 index 0000000000..47d56ffcf6 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openMySQL.spec.js @@ -0,0 +1,439 @@ +var expect = require('chai').expect; +var openMySQL = require('./openMySQL'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "4333", + "3306" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openMySQL', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openMySQL.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openMySQL.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 4333 or 3306 for MySQL is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openMySQL.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 4333 or 3306 for MySQL is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openMySQL.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openNetBIOS.spec.js b/plugins/azure/networksecuritygroups/openNetBIOS.spec.js new file mode 100644 index 0000000000..087f1fa1b1 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openNetBIOS.spec.js @@ -0,0 +1,439 @@ +var expect = require('chai').expect; +var openNetBIOS = require('./openNetBIOS'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "137", + "138" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openNetBIOS', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openNetBIOS.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openNetBIOS.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if UDP port 137 or 138 for NetBIOS is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openNetBIOS.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if UDP port 137 or 138 for NetBIOS is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openNetBIOS.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openOracle.spec.js b/plugins/azure/networksecuritygroups/openOracle.spec.js new file mode 100644 index 0000000000..8a4e6c7a32 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openOracle.spec.js @@ -0,0 +1,438 @@ +var expect = require('chai').expect; +var openOracle = require('./openOracle'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "1521" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openOracle', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openOracle.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openOracle.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 1521 for Oracle is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openOracle.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 1521 for Oracle is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openOracle.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openOracleAutoDataWarehouse.spec.js b/plugins/azure/networksecuritygroups/openOracleAutoDataWarehouse.spec.js new file mode 100644 index 0000000000..481f198930 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openOracleAutoDataWarehouse.spec.js @@ -0,0 +1,438 @@ +var expect = require('chai').expect; +var openOracleAutoDataWarehouse = require('./openOracleAutoDataWarehouse'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "1522" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openOracleAutoDataWarehouse', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openOracleAutoDataWarehouse.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openOracleAutoDataWarehouse.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 1522 for Oracle Auto Data Warehouse is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openOracleAutoDataWarehouse.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 1522 for Oracle Auto Data Warehouse is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openOracleAutoDataWarehouse.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openPostgreSQL.spec.js b/plugins/azure/networksecuritygroups/openPostgreSQL.spec.js new file mode 100644 index 0000000000..eb06bc6bd9 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openPostgreSQL.spec.js @@ -0,0 +1,438 @@ +var expect = require('chai').expect; +var openPostgreSQL = require('./openPostgreSQL'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "5432" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openPostgreSQL', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openPostgreSQL.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openPostgreSQL.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 5432 for PostgreSQL is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openPostgreSQL.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 5432 for PostgreSQL is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openPostgreSQL.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openRDP.spec.js b/plugins/azure/networksecuritygroups/openRDP.spec.js new file mode 100644 index 0000000000..147da26f15 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openRDP.spec.js @@ -0,0 +1,438 @@ +var expect = require('chai').expect; +var openRDP = require('./openRDP'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "3389" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openRDP', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openRDP.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openRDP.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 3389 for RDP is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openRDP.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 3389 for RDP is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openRDP.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openRPC.spec.js b/plugins/azure/networksecuritygroups/openRPC.spec.js new file mode 100644 index 0000000000..28a9d0b288 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openRPC.spec.js @@ -0,0 +1,438 @@ +var expect = require('chai').expect; +var openRPC = require('./openRPC'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "135" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openRPC', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openRPC.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openRPC.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 135 for RPC is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openRPC.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 135 for RPC is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openRPC.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openSMBoTCP.spec.js b/plugins/azure/networksecuritygroups/openSMBoTCP.spec.js new file mode 100644 index 0000000000..f565e20cb2 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openSMBoTCP.spec.js @@ -0,0 +1,438 @@ +var expect = require('chai').expect; +var openSMBoTCP = require('./openSMBoTCP'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "445" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openSMBoTCP', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openSMBoTCP.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openSMBoTCP.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 445 for Windows SMB over TCP is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openSMBoTCP.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 445 for Windows SMB over TCP is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openSMBoTCP.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openSMTP.spec.js b/plugins/azure/networksecuritygroups/openSMTP.spec.js new file mode 100644 index 0000000000..4775fa84fb --- /dev/null +++ b/plugins/azure/networksecuritygroups/openSMTP.spec.js @@ -0,0 +1,438 @@ +var expect = require('chai').expect; +var openSMTP = require('./openSMTP'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "25" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openSMTP', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openSMTP.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openSMTP.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 25 for SMTP is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openSMTP.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 25 for SMTP is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openSMTP.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openSQLServer.spec.js b/plugins/azure/networksecuritygroups/openSQLServer.spec.js new file mode 100644 index 0000000000..5e1af57442 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openSQLServer.spec.js @@ -0,0 +1,439 @@ +var expect = require('chai').expect; +var openSQLServer = require('./openSQLServer'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "1433", + "1434" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openSQLServer', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openSQLServer.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openSQLServer.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 1433 or UDP port 1434 for SQL Server is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openSQLServer.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 1433 or UDP port 1434 for SQL Server is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openSQLServer.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openSSH.spec.js b/plugins/azure/networksecuritygroups/openSSH.spec.js new file mode 100644 index 0000000000..cbea11a4e3 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openSSH.spec.js @@ -0,0 +1,438 @@ +var expect = require('chai').expect; +var openSSH = require('./openSSH'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "22" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openSSH', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openSSH.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openSSH.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 22 for SSH is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openSSH.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 22 for SSH is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openSSH.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openSalt.spec.js b/plugins/azure/networksecuritygroups/openSalt.spec.js new file mode 100644 index 0000000000..bdafbe87de --- /dev/null +++ b/plugins/azure/networksecuritygroups/openSalt.spec.js @@ -0,0 +1,439 @@ +var expect = require('chai').expect; +var openSalt = require('./openSalt'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "4505", + "4506" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openSalt', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openSalt.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openSalt.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 4505 or 4506 for the Salt master is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openSalt.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 4505 or 4506 for the Salt master is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openSalt.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openTelnet.spec.js b/plugins/azure/networksecuritygroups/openTelnet.spec.js new file mode 100644 index 0000000000..bfbeda5196 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openTelnet.spec.js @@ -0,0 +1,438 @@ +var expect = require('chai').expect; +var openTelnet = require('./openTelnet'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "23" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openTelnet', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openTelnet.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openTelnet.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 23 for Telnet is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openTelnet.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 23 for Telnet is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openTelnet.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openVNCClient.spec.js b/plugins/azure/networksecuritygroups/openVNCClient.spec.js new file mode 100644 index 0000000000..59171b8696 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openVNCClient.spec.js @@ -0,0 +1,438 @@ +var expect = require('chai').expect; +var openVNCClient = require('./openVNCClient'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "5500" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openVNCClient', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openVNCClient.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openVNCClient.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 5500 for VNC Client is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openVNCClient.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 5500 for VNC Client is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openVNCClient.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/openVNCServer.spec.js b/plugins/azure/networksecuritygroups/openVNCServer.spec.js new file mode 100644 index 0000000000..0875388225 --- /dev/null +++ b/plugins/azure/networksecuritygroups/openVNCServer.spec.js @@ -0,0 +1,438 @@ +var expect = require('chai').expect; +var openVNCServer = require('./openVNCServer'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "CorpNetSaw", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 201, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "*", + "sourcePortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [ + "5900" + ], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + ], + "defaultSecurityRules": [ + { + "name": "AllowVnetInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowAzureLoadBalancerInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow inbound traffic from azure load balancer", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 65001, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllInBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all inbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowVnetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to all VMs in VNET", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 65000, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "AllowInternetOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Allow outbound traffic from all VMs to Internet", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 65001, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + }, + { + "name": "DenyAllOutBound", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", + "properties": { + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [] + } + } + ], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openVNCServer', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openVNCServer.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openVNCServer.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if TCP port 5900 for VNC Server is not open to public', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openVNCServer.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No public open ports found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if TCP port 5900 for VNC Server is open to public', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openVNCServer.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file From 936363474a89e950b68b29e8e814c8cb7233cc8f Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Wed, 19 Jan 2022 16:15:39 +0500 Subject: [PATCH 008/350] Update plugins/azure/networksecuritygroups/networkWatcherEnabled.js --- plugins/azure/networksecuritygroups/networkWatcherEnabled.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/azure/networksecuritygroups/networkWatcherEnabled.js b/plugins/azure/networksecuritygroups/networkWatcherEnabled.js index 6ef9c22d37..bfcb599444 100644 --- a/plugins/azure/networksecuritygroups/networkWatcherEnabled.js +++ b/plugins/azure/networksecuritygroups/networkWatcherEnabled.js @@ -44,7 +44,8 @@ module.exports = { } networkWatchers.data.forEach((networkWatcher) => { - if (networkWatcher.properties.provisioningState && + if (networkWatcher.properties && + networkWatcher.properties.provisioningState && networkWatcher.properties.provisioningState.toLowerCase() == 'succeeded') { helpers.addResult(results, 0, 'Network Watcher is enabled', location, networkWatcher.id); } else { From a30d5526febeafb5642aef2dda913568a8fe8407 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Wed, 26 Jan 2022 14:13:10 -0800 Subject: [PATCH 009/350] Incoporated feedback changes --- .../defaultSecurityGroup.spec.js | 64 +--- .../openAllPorts.spec.js | 292 +----------------- .../networksecuritygroups/openCIFS.spec.js | 292 +----------------- .../networksecuritygroups/openDNS.spec.js | 292 +----------------- .../networksecuritygroups/openDocker.spec.js | 278 +---------------- .../networksecuritygroups/openFTP.spec.js | 292 +----------------- .../openHadoopNameNode.spec.js | 284 +---------------- .../openHadoopNameNodeWebUI.spec.js | 278 +---------------- .../networksecuritygroups/openKibana.spec.js | 278 +---------------- .../networksecuritygroups/openMySQL.spec.js | 278 +---------------- .../networksecuritygroups/openNetBIOS.spec.js | 278 +---------------- .../networksecuritygroups/openOracle.spec.js | 278 +---------------- .../openOracleAutoDataWarehouse.spec.js | 278 +---------------- .../openPostgreSQL.spec.js | 278 +---------------- .../networksecuritygroups/openRDP.spec.js | 278 +---------------- .../networksecuritygroups/openRPC.spec.js | 278 +---------------- .../networksecuritygroups/openSMBoTCP.spec.js | 278 +---------------- .../networksecuritygroups/openSMTP.spec.js | 278 +---------------- .../openSQLServer.spec.js | 278 +---------------- .../networksecuritygroups/openSSH.spec.js | 278 +---------------- .../networksecuritygroups/openSalt.spec.js | 278 +---------------- .../networksecuritygroups/openTelnet.spec.js | 278 +---------------- .../openVNCClient.spec.js | 278 +---------------- .../openVNCServer.spec.js | 278 +---------------- 24 files changed, 58 insertions(+), 6462 deletions(-) diff --git a/plugins/azure/networksecuritygroups/defaultSecurityGroup.spec.js b/plugins/azure/networksecuritygroups/defaultSecurityGroup.spec.js index a01005bece..2b9b710b78 100644 --- a/plugins/azure/networksecuritygroups/defaultSecurityGroup.spec.js +++ b/plugins/azure/networksecuritygroups/defaultSecurityGroup.spec.js @@ -11,8 +11,7 @@ const networkSecurityGroups = [ "provisioningState": "Succeeded", "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", "securityRules": [], - "defaultSecurityRules": [ - { + "defaultSecurityRules": [{ "name": "DenyAllInBound", "id": "/subscriptions/dce9d1sa-ebf6-437f-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", @@ -68,54 +67,27 @@ const networkSecurityGroups = [ "provisioningState": "Succeeded", "resourceGuid": "12a3456b-7dd8-4d9e-aa71-99cdc67b4506", "securityRules": [], - "defaultSecurityRules": [ - { - "name": "DenyAllInBound", - "id": "/subscriptions/dce9d1sa-ebf6-437f-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { + "defaultSecurityRules": [{ "name": "DenyAllOutBound", "id": "/subscriptions/dce9d1sa-ebf6-437f-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] + "provisioningState": "Succeeded", + "description": "Deny all outbound traffic", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Deny", + "priority": 65500, + "direction": "Outbound", } - } - ], - "networkInterfaces": [ - { + }], + "networkInterfaces": [{ "id": "/subscriptions/dce9d1sa-ebf6-437f-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" - } - ] + }] }, { "name": "test-vm-1-nsg", @@ -127,11 +99,9 @@ const networkSecurityGroups = [ "resourceGuid": "12a3456b-7dd8-4d9e-aa71-99cdc67b4506", "securityRules": [], "defaultSecurityRules": [], - "networkInterfaces": [ - { + "networkInterfaces": [{ "id": "/subscriptions/dce9d1sa-ebf6-437f-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" - } - ] + }] } ]; diff --git a/plugins/azure/networksecuritygroups/openAllPorts.spec.js b/plugins/azure/networksecuritygroups/openAllPorts.spec.js index 37cc89334b..342a81b6e4 100644 --- a/plugins/azure/networksecuritygroups/openAllPorts.spec.js +++ b/plugins/azure/networksecuritygroups/openAllPorts.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -228,155 +87,6 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "networkInterfaces": [ - { - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" - } - ] - }, - { - "name": "test-vm-1-nsg", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups", - "location": "eastus", - "provisioningState": "Succeeded", - "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", - "securityRules": [], "defaultSecurityRules": [], "networkInterfaces": [ { diff --git a/plugins/azure/networksecuritygroups/openCIFS.spec.js b/plugins/azure/networksecuritygroups/openCIFS.spec.js index 363539e006..54133a29aa 100644 --- a/plugins/azure/networksecuritygroups/openCIFS.spec.js +++ b/plugins/azure/networksecuritygroups/openCIFS.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -228,155 +87,6 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "networkInterfaces": [ - { - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" - } - ] - }, - { - "name": "test-vm-1-nsg", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups", - "location": "eastus", - "provisioningState": "Succeeded", - "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", - "securityRules": [], "defaultSecurityRules": [], "networkInterfaces": [ { diff --git a/plugins/azure/networksecuritygroups/openDNS.spec.js b/plugins/azure/networksecuritygroups/openDNS.spec.js index 45ca5cffcc..f52c2bbbb6 100644 --- a/plugins/azure/networksecuritygroups/openDNS.spec.js +++ b/plugins/azure/networksecuritygroups/openDNS.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -229,155 +88,6 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "networkInterfaces": [ - { - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" - } - ] - }, - { - "name": "test-vm-1-nsg", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups", - "location": "eastus", - "provisioningState": "Succeeded", - "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", - "securityRules": [], "defaultSecurityRules": [], "networkInterfaces": [ { diff --git a/plugins/azure/networksecuritygroups/openDocker.spec.js b/plugins/azure/networksecuritygroups/openDocker.spec.js index e295daa456..9554915318 100644 --- a/plugins/azure/networksecuritygroups/openDocker.spec.js +++ b/plugins/azure/networksecuritygroups/openDocker.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -227,140 +86,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openFTP.spec.js b/plugins/azure/networksecuritygroups/openFTP.spec.js index 2e21588956..554c446c44 100644 --- a/plugins/azure/networksecuritygroups/openFTP.spec.js +++ b/plugins/azure/networksecuritygroups/openFTP.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -227,155 +86,6 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "networkInterfaces": [ - { - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" - } - ] - }, - { - "name": "test-vm-1-nsg", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups", - "location": "eastus", - "provisioningState": "Succeeded", - "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", - "securityRules": [], "defaultSecurityRules": [], "networkInterfaces": [ { diff --git a/plugins/azure/networksecuritygroups/openHadoopNameNode.spec.js b/plugins/azure/networksecuritygroups/openHadoopNameNode.spec.js index fc9fb9a733..3a2529e464 100644 --- a/plugins/azure/networksecuritygroups/openHadoopNameNode.spec.js +++ b/plugins/azure/networksecuritygroups/openHadoopNameNode.spec.js @@ -54,140 +54,7 @@ const networkSecurityGroups = [ } } ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -226,155 +93,6 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "networkInterfaces": [ - { - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" - } - ] - }, - { - "name": "test-vm-1-nsg", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups", - "location": "eastus", - "provisioningState": "Succeeded", - "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", - "securityRules": [], "defaultSecurityRules": [], "networkInterfaces": [ { diff --git a/plugins/azure/networksecuritygroups/openHadoopNameNodeWebUI.spec.js b/plugins/azure/networksecuritygroups/openHadoopNameNodeWebUI.spec.js index b5a7473708..f18b0e9d2e 100644 --- a/plugins/azure/networksecuritygroups/openHadoopNameNodeWebUI.spec.js +++ b/plugins/azure/networksecuritygroups/openHadoopNameNodeWebUI.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -227,140 +86,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openKibana.spec.js b/plugins/azure/networksecuritygroups/openKibana.spec.js index 8757678ff4..819d24f1b1 100644 --- a/plugins/azure/networksecuritygroups/openKibana.spec.js +++ b/plugins/azure/networksecuritygroups/openKibana.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -226,140 +85,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openMySQL.spec.js b/plugins/azure/networksecuritygroups/openMySQL.spec.js index 47d56ffcf6..182ca013bc 100644 --- a/plugins/azure/networksecuritygroups/openMySQL.spec.js +++ b/plugins/azure/networksecuritygroups/openMySQL.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -227,140 +86,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openNetBIOS.spec.js b/plugins/azure/networksecuritygroups/openNetBIOS.spec.js index 087f1fa1b1..cd4e2ee392 100644 --- a/plugins/azure/networksecuritygroups/openNetBIOS.spec.js +++ b/plugins/azure/networksecuritygroups/openNetBIOS.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -227,140 +86,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openOracle.spec.js b/plugins/azure/networksecuritygroups/openOracle.spec.js index 8a4e6c7a32..2b1a55133c 100644 --- a/plugins/azure/networksecuritygroups/openOracle.spec.js +++ b/plugins/azure/networksecuritygroups/openOracle.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -226,140 +85,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openOracleAutoDataWarehouse.spec.js b/plugins/azure/networksecuritygroups/openOracleAutoDataWarehouse.spec.js index 481f198930..2fc0752cad 100644 --- a/plugins/azure/networksecuritygroups/openOracleAutoDataWarehouse.spec.js +++ b/plugins/azure/networksecuritygroups/openOracleAutoDataWarehouse.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -226,140 +85,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openPostgreSQL.spec.js b/plugins/azure/networksecuritygroups/openPostgreSQL.spec.js index eb06bc6bd9..aaaccc5b6c 100644 --- a/plugins/azure/networksecuritygroups/openPostgreSQL.spec.js +++ b/plugins/azure/networksecuritygroups/openPostgreSQL.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -226,140 +85,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openRDP.spec.js b/plugins/azure/networksecuritygroups/openRDP.spec.js index 147da26f15..65c9522a71 100644 --- a/plugins/azure/networksecuritygroups/openRDP.spec.js +++ b/plugins/azure/networksecuritygroups/openRDP.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -226,140 +85,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openRPC.spec.js b/plugins/azure/networksecuritygroups/openRPC.spec.js index 28a9d0b288..de81fbe552 100644 --- a/plugins/azure/networksecuritygroups/openRPC.spec.js +++ b/plugins/azure/networksecuritygroups/openRPC.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -226,140 +85,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openSMBoTCP.spec.js b/plugins/azure/networksecuritygroups/openSMBoTCP.spec.js index f565e20cb2..274ea8866b 100644 --- a/plugins/azure/networksecuritygroups/openSMBoTCP.spec.js +++ b/plugins/azure/networksecuritygroups/openSMBoTCP.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -226,140 +85,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openSMTP.spec.js b/plugins/azure/networksecuritygroups/openSMTP.spec.js index 4775fa84fb..914423a8d5 100644 --- a/plugins/azure/networksecuritygroups/openSMTP.spec.js +++ b/plugins/azure/networksecuritygroups/openSMTP.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -226,140 +85,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openSQLServer.spec.js b/plugins/azure/networksecuritygroups/openSQLServer.spec.js index 5e1af57442..1d3aecbe5e 100644 --- a/plugins/azure/networksecuritygroups/openSQLServer.spec.js +++ b/plugins/azure/networksecuritygroups/openSQLServer.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -227,140 +86,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openSSH.spec.js b/plugins/azure/networksecuritygroups/openSSH.spec.js index cbea11a4e3..f4bd8ecc35 100644 --- a/plugins/azure/networksecuritygroups/openSSH.spec.js +++ b/plugins/azure/networksecuritygroups/openSSH.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -226,140 +85,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openSalt.spec.js b/plugins/azure/networksecuritygroups/openSalt.spec.js index bdafbe87de..4b191998cb 100644 --- a/plugins/azure/networksecuritygroups/openSalt.spec.js +++ b/plugins/azure/networksecuritygroups/openSalt.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -227,140 +86,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openTelnet.spec.js b/plugins/azure/networksecuritygroups/openTelnet.spec.js index bfbeda5196..1e9259996b 100644 --- a/plugins/azure/networksecuritygroups/openTelnet.spec.js +++ b/plugins/azure/networksecuritygroups/openTelnet.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -226,140 +85,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openVNCClient.spec.js b/plugins/azure/networksecuritygroups/openVNCClient.spec.js index 59171b8696..59686d5947 100644 --- a/plugins/azure/networksecuritygroups/openVNCClient.spec.js +++ b/plugins/azure/networksecuritygroups/openVNCClient.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -226,140 +85,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" diff --git a/plugins/azure/networksecuritygroups/openVNCServer.spec.js b/plugins/azure/networksecuritygroups/openVNCServer.spec.js index 0875388225..cdec216423 100644 --- a/plugins/azure/networksecuritygroups/openVNCServer.spec.js +++ b/plugins/azure/networksecuritygroups/openVNCServer.spec.js @@ -26,10 +26,6 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 301, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } }, { @@ -47,147 +43,10 @@ const networkSecurityGroups = [ "access": "Allow", "priority": 201, "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] } } ], + "defaultSecurityRules": [], "subnets": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" @@ -226,140 +85,7 @@ const networkSecurityGroups = [ } }, ], - "defaultSecurityRules": [ - { - "name": "AllowVnetInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowAzureLoadBalancerInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowAzureLoadBalancerInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow inbound traffic from azure load balancer", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "AzureLoadBalancer", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 65001, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllInBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllInBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all inbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Inbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowVnetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowVnetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to all VMs in VNET", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "VirtualNetwork", - "destinationAddressPrefix": "VirtualNetwork", - "access": "Allow", - "priority": 65000, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "AllowInternetOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/AllowInternetOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Allow outbound traffic from all VMs to Internet", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "Internet", - "access": "Allow", - "priority": 65001, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - }, - { - "name": "DenyAllOutBound", - "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg/defaultSecurityRules/DenyAllOutBound", - "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", - "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules", - "properties": { - "provisioningState": "Succeeded", - "description": "Deny all outbound traffic", - "protocol": "*", - "sourcePortRange": "*", - "destinationPortRange": "*", - "sourceAddressPrefix": "*", - "destinationAddressPrefix": "*", - "access": "Deny", - "priority": 65500, - "direction": "Outbound", - "sourcePortRanges": [], - "destinationPortRanges": [], - "sourceAddressPrefixes": [], - "destinationAddressPrefixes": [] - } - } - ], + "defaultSecurityRules": [], "networkInterfaces": [ { "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" From d65876cb3129efaa49670ad01c2f05f6180b298e Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Sun, 30 Jan 2022 04:25:43 +0500 Subject: [PATCH 010/350] GCP remediation function and remediation for bucket versioning plugin --- helpers/google/index.js | 31 +++++++++++++++++ index.js | 8 +++++ plugins/google/storage/bucketVersioning.js | 40 +++++++++++++++++++++- 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/helpers/google/index.js b/helpers/google/index.js index 426225a2b2..04b9836f67 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -408,11 +408,42 @@ var execute = function(LocalGoogleConfig, collection, service, callObj, callKey, } }; +function remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, callback) { + makeRemediationCall(config, method, body, baseUrl, resource, function(err) { + if (err) { + remediation_file['remediate']['actions'][pluginName]['error'] = err; + return callback(err, null); + } + + let action = body; + return callback(null, action); + }); +} +function makeRemediationCall(GoogleConfig, method, body, baseUrl, resource, callCb) { + authenticate(GoogleConfig).then(client => { + if (resource) { + baseUrl = baseUrl.replace(/\{resource\}/g, resource); + } + client.request({ + url: baseUrl, + method, + data: body + }, function(err, res) { + if (err) { + callCb(err); + } else if (res && res.data) { + callCb(null); + } + }); + }); +} + var helpers = { regions: regions, MAX_REGIONS_AT_A_TIME: 6, authenticate: authenticate, processCall: processCall, + remediatePlugin: remediatePlugin, PROTECTION_LEVELS: ['unspecified', 'default', 'cloudcmek', 'cloudhsm', 'external'], }; diff --git a/index.js b/index.js index 921d28f8b6..1668488c1c 100644 --- a/index.js +++ b/index.js @@ -258,6 +258,14 @@ if (settings.remediate && settings.remediate.length) { DirectoryID: config.credentials.azure_remediate.directory_id, SubscriptionID: config.credentials.azure_remediate.subscription_id }; + } else if (config.credentials.google_remediate && config.credentials.google_remediate.project) { + checkRequiredKeys(config.credentials.google, ['client_email', 'private_key']); + cloudConfig = { + type: 'service_account', + project: config.credentials.google.project, + client_email: config.credentials.google.client_email, + private_key: config.credentials.google.private_key, + }; } else { console.error('ERROR: Config file does not contain any valid credential configs for remediation.'); process.exit(1); diff --git a/plugins/google/storage/bucketVersioning.js b/plugins/google/storage/bucketVersioning.js index 2be55f0866..1e7aa85d0b 100644 --- a/plugins/google/storage/bucketVersioning.js +++ b/plugins/google/storage/bucketVersioning.js @@ -10,7 +10,12 @@ module.exports = { link: 'https://cloud.google.com/storage/docs/using-object-versioning', recommended_action: 'Bucket Versioning can only be enabled by using the Command Line Interface, use this command to enable Versioning: gsutil versioning set on gs://[BUCKET_NAME]', apis: ['buckets:list'], - + remediation_min_version: '202201291836', + remediation_description: 'Bucket versioning will be enabled on storage buckets', + apis_remediate: ['buckets:list'], + actions: {remediate:['storage.buckets.update'], rollback:['storage.buckets.update']}, + permissions: {remediate: ['storage.buckets.setIamPolicy', 'storage.buckets.update'], rollback: ['storage.buckets.setIamPolicy','storage.buckets.update']}, + realtime_triggers: ['storage.buckets.update', 'storage.buckets.create'], run: function(cache, settings, callback) { var results = []; @@ -55,5 +60,38 @@ module.exports = { // Global checking goes here callback(null, results, source); }); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'bucketVersioning'; + var baseUrl = 'https://storage.googleapis.com/storage/v1/{resource}'; + var method = 'PUT'; + var putCall = this.actions.remediate; + + // create the params necessary for the remediation + var body = { + versioning: { + enabled: true + } + }; + // logging + remediation_file['pre_remediate']['actions'][pluginName][resource] = { + 'Versioning': 'Disabled' + }; + + helpers.remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } }; \ No newline at end of file From 96ba3f76f325c71e837d693a89d1342616f482c4 Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Sun, 30 Jan 2022 04:33:32 +0500 Subject: [PATCH 011/350] GCP remediation for bucket uniform acces plugin --- plugins/google/storage/bucketUniformAccess.js | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/plugins/google/storage/bucketUniformAccess.js b/plugins/google/storage/bucketUniformAccess.js index 130dbd7f4a..c6db8a6699 100644 --- a/plugins/google/storage/bucketUniformAccess.js +++ b/plugins/google/storage/bucketUniformAccess.js @@ -10,6 +10,12 @@ module.exports = { link: 'https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use', recommended_action: 'Make sure that storage buckets have uniform level access enabled', apis: ['buckets:list'], + remediation_min_version: '202201291836', + remediation_description: 'Unfiorm Level Access will be enabled on storage buckets', + apis_remediate: ['buckets:list'], + actions: {remediate:['storage.buckets.update'], rollback:['storage.buckets.update']}, + permissions: {remediate: ['storage.buckets.setIamPolicy', 'storage.buckets.update'], rollback: ['storage.buckets.setIamPolicy','storage.buckets.update']}, + realtime_triggers: ['storage.buckets.update', 'storage.buckets.create'], run: function(cache, settings, callback) { var results = []; @@ -56,5 +62,40 @@ module.exports = { // Global checking goes here callback(null, results, source); }); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'bucketUniformAccess'; + var baseUrl = 'https://storage.googleapis.com/storage/v1/{resource}'; + var method = 'PUT'; + var putCall = this.actions.remediate; + + // create the params necessary for the remediation + var body = { + iamConfiguration: { + uniformBucketLevelAccess: { + enabled: true + } + } + }; + // logging + remediation_file['pre_remediate']['actions'][pluginName][resource] = { + 'UniformBucketLevelAccess': 'Disabled' + }; + + helpers.remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } }; \ No newline at end of file From 6c76b14699f1c0510c4c56755da9555a5483c89c Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Sun, 30 Jan 2022 04:33:32 +0500 Subject: [PATCH 012/350] GCP remediation for bucket uniform acces plugin --- plugins/google/storage/bucketUniformAccess.js | 41 +++++++++++++++++++ plugins/google/storage/bucketVersioning.js | 40 +----------------- 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/plugins/google/storage/bucketUniformAccess.js b/plugins/google/storage/bucketUniformAccess.js index 130dbd7f4a..c6db8a6699 100644 --- a/plugins/google/storage/bucketUniformAccess.js +++ b/plugins/google/storage/bucketUniformAccess.js @@ -10,6 +10,12 @@ module.exports = { link: 'https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use', recommended_action: 'Make sure that storage buckets have uniform level access enabled', apis: ['buckets:list'], + remediation_min_version: '202201291836', + remediation_description: 'Unfiorm Level Access will be enabled on storage buckets', + apis_remediate: ['buckets:list'], + actions: {remediate:['storage.buckets.update'], rollback:['storage.buckets.update']}, + permissions: {remediate: ['storage.buckets.setIamPolicy', 'storage.buckets.update'], rollback: ['storage.buckets.setIamPolicy','storage.buckets.update']}, + realtime_triggers: ['storage.buckets.update', 'storage.buckets.create'], run: function(cache, settings, callback) { var results = []; @@ -56,5 +62,40 @@ module.exports = { // Global checking goes here callback(null, results, source); }); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'bucketUniformAccess'; + var baseUrl = 'https://storage.googleapis.com/storage/v1/{resource}'; + var method = 'PUT'; + var putCall = this.actions.remediate; + + // create the params necessary for the remediation + var body = { + iamConfiguration: { + uniformBucketLevelAccess: { + enabled: true + } + } + }; + // logging + remediation_file['pre_remediate']['actions'][pluginName][resource] = { + 'UniformBucketLevelAccess': 'Disabled' + }; + + helpers.remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } }; \ No newline at end of file diff --git a/plugins/google/storage/bucketVersioning.js b/plugins/google/storage/bucketVersioning.js index 1e7aa85d0b..2be55f0866 100644 --- a/plugins/google/storage/bucketVersioning.js +++ b/plugins/google/storage/bucketVersioning.js @@ -10,12 +10,7 @@ module.exports = { link: 'https://cloud.google.com/storage/docs/using-object-versioning', recommended_action: 'Bucket Versioning can only be enabled by using the Command Line Interface, use this command to enable Versioning: gsutil versioning set on gs://[BUCKET_NAME]', apis: ['buckets:list'], - remediation_min_version: '202201291836', - remediation_description: 'Bucket versioning will be enabled on storage buckets', - apis_remediate: ['buckets:list'], - actions: {remediate:['storage.buckets.update'], rollback:['storage.buckets.update']}, - permissions: {remediate: ['storage.buckets.setIamPolicy', 'storage.buckets.update'], rollback: ['storage.buckets.setIamPolicy','storage.buckets.update']}, - realtime_triggers: ['storage.buckets.update', 'storage.buckets.create'], + run: function(cache, settings, callback) { var results = []; @@ -60,38 +55,5 @@ module.exports = { // Global checking goes here callback(null, results, source); }); - }, - remediate: function(config, cache, settings, resource, callback) { - var remediation_file = settings.remediation_file; - - // inputs specific to the plugin - var pluginName = 'bucketVersioning'; - var baseUrl = 'https://storage.googleapis.com/storage/v1/{resource}'; - var method = 'PUT'; - var putCall = this.actions.remediate; - - // create the params necessary for the remediation - var body = { - versioning: { - enabled: true - } - }; - // logging - remediation_file['pre_remediate']['actions'][pluginName][resource] = { - 'Versioning': 'Disabled' - }; - - helpers.remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, function(err, action) { - if (err) return callback(err); - if (action) action.action = putCall; - - - remediation_file['post_remediate']['actions'][pluginName][resource] = action; - remediation_file['remediate']['actions'][pluginName][resource] = { - 'Action': 'Enabled' - }; - - callback(null, action); - }); } }; \ No newline at end of file From 960a1cd607737de254c1cc9f0830c212832066cc Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Mon, 7 Feb 2022 02:27:47 +0500 Subject: [PATCH 013/350] Remediation function only, moved remediations to separate branches --- plugins/google/storage/bucketUniformAccess.js | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/plugins/google/storage/bucketUniformAccess.js b/plugins/google/storage/bucketUniformAccess.js index c6db8a6699..130dbd7f4a 100644 --- a/plugins/google/storage/bucketUniformAccess.js +++ b/plugins/google/storage/bucketUniformAccess.js @@ -10,12 +10,6 @@ module.exports = { link: 'https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use', recommended_action: 'Make sure that storage buckets have uniform level access enabled', apis: ['buckets:list'], - remediation_min_version: '202201291836', - remediation_description: 'Unfiorm Level Access will be enabled on storage buckets', - apis_remediate: ['buckets:list'], - actions: {remediate:['storage.buckets.update'], rollback:['storage.buckets.update']}, - permissions: {remediate: ['storage.buckets.setIamPolicy', 'storage.buckets.update'], rollback: ['storage.buckets.setIamPolicy','storage.buckets.update']}, - realtime_triggers: ['storage.buckets.update', 'storage.buckets.create'], run: function(cache, settings, callback) { var results = []; @@ -62,40 +56,5 @@ module.exports = { // Global checking goes here callback(null, results, source); }); - }, - remediate: function(config, cache, settings, resource, callback) { - var remediation_file = settings.remediation_file; - - // inputs specific to the plugin - var pluginName = 'bucketUniformAccess'; - var baseUrl = 'https://storage.googleapis.com/storage/v1/{resource}'; - var method = 'PUT'; - var putCall = this.actions.remediate; - - // create the params necessary for the remediation - var body = { - iamConfiguration: { - uniformBucketLevelAccess: { - enabled: true - } - } - }; - // logging - remediation_file['pre_remediate']['actions'][pluginName][resource] = { - 'UniformBucketLevelAccess': 'Disabled' - }; - - helpers.remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, function(err, action) { - if (err) return callback(err); - if (action) action.action = putCall; - - - remediation_file['post_remediate']['actions'][pluginName][resource] = action; - remediation_file['remediate']['actions'][pluginName][resource] = { - 'Action': 'Enabled' - }; - - callback(null, action); - }); } }; \ No newline at end of file From 64402abd604129d82068f697658bd28ac3d3323e Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Mon, 7 Feb 2022 02:34:50 +0500 Subject: [PATCH 014/350] GCP Remediation for Bucket Versioning plugin --- plugins/google/storage/bucketVersioning.js | 42 ++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/plugins/google/storage/bucketVersioning.js b/plugins/google/storage/bucketVersioning.js index 2be55f0866..ab17dccb77 100644 --- a/plugins/google/storage/bucketVersioning.js +++ b/plugins/google/storage/bucketVersioning.js @@ -10,7 +10,12 @@ module.exports = { link: 'https://cloud.google.com/storage/docs/using-object-versioning', recommended_action: 'Bucket Versioning can only be enabled by using the Command Line Interface, use this command to enable Versioning: gsutil versioning set on gs://[BUCKET_NAME]', apis: ['buckets:list'], - + remediation_min_version: '202201291836', + remediation_description: 'Bucket versioning will be enabled on storage buckets', + apis_remediate: ['buckets:list'], + actions: {remediate:['storage.buckets.update'], rollback:['storage.buckets.update']}, + permissions: {remediate: ['storage.buckets.setIamPolicy', 'storage.buckets.update'], rollback: ['storage.buckets.setIamPolicy','storage.buckets.update']}, + realtime_triggers: ['storage.buckets.update', 'storage.buckets.create'], run: function(cache, settings, callback) { var results = []; @@ -55,5 +60,38 @@ module.exports = { // Global checking goes here callback(null, results, source); }); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'bucketVersioning'; + var baseUrl = 'https://storage.googleapis.com/storage/v1/{resource}'; + var method = 'PUT'; + var putCall = this.actions.remediate; + + // create the params necessary for the remediation + var body = { + versioning: { + enabled: true + } + }; + // logging + remediation_file['pre_remediate']['actions'][pluginName][resource] = { + 'Versioning': 'Disabled' + }; + + helpers.remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } -}; \ No newline at end of file +}; From 8a75b8c767b1f1edc91b4ac087efaa2a3c284e06 Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Mon, 14 Feb 2022 04:23:39 +0500 Subject: [PATCH 015/350] added remediateOrgPolicy method to remediate organization policies --- helpers/google/functions.js | 4 ++-- helpers/google/index.js | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/helpers/google/functions.js b/helpers/google/functions.js index ecd858d658..fde1635423 100644 --- a/helpers/google/functions.js +++ b/helpers/google/functions.js @@ -280,7 +280,7 @@ function createResourceName(resourceType, resourceId, project, locationType, loc return resourceName; } -function checkOrgPolicy(orgPolicies, constraintName, constraintType, shouldBeEnabled, ifNotFound, displayName, results) { +function checkOrgPolicy(orgPolicies, constraintName, constraintType, shouldBeEnabled, ifNotFound, displayName, results, resource) { let isEnabled = false; if (orgPolicies && orgPolicies.policies) { let policyToCheck = orgPolicies.policies.find(policy => ( @@ -311,7 +311,7 @@ function checkOrgPolicy(orgPolicies, constraintName, constraintType, shouldBeEna message = shouldBeEnabled ? failureMessage : successMessage; } - shared.addResult(results, status, message, 'global'); + shared.addResult(results, status, message, 'global', resource); } diff --git a/helpers/google/index.js b/helpers/google/index.js index 04b9836f67..9e6d57cbd7 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -408,6 +408,32 @@ var execute = function(LocalGoogleConfig, collection, service, callObj, callKey, } }; +function remediateOrgPolicy (config, constraintName, policyType, policyValue, resource, remediation_file, putCall, pluginName, callback) { + + // url to update org policy + var baseUrl = 'https://cloudresourcemanager.googleapis.com/v1/{resource}:setOrgPolicy'; + var method = 'POST'; + + // create the params necessary for the remediation + var body; + if (policyType == "booleanPolicy") { + body = { + policy: { + constraint: constraintName, + booleanPolicy: { + enforced: policyValue + } + } + } + } + // logging + remediation_file['pre_remediate']['actions'][pluginName][resource] = { + constraintName : policyValue ? 'Disabled' : 'Enabled' + }; + + remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, callback) +} + function remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, callback) { makeRemediationCall(config, method, body, baseUrl, resource, function(err) { if (err) { @@ -444,6 +470,7 @@ var helpers = { authenticate: authenticate, processCall: processCall, remediatePlugin: remediatePlugin, + remediateOrgPolicy: remediateOrgPolicy, PROTECTION_LEVELS: ['unspecified', 'default', 'cloudcmek', 'cloudhsm', 'external'], }; From e9f9342ffbfd09fe701240446c7e6c5e2ba3bed9 Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Mon, 14 Feb 2022 04:42:06 +0500 Subject: [PATCH 016/350] GCP remediation for Disable Serial Port Access plugin --- .../disableSerialPortAccess.js | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/plugins/google/cloudresourcemanager/disableSerialPortAccess.js b/plugins/google/cloudresourcemanager/disableSerialPortAccess.js index 97f3d47ffc..9ad2c9bec7 100644 --- a/plugins/google/cloudresourcemanager/disableSerialPortAccess.js +++ b/plugins/google/cloudresourcemanager/disableSerialPortAccess.js @@ -9,11 +9,26 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Disable VM serial port access" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], + remediation_min_version: '202202140432', + apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], + actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, + permissions: {remediate: ['orgpolicy.policy.set'], rollback: ['orgpolicy.policy.set']}, run: function(cache, settings, callback) { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,8 +45,29 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'compute.disableSerialPortAccess', 'booleanPolicy', true, false, 'Disable VM serial port access', results); + helpers.checkOrgPolicy(orgPolicies, 'compute.disableSerialPortAccess', 'booleanPolicy', true, false, 'Disable VM serial port access', results, organization); return callback(null, results, source); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'disableSerialPortAccess'; + + var putCall = this.actions.remediate; + + helpers.remediateOrgPolicy(config, 'constraints/compute.disableSerialPortAccess', 'booleanPolicy', true, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } }; \ No newline at end of file From 0f880ec071b24f9c58c2ca642fa5c6396e2f92ae Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Mon, 14 Feb 2022 04:23:39 +0500 Subject: [PATCH 017/350] added remediateOrgPolicy method to remediate organization policies --- helpers/google/functions.js | 4 ++-- helpers/google/index.js | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/helpers/google/functions.js b/helpers/google/functions.js index ecd858d658..fde1635423 100644 --- a/helpers/google/functions.js +++ b/helpers/google/functions.js @@ -280,7 +280,7 @@ function createResourceName(resourceType, resourceId, project, locationType, loc return resourceName; } -function checkOrgPolicy(orgPolicies, constraintName, constraintType, shouldBeEnabled, ifNotFound, displayName, results) { +function checkOrgPolicy(orgPolicies, constraintName, constraintType, shouldBeEnabled, ifNotFound, displayName, results, resource) { let isEnabled = false; if (orgPolicies && orgPolicies.policies) { let policyToCheck = orgPolicies.policies.find(policy => ( @@ -311,7 +311,7 @@ function checkOrgPolicy(orgPolicies, constraintName, constraintType, shouldBeEna message = shouldBeEnabled ? failureMessage : successMessage; } - shared.addResult(results, status, message, 'global'); + shared.addResult(results, status, message, 'global', resource); } diff --git a/helpers/google/index.js b/helpers/google/index.js index 04b9836f67..1cfbd05e12 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -408,6 +408,32 @@ var execute = function(LocalGoogleConfig, collection, service, callObj, callKey, } }; +function remediateOrgPolicy(config, constraintName, policyType, policyValue, resource, remediation_file, putCall, pluginName, callback) { + + // url to update org policy + var baseUrl = 'https://cloudresourcemanager.googleapis.com/v1/{resource}:setOrgPolicy'; + var method = 'POST'; + + // create the params necessary for the remediation + var body; + if (policyType == 'booleanPolicy') { + body = { + policy: { + constraint: constraintName, + booleanPolicy: { + enforced: policyValue + } + } + }; + } + // logging + remediation_file['pre_remediate']['actions'][pluginName][resource] = { + constraintName: policyValue ? 'Disabled' : 'Enabled' + }; + + remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, callback); +} + function remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, callback) { makeRemediationCall(config, method, body, baseUrl, resource, function(err) { if (err) { @@ -444,6 +470,7 @@ var helpers = { authenticate: authenticate, processCall: processCall, remediatePlugin: remediatePlugin, + remediateOrgPolicy: remediateOrgPolicy, PROTECTION_LEVELS: ['unspecified', 'default', 'cloudcmek', 'cloudhsm', 'external'], }; From 6dc9c43904d7a98f8a962099be9d521575f4abad Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Mon, 14 Feb 2022 05:00:37 +0500 Subject: [PATCH 018/350] GCP remediation for Disabled Default Encryption plugin --- .../disableDefaultEncryption.js | 42 ++++++++++++++++++- .../disableDefaultEncryption.spec.js | 15 +++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/plugins/google/cloudresourcemanager/disableDefaultEncryption.js b/plugins/google/cloudresourcemanager/disableDefaultEncryption.js index df3d488d30..1924ec5793 100644 --- a/plugins/google/cloudresourcemanager/disableDefaultEncryption.js +++ b/plugins/google/cloudresourcemanager/disableDefaultEncryption.js @@ -9,11 +9,28 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Restrict Default Google-Managed Encryption for Cloud SQL Instances" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], + remediation_min_version: '202202140432', + remediation_description: 'The "Restrict Default Google-Managed Encryption for Cloud SQL Instances" constraint will be enforced at the organization level.', + apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], + actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, + permissions: {remediate: ['orgpolicy.policy.set'], rollback: ['orgpolicy.policy.set']}, + realtime_triggers: ['SetOrgPolicy'], run: function(cache, settings, callback) { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,8 +47,29 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'sql.disableDefaultEncryptionCreation', 'booleanPolicy', true, false, 'Restrict Default Google-Managed Encryption for Cloud SQL Instances', results); + helpers.checkOrgPolicy(orgPolicies, 'sql.disableDefaultEncryptionCreation', 'booleanPolicy', true, false, 'Restrict Default Google-Managed Encryption for Cloud SQL Instances', results, organization); return callback(null, results, source); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'disableDefaultEncryption'; + + var putCall = this.actions.remediate; + + helpers.remediateOrgPolicy(config, 'constraints/sql.disableDefaultEncryptionCreation', 'booleanPolicy', true, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } -}; \ No newline at end of file +}; diff --git a/plugins/google/cloudresourcemanager/disableDefaultEncryption.spec.js b/plugins/google/cloudresourcemanager/disableDefaultEncryption.spec.js index 9dde870cbc..c8fd3c517e 100644 --- a/plugins/google/cloudresourcemanager/disableDefaultEncryption.spec.js +++ b/plugins/google/cloudresourcemanager/disableDefaultEncryption.spec.js @@ -4,6 +4,21 @@ var plugin = require('./disableDefaultEncryption'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + + }, listOrgPolicies: { 'global': { err: err, From 7d4c65c7712ee0256f78d0d5a37a39fa431ddc89 Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Mon, 14 Feb 2022 04:49:18 +0500 Subject: [PATCH 019/350] GCP remediation for Detailed Audit Logging Mode plugin --- .../detailedAuditLoggingMode.js | 40 ++++++++++++++++++- .../detailedAuditLoggingMode.spec.js | 14 +++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/plugins/google/cloudresourcemanager/detailedAuditLoggingMode.js b/plugins/google/cloudresourcemanager/detailedAuditLoggingMode.js index fdf1664507..784d4da169 100644 --- a/plugins/google/cloudresourcemanager/detailedAuditLoggingMode.js +++ b/plugins/google/cloudresourcemanager/detailedAuditLoggingMode.js @@ -9,11 +9,28 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Detailed Audit Logging Mode" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], + remediation_min_version: '202202140432', + remediation_description: 'The "Detailed Audit Logging Mode" constraint will be enforced at the organization level.', + apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], + actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, + permissions: {remediate: ['orgpolicy.policy.set'], rollback: ['orgpolicy.policy.set']}, + realtime_triggers: ['SetOrgPolicy'], run: function(cache, settings, callback) { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,8 +47,29 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'gcp.detailedAuditLoggingMode', 'booleanPolicy', true, false, 'Detailed Audit Logging Mode', results); + helpers.checkOrgPolicy(orgPolicies, 'gcp.detailedAuditLoggingMode', 'booleanPolicy', true, false, 'Detailed Audit Logging Mode', results, organization); return callback(null, results, source); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'detailedAuditLoggingMode'; + + var putCall = this.actions.remediate; + + helpers.remediateOrgPolicy(config, 'constraints/gcp.detailedAuditLoggingMode', 'booleanPolicy', true, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } }; \ No newline at end of file diff --git a/plugins/google/cloudresourcemanager/detailedAuditLoggingMode.spec.js b/plugins/google/cloudresourcemanager/detailedAuditLoggingMode.spec.js index 25c1cb8323..628b904261 100644 --- a/plugins/google/cloudresourcemanager/detailedAuditLoggingMode.spec.js +++ b/plugins/google/cloudresourcemanager/detailedAuditLoggingMode.spec.js @@ -4,6 +4,20 @@ var plugin = require('./detailedAuditLoggingMode'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, From b2f9c6ef0f9d6e6ccecda2caa7231aee636a27f9 Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Mon, 14 Feb 2022 04:54:31 +0500 Subject: [PATCH 020/350] GCP remediation for Detailed Automatic IAM Grants plugin --- .../disableAutomaticIAMGrants.js | 41 ++++++++++++++++++- .../disableAutomaticIAMGrants.spec.js | 15 +++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/plugins/google/cloudresourcemanager/disableAutomaticIAMGrants.js b/plugins/google/cloudresourcemanager/disableAutomaticIAMGrants.js index fecb11722e..7270b6909a 100644 --- a/plugins/google/cloudresourcemanager/disableAutomaticIAMGrants.js +++ b/plugins/google/cloudresourcemanager/disableAutomaticIAMGrants.js @@ -9,11 +9,29 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Disable Automatic IAM Grants for Default Service Accounts" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], + remediation_min_version: '202202140432', + remediation_description: 'The "Disable Automatic IAM Grants for Default Service Accounts" constraint will be enforced at the organization level.', + apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], + actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, + permissions: {remediate: ['orgpolicy.policy.set'], rollback: ['orgpolicy.policy.set']}, + realtime_triggers: ['SetOrgPolicy'], run: function(cache, settings, callback) { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,8 +48,29 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'iam.automaticIamGrantsForDefaultServiceAccounts', 'booleanPolicy', true, false, 'Disable Automatic IAM Grants for Default Service Accounts', results); + helpers.checkOrgPolicy(orgPolicies, 'iam.automaticIamGrantsForDefaultServiceAccounts', 'booleanPolicy', true, false, 'Disable Automatic IAM Grants for Default Service Accounts', results, organization); return callback(null, results, source); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'disableAutomaticIAMGrants'; + + var putCall = this.actions.remediate; + + helpers.remediateOrgPolicy(config, 'constraints/iam.automaticIamGrantsForDefaultServiceAccounts', 'booleanPolicy', true, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } }; \ No newline at end of file diff --git a/plugins/google/cloudresourcemanager/disableAutomaticIAMGrants.spec.js b/plugins/google/cloudresourcemanager/disableAutomaticIAMGrants.spec.js index 18ac8f1a0a..1de54b5216 100644 --- a/plugins/google/cloudresourcemanager/disableAutomaticIAMGrants.spec.js +++ b/plugins/google/cloudresourcemanager/disableAutomaticIAMGrants.spec.js @@ -4,6 +4,21 @@ var plugin = require('./disableAutomaticIAMGrants'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, From 43e8c32e0722b76e98adf237248d6ecabe86779f Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Mon, 21 Feb 2022 03:41:06 +0500 Subject: [PATCH 021/350] GCP Remediations for Cloud Resource Manager Plugins --- .../computeAllowedExternalIPs.js | 13 +++++- .../computeAllowedExternalIPs.spec.js | 14 +++++++ .../disableDefaultEncryption.spec.js | 1 - .../disableGuestAttributes.js | 41 ++++++++++++++++++- .../disableGuestAttributes.spec.js | 14 +++++++ .../disableIdentityClusterCreation.js | 39 +++++++++++++++++- .../disableIdentityClusterCreation.spec.js | 14 +++++++ .../disableKeyCreation.js | 39 +++++++++++++++++- .../disableKeyCreation.spec.js | 14 +++++++ .../cloudresourcemanager/disableKeyUpload.js | 39 +++++++++++++++++- .../disableKeyUpload.spec.js | 14 +++++++ .../disableSerialPortAccess.spec.js | 1 - .../disableVMIPForwarding.js | 13 +++++- .../disableVMIPForwarding.spec.js | 14 +++++++ .../locationBasedRestriction.js | 15 ++++++- .../locationBasedRestriction.spec.js | 14 +++++++ .../cloudresourcemanager/requireOsLogin.js | 40 +++++++++++++++++- .../requireOsLogin.spec.js | 14 +++++++ .../restrictAuthorizedNetworks.js | 40 +++++++++++++++++- .../restrictAuthorizedNetworks.spec.js | 14 +++++++ .../restrictLoadBalancerCreation.js | 13 +++++- .../restrictLoadBalancerCreation.spec.js | 14 +++++++ .../restrictSharedVPCSubnetworks.js | 13 +++++- .../restrictSharedVPCSubnetworks.spec.js | 14 +++++++ .../restrictVPCPeering.js | 13 +++++- .../restrictVPCPeering.spec.js | 14 +++++++ .../restrictVPNPeerIPs.js | 13 +++++- .../restrictVPNPeerIPs.spec.js | 14 +++++++ .../skipDefaultNetworkCreation.js | 40 +++++++++++++++++- .../skipDefaultNetworkCreation.spec.js | 14 +++++++ .../trustedImageProjects.js | 13 +++++- .../trustedImageProjects.spec.js | 14 +++++++ .../uniformBucketLevelAccess.js | 40 +++++++++++++++++- .../uniformBucketLevelAccess.spec.js | 14 +++++++ 34 files changed, 631 insertions(+), 19 deletions(-) diff --git a/plugins/google/cloudresourcemanager/computeAllowedExternalIPs.js b/plugins/google/cloudresourcemanager/computeAllowedExternalIPs.js index 9cb2cf2c0c..15ef0a65fd 100644 --- a/plugins/google/cloudresourcemanager/computeAllowedExternalIPs.js +++ b/plugins/google/cloudresourcemanager/computeAllowedExternalIPs.js @@ -14,6 +14,17 @@ module.exports = { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); if (!listOrgPolicies) return callback(null, results, source); @@ -29,7 +40,7 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'compute.vmExternalIpAccess', 'listPolicy', true, false, 'Define Allowed External IPs for VM Instances', results); + helpers.checkOrgPolicy(orgPolicies, 'compute.vmExternalIpAccess', 'listPolicy', true, false, 'Define Allowed External IPs for VM Instances', results, organization); return callback(null, results, source); } diff --git a/plugins/google/cloudresourcemanager/computeAllowedExternalIPs.spec.js b/plugins/google/cloudresourcemanager/computeAllowedExternalIPs.spec.js index 4926a51e3b..8229e3a76c 100644 --- a/plugins/google/cloudresourcemanager/computeAllowedExternalIPs.spec.js +++ b/plugins/google/cloudresourcemanager/computeAllowedExternalIPs.spec.js @@ -4,6 +4,20 @@ var plugin = require('./computeAllowedExternalIPs'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, diff --git a/plugins/google/cloudresourcemanager/disableDefaultEncryption.spec.js b/plugins/google/cloudresourcemanager/disableDefaultEncryption.spec.js index c8fd3c517e..a1dd4e40f8 100644 --- a/plugins/google/cloudresourcemanager/disableDefaultEncryption.spec.js +++ b/plugins/google/cloudresourcemanager/disableDefaultEncryption.spec.js @@ -17,7 +17,6 @@ const createCache = (err, data) => { ], err: null } - }, listOrgPolicies: { 'global': { diff --git a/plugins/google/cloudresourcemanager/disableGuestAttributes.js b/plugins/google/cloudresourcemanager/disableGuestAttributes.js index e3fbb995aa..935ca3d040 100644 --- a/plugins/google/cloudresourcemanager/disableGuestAttributes.js +++ b/plugins/google/cloudresourcemanager/disableGuestAttributes.js @@ -9,11 +9,29 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Disable Guest Attributes of Compute Engine Metadata" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], + remediation_min_version: '202202200432', + remediation_description: 'The "Disable Guest Attributes of Compute Engine Metadata" constraint will be enforced at the organization level.', + apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], + actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, + permissions: {remediate: ['orgpolicy.policy.set'], rollback: ['orgpolicy.policy.set']}, + realtime_triggers: ['SetOrgPolicy'], + run: function(cache, settings, callback) { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,8 +48,29 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'compute.disableGuestAttributesAccess', 'booleanPolicy', true, false, 'Disable Guest Attributes of Compute Engine Metadata', results); + helpers.checkOrgPolicy(orgPolicies, 'compute.disableGuestAttributesAccess', 'booleanPolicy', true, false, 'Disable Guest Attributes of Compute Engine Metadata', results, organization); return callback(null, results, source); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'disableGuestAttributes'; + + var putCall = this.actions.remediate; + + helpers.remediateOrgPolicy(config, 'constraints/compute.disableGuestAttributesAccess', 'booleanPolicy', true, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } }; \ No newline at end of file diff --git a/plugins/google/cloudresourcemanager/disableGuestAttributes.spec.js b/plugins/google/cloudresourcemanager/disableGuestAttributes.spec.js index e365c0a8a4..f1b54606dd 100644 --- a/plugins/google/cloudresourcemanager/disableGuestAttributes.spec.js +++ b/plugins/google/cloudresourcemanager/disableGuestAttributes.spec.js @@ -4,6 +4,20 @@ var plugin = require('./disableGuestAttributes'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, diff --git a/plugins/google/cloudresourcemanager/disableIdentityClusterCreation.js b/plugins/google/cloudresourcemanager/disableIdentityClusterCreation.js index 4dd93b39d3..ae1e987c62 100644 --- a/plugins/google/cloudresourcemanager/disableIdentityClusterCreation.js +++ b/plugins/google/cloudresourcemanager/disableIdentityClusterCreation.js @@ -9,11 +9,27 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Disable Workload Identity Cluster Creation" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], + remediation_min_version: '202202200432', + remediation_description: 'The "Disable Workload Identity Cluster Creation" constraint will be enforced at the organization level.', + apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], + actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, + permissions: {remediate: ['orgpolicy.policy.set'], rollback: ['orgpolicy.policy.set']}, run: function(cache, settings, callback) { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,8 +46,29 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'iam.disableWorkloadIdentityClusterCreation', 'booleanPolicy', true, false, 'Disable Workload Identity Cluster Creation', results); + helpers.checkOrgPolicy(orgPolicies, 'iam.disableWorkloadIdentityClusterCreation', 'booleanPolicy', true, false, 'Disable Workload Identity Cluster Creation', results, organization); return callback(null, results, source); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'disableIdentityClusterCreation'; + + var putCall = this.actions.remediate; + + helpers.remediateOrgPolicy(config, 'constraints/iam.disableWorkloadIdentityClusterCreation', 'booleanPolicy', true, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } }; \ No newline at end of file diff --git a/plugins/google/cloudresourcemanager/disableIdentityClusterCreation.spec.js b/plugins/google/cloudresourcemanager/disableIdentityClusterCreation.spec.js index f5c357e84e..7150b3e581 100644 --- a/plugins/google/cloudresourcemanager/disableIdentityClusterCreation.spec.js +++ b/plugins/google/cloudresourcemanager/disableIdentityClusterCreation.spec.js @@ -4,6 +4,20 @@ var plugin = require('./disableIdentityClusterCreation'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, diff --git a/plugins/google/cloudresourcemanager/disableKeyCreation.js b/plugins/google/cloudresourcemanager/disableKeyCreation.js index f1856d1dbd..d895aa4e63 100644 --- a/plugins/google/cloudresourcemanager/disableKeyCreation.js +++ b/plugins/google/cloudresourcemanager/disableKeyCreation.js @@ -9,11 +9,27 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Disable Service Account Key Creation" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], + remediation_min_version: '202202200432', + remediation_description: 'The "Disable Service Account Key Creation" constraint will be enforced at the organization level.', + apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], + actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, + permissions: {remediate: ['orgpolicy.policy.set'], rollback: ['orgpolicy.policy.set']}, run: function(cache, settings, callback) { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,8 +46,29 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'iam.disableServiceAccountKeyCreation', 'booleanPolicy', true, false, 'Disable Service Account Key Creation', results); + helpers.checkOrgPolicy(orgPolicies, 'iam.disableServiceAccountKeyCreation', 'booleanPolicy', true, false, 'Disable Service Account Key Creation', results, organization); return callback(null, results, source); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'disableKeyCreation'; + + var putCall = this.actions.remediate; + + helpers.remediateOrgPolicy(config, 'constraints/iam.disableServiceAccountKeyCreation', 'booleanPolicy', true, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } }; \ No newline at end of file diff --git a/plugins/google/cloudresourcemanager/disableKeyCreation.spec.js b/plugins/google/cloudresourcemanager/disableKeyCreation.spec.js index ba929e394f..62e9b9b7ef 100644 --- a/plugins/google/cloudresourcemanager/disableKeyCreation.spec.js +++ b/plugins/google/cloudresourcemanager/disableKeyCreation.spec.js @@ -4,6 +4,20 @@ var plugin = require('./disableKeyCreation'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, diff --git a/plugins/google/cloudresourcemanager/disableKeyUpload.js b/plugins/google/cloudresourcemanager/disableKeyUpload.js index 9327e3c3e2..99c610ef6f 100644 --- a/plugins/google/cloudresourcemanager/disableKeyUpload.js +++ b/plugins/google/cloudresourcemanager/disableKeyUpload.js @@ -9,11 +9,27 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Disable Service Account Key Upload" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], + remediation_min_version: '202202200432', + remediation_description: 'The "Disable Service Account Key Upload" constraint will be enforced at the organization level.', + apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], + actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, + permissions: {remediate: ['orgpolicy.policy.set'], rollback: ['orgpolicy.policy.set']}, run: function(cache, settings, callback) { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,8 +46,29 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'iam.disableServiceAccountKeyUpload', 'booleanPolicy', true, false, 'Disable Service Account Key Upload', results); + helpers.checkOrgPolicy(orgPolicies, 'iam.disableServiceAccountKeyUpload', 'booleanPolicy', true, false, 'Disable Service Account Key Upload', results, organization); return callback(null, results, source); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'disableKeyUpload'; + + var putCall = this.actions.remediate; + + helpers.remediateOrgPolicy(config, 'constraints/iam.disableServiceAccountKeyUpload', 'booleanPolicy', true, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } }; \ No newline at end of file diff --git a/plugins/google/cloudresourcemanager/disableKeyUpload.spec.js b/plugins/google/cloudresourcemanager/disableKeyUpload.spec.js index 6b81d78295..baebe1580c 100644 --- a/plugins/google/cloudresourcemanager/disableKeyUpload.spec.js +++ b/plugins/google/cloudresourcemanager/disableKeyUpload.spec.js @@ -4,6 +4,20 @@ var plugin = require('./disableKeyUpload'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, diff --git a/plugins/google/cloudresourcemanager/disableSerialPortAccess.spec.js b/plugins/google/cloudresourcemanager/disableSerialPortAccess.spec.js index f966d5bb2b..4b16a66637 100644 --- a/plugins/google/cloudresourcemanager/disableSerialPortAccess.spec.js +++ b/plugins/google/cloudresourcemanager/disableSerialPortAccess.spec.js @@ -17,7 +17,6 @@ const createCache = (err, data) => { ], err: null } - }, listOrgPolicies: { 'global': { diff --git a/plugins/google/cloudresourcemanager/disableVMIPForwarding.js b/plugins/google/cloudresourcemanager/disableVMIPForwarding.js index bdd9719557..d0b8432547 100644 --- a/plugins/google/cloudresourcemanager/disableVMIPForwarding.js +++ b/plugins/google/cloudresourcemanager/disableVMIPForwarding.js @@ -14,6 +14,17 @@ module.exports = { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,7 +41,7 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'compute.vmCanIpForward', 'listPolicy', true, false, 'Restrict VM IP Forwarding', results); + helpers.checkOrgPolicy(orgPolicies, 'compute.vmCanIpForward', 'listPolicy', true, false, 'Restrict VM IP Forwarding', results, organization); return callback(null, results, source); } diff --git a/plugins/google/cloudresourcemanager/disableVMIPForwarding.spec.js b/plugins/google/cloudresourcemanager/disableVMIPForwarding.spec.js index 56cbe74c7c..08339594d6 100644 --- a/plugins/google/cloudresourcemanager/disableVMIPForwarding.spec.js +++ b/plugins/google/cloudresourcemanager/disableVMIPForwarding.spec.js @@ -4,6 +4,20 @@ var plugin = require('./disableVMIPForwarding'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, diff --git a/plugins/google/cloudresourcemanager/locationBasedRestriction.js b/plugins/google/cloudresourcemanager/locationBasedRestriction.js index 75dba51502..7492bf1cad 100644 --- a/plugins/google/cloudresourcemanager/locationBasedRestriction.js +++ b/plugins/google/cloudresourcemanager/locationBasedRestriction.js @@ -9,11 +9,22 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Resource Location Restriction" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], - + run: function(cache, settings, callback) { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,7 +41,7 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'gcp.resourceLocations', 'listPolicy', true, false, 'Resource Location Restriction', results); + helpers.checkOrgPolicy(orgPolicies, 'gcp.resourceLocations', 'listPolicy', true, false, 'Resource Location Restriction', results, organization); return callback(null, results, source); } diff --git a/plugins/google/cloudresourcemanager/locationBasedRestriction.spec.js b/plugins/google/cloudresourcemanager/locationBasedRestriction.spec.js index 95e4b2b56e..e86a96a54b 100644 --- a/plugins/google/cloudresourcemanager/locationBasedRestriction.spec.js +++ b/plugins/google/cloudresourcemanager/locationBasedRestriction.spec.js @@ -4,6 +4,20 @@ var plugin = require('./locationBasedRestriction'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, diff --git a/plugins/google/cloudresourcemanager/requireOsLogin.js b/plugins/google/cloudresourcemanager/requireOsLogin.js index bd1499f07f..a68ef3c303 100644 --- a/plugins/google/cloudresourcemanager/requireOsLogin.js +++ b/plugins/google/cloudresourcemanager/requireOsLogin.js @@ -9,11 +9,28 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Require OS Login" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], + remediation_min_version: '202202140432', + remediation_description: 'The "Require OS Login" constraint will be enforced at the organization level.', + apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], + actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, + permissions: {remediate: ['orgpolicy.policy.set'], rollback: ['orgpolicy.policy.set']}, + realtime_triggers: ['SetOrgPolicy'], run: function(cache, settings, callback) { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,8 +47,29 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'compute.requireOsLogin', 'booleanPolicy', true, false, 'Require OS Login', results); + helpers.checkOrgPolicy(orgPolicies, 'compute.requireOsLogin', 'booleanPolicy', true, false, 'Require OS Login', results, organization); return callback(null, results, source); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'requireOsLogin'; + + var putCall = this.actions.remediate; + + helpers.remediateOrgPolicy(config, 'constraints/compute.requireOsLogin', 'booleanPolicy', true, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } }; \ No newline at end of file diff --git a/plugins/google/cloudresourcemanager/requireOsLogin.spec.js b/plugins/google/cloudresourcemanager/requireOsLogin.spec.js index 127b04a952..e5c464b91f 100644 --- a/plugins/google/cloudresourcemanager/requireOsLogin.spec.js +++ b/plugins/google/cloudresourcemanager/requireOsLogin.spec.js @@ -4,6 +4,20 @@ var plugin = require('./requireOsLogin'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, diff --git a/plugins/google/cloudresourcemanager/restrictAuthorizedNetworks.js b/plugins/google/cloudresourcemanager/restrictAuthorizedNetworks.js index 4b2bf23327..b947f57d61 100644 --- a/plugins/google/cloudresourcemanager/restrictAuthorizedNetworks.js +++ b/plugins/google/cloudresourcemanager/restrictAuthorizedNetworks.js @@ -9,11 +9,28 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Restrict Authorized Networks on Cloud SQL instances" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], + remediation_min_version: '202202140432', + remediation_description: 'The "Restrict Authorized Networks on Cloud SQL instances" constraint will be enforced at the organization level.', + apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], + actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, + permissions: {remediate: ['orgpolicy.policy.set'], rollback: ['orgpolicy.policy.set']}, + realtime_triggers: ['SetOrgPolicy'], run: function(cache, settings, callback) { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,8 +47,29 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'sql.restrictAuthorizedNetworks', 'booleanPolicy', true, false, 'Restrict Authorized Networks on Cloud SQL instances', results); + helpers.checkOrgPolicy(orgPolicies, 'sql.restrictAuthorizedNetworks', 'booleanPolicy', true, false, 'Restrict Authorized Networks on Cloud SQL instances', results, organization); return callback(null, results, source); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'restrictAuthorizedNetworks'; + + var putCall = this.actions.remediate; + + helpers.remediateOrgPolicy(config, 'constraints/sql.restrictAuthorizedNetworks', 'booleanPolicy', true, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } }; \ No newline at end of file diff --git a/plugins/google/cloudresourcemanager/restrictAuthorizedNetworks.spec.js b/plugins/google/cloudresourcemanager/restrictAuthorizedNetworks.spec.js index efb2bf2a59..830ce56b24 100644 --- a/plugins/google/cloudresourcemanager/restrictAuthorizedNetworks.spec.js +++ b/plugins/google/cloudresourcemanager/restrictAuthorizedNetworks.spec.js @@ -4,6 +4,20 @@ var plugin = require('./restrictAuthorizedNetworks'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, diff --git a/plugins/google/cloudresourcemanager/restrictLoadBalancerCreation.js b/plugins/google/cloudresourcemanager/restrictLoadBalancerCreation.js index 797e65d0f0..f5862d2dd2 100644 --- a/plugins/google/cloudresourcemanager/restrictLoadBalancerCreation.js +++ b/plugins/google/cloudresourcemanager/restrictLoadBalancerCreation.js @@ -14,6 +14,17 @@ module.exports = { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,7 +41,7 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'compute.restrictLoadBalancerCreationForTypes', 'listPolicy', true, false, 'Restrict Load Balancer Creation for Types', results); + helpers.checkOrgPolicy(orgPolicies, 'compute.restrictLoadBalancerCreationForTypes', 'listPolicy', true, false, 'Restrict Load Balancer Creation for Types', results, organization); return callback(null, results, source); } diff --git a/plugins/google/cloudresourcemanager/restrictLoadBalancerCreation.spec.js b/plugins/google/cloudresourcemanager/restrictLoadBalancerCreation.spec.js index 2187a6ab27..8b6d94afac 100644 --- a/plugins/google/cloudresourcemanager/restrictLoadBalancerCreation.spec.js +++ b/plugins/google/cloudresourcemanager/restrictLoadBalancerCreation.spec.js @@ -4,6 +4,20 @@ var plugin = require('./restrictLoadBalancerCreation'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, diff --git a/plugins/google/cloudresourcemanager/restrictSharedVPCSubnetworks.js b/plugins/google/cloudresourcemanager/restrictSharedVPCSubnetworks.js index 4d55d87504..b0dd29f0c8 100644 --- a/plugins/google/cloudresourcemanager/restrictSharedVPCSubnetworks.js +++ b/plugins/google/cloudresourcemanager/restrictSharedVPCSubnetworks.js @@ -14,6 +14,17 @@ module.exports = { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,7 +41,7 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'compute.restrictSharedVpcSubnetworks', 'listPolicy', true, false, 'Restrict Shared VPC Subnetworks', results); + helpers.checkOrgPolicy(orgPolicies, 'compute.restrictSharedVpcSubnetworks', 'listPolicy', true, false, 'Restrict Shared VPC Subnetworks', results, organization); return callback(null, results, source); } diff --git a/plugins/google/cloudresourcemanager/restrictSharedVPCSubnetworks.spec.js b/plugins/google/cloudresourcemanager/restrictSharedVPCSubnetworks.spec.js index e402066dbd..0e4a46f6d7 100644 --- a/plugins/google/cloudresourcemanager/restrictSharedVPCSubnetworks.spec.js +++ b/plugins/google/cloudresourcemanager/restrictSharedVPCSubnetworks.spec.js @@ -4,6 +4,20 @@ var plugin = require('./restrictSharedVPCSubnetworks'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, diff --git a/plugins/google/cloudresourcemanager/restrictVPCPeering.js b/plugins/google/cloudresourcemanager/restrictVPCPeering.js index f29ae3f3e4..daf4099b57 100644 --- a/plugins/google/cloudresourcemanager/restrictVPCPeering.js +++ b/plugins/google/cloudresourcemanager/restrictVPCPeering.js @@ -14,6 +14,17 @@ module.exports = { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,7 +41,7 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'compute.restrictVpcPeering', 'listPolicy', true, false, 'Restrict VPC Peering', results); + helpers.checkOrgPolicy(orgPolicies, 'compute.restrictVpcPeering', 'listPolicy', true, false, 'Restrict VPC Peering', results, organization); return callback(null, results, source); } diff --git a/plugins/google/cloudresourcemanager/restrictVPCPeering.spec.js b/plugins/google/cloudresourcemanager/restrictVPCPeering.spec.js index 8d7c13ba3a..58ecfc032d 100644 --- a/plugins/google/cloudresourcemanager/restrictVPCPeering.spec.js +++ b/plugins/google/cloudresourcemanager/restrictVPCPeering.spec.js @@ -4,6 +4,20 @@ var plugin = require('./restrictVPCPeering'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, diff --git a/plugins/google/cloudresourcemanager/restrictVPNPeerIPs.js b/plugins/google/cloudresourcemanager/restrictVPNPeerIPs.js index 97bbb7ea2a..4b14c77987 100644 --- a/plugins/google/cloudresourcemanager/restrictVPNPeerIPs.js +++ b/plugins/google/cloudresourcemanager/restrictVPNPeerIPs.js @@ -14,6 +14,17 @@ module.exports = { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,7 +41,7 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'compute.restrictVpnPeerIPs', 'listPolicy', true, false, 'Restrict VPN Peer IPs', results); + helpers.checkOrgPolicy(orgPolicies, 'compute.restrictVpnPeerIPs', 'listPolicy', true, false, 'Restrict VPN Peer IPs', results, organization); return callback(null, results, source); } diff --git a/plugins/google/cloudresourcemanager/restrictVPNPeerIPs.spec.js b/plugins/google/cloudresourcemanager/restrictVPNPeerIPs.spec.js index bc703eb7b8..e8eba58286 100644 --- a/plugins/google/cloudresourcemanager/restrictVPNPeerIPs.spec.js +++ b/plugins/google/cloudresourcemanager/restrictVPNPeerIPs.spec.js @@ -4,6 +4,20 @@ var plugin = require('./restrictVPNPeerIPs'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, diff --git a/plugins/google/cloudresourcemanager/skipDefaultNetworkCreation.js b/plugins/google/cloudresourcemanager/skipDefaultNetworkCreation.js index 4084f87022..31bc2e297d 100644 --- a/plugins/google/cloudresourcemanager/skipDefaultNetworkCreation.js +++ b/plugins/google/cloudresourcemanager/skipDefaultNetworkCreation.js @@ -10,11 +10,28 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Skip Default Network Creation" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], + remediation_min_version: '202202140432', + remediation_description: 'The "Skip Default Network Creation" constraint will be enforced at the organization level.', + apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], + actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, + permissions: {remediate: ['orgpolicy.policy.set'], rollback: ['orgpolicy.policy.set']}, + realtime_triggers: ['SetOrgPolicy'], run: function(cache, settings, callback) { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -31,8 +48,29 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'compute.skipDefaultNetworkCreation', 'booleanPolicy', true, false, 'Skip Default Network Creation', results); + helpers.checkOrgPolicy(orgPolicies, 'compute.skipDefaultNetworkCreation', 'booleanPolicy', true, false, 'Skip Default Network Creation', results, organization); return callback(null, results, source); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'skipDefaultNetworkCreation'; + + var putCall = this.actions.remediate; + + helpers.remediateOrgPolicy(config, 'constraints/compute.skipDefaultNetworkCreation', 'booleanPolicy', true, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } }; \ No newline at end of file diff --git a/plugins/google/cloudresourcemanager/skipDefaultNetworkCreation.spec.js b/plugins/google/cloudresourcemanager/skipDefaultNetworkCreation.spec.js index 36f56043e2..fa5c38b656 100644 --- a/plugins/google/cloudresourcemanager/skipDefaultNetworkCreation.spec.js +++ b/plugins/google/cloudresourcemanager/skipDefaultNetworkCreation.spec.js @@ -4,6 +4,20 @@ var plugin = require('./skipDefaultNetworkCreation'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, diff --git a/plugins/google/cloudresourcemanager/trustedImageProjects.js b/plugins/google/cloudresourcemanager/trustedImageProjects.js index 4e9d00decb..9a5c6e06d6 100644 --- a/plugins/google/cloudresourcemanager/trustedImageProjects.js +++ b/plugins/google/cloudresourcemanager/trustedImageProjects.js @@ -15,6 +15,17 @@ module.exports = { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -31,7 +42,7 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'compute.trustedImageProjects', 'listPolicy', true, false, 'Define Trusted Image Projects', results); + helpers.checkOrgPolicy(orgPolicies, 'compute.trustedImageProjects', 'listPolicy', true, false, 'Define Trusted Image Projects', results, organization); return callback(null, results, source); } diff --git a/plugins/google/cloudresourcemanager/trustedImageProjects.spec.js b/plugins/google/cloudresourcemanager/trustedImageProjects.spec.js index e13fa842a2..073ec524c2 100644 --- a/plugins/google/cloudresourcemanager/trustedImageProjects.spec.js +++ b/plugins/google/cloudresourcemanager/trustedImageProjects.spec.js @@ -4,6 +4,20 @@ var plugin = require('./trustedImageProjects'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, diff --git a/plugins/google/cloudresourcemanager/uniformBucketLevelAccess.js b/plugins/google/cloudresourcemanager/uniformBucketLevelAccess.js index 7bd86e0d2a..475208e8d7 100644 --- a/plugins/google/cloudresourcemanager/uniformBucketLevelAccess.js +++ b/plugins/google/cloudresourcemanager/uniformBucketLevelAccess.js @@ -9,11 +9,28 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Enforce uniform bucket-level access" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], + remediation_min_version: '202202140432', + remediation_description: 'The "Enforce uniform bucket-level access" constraint will be enforced at the organization level.', + apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], + actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, + permissions: {remediate: ['orgpolicy.policy.set'], rollback: ['orgpolicy.policy.set']}, + realtime_triggers: ['SetOrgPolicy'], run: function(cache, settings, callback) { var results = []; var source = {}; + let organizations = helpers.addSource(cache, source, + ['organizations','list', 'global']); + + if (!organizations || organizations.err || !organizations.data || !organizations.data.length) { + helpers.addResult(results, 3, + 'Unable to query for organizations: ' + helpers.addError(organizations), 'global', null, null, (organizations) ? organizations.err : null); + return callback(null, results, source); + } + + var organization = organizations.data[0].name; + let listOrgPolicies = helpers.addSource(cache, source, ['organizations', 'listOrgPolicies', 'global']); @@ -30,8 +47,29 @@ module.exports = { } let orgPolicies = listOrgPolicies.data[0]; - helpers.checkOrgPolicy(orgPolicies, 'storage.uniformBucketLevelAccess', 'booleanPolicy', true, false, 'Enforce uniform bucket-level access', results); + helpers.checkOrgPolicy(orgPolicies, 'storage.uniformBucketLevelAccess', 'booleanPolicy', true, false, 'Enforce uniform bucket-level access', results, organization); return callback(null, results, source); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'uniformBucketLevelAccess'; + + var putCall = this.actions.remediate; + + helpers.remediateOrgPolicy(config, 'constraints/storage.uniformBucketLevelAccess', 'booleanPolicy', true, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } }; \ No newline at end of file diff --git a/plugins/google/cloudresourcemanager/uniformBucketLevelAccess.spec.js b/plugins/google/cloudresourcemanager/uniformBucketLevelAccess.spec.js index 290eee464f..8ba1389c06 100644 --- a/plugins/google/cloudresourcemanager/uniformBucketLevelAccess.spec.js +++ b/plugins/google/cloudresourcemanager/uniformBucketLevelAccess.spec.js @@ -4,6 +4,20 @@ var plugin = require('./uniformBucketLevelAccess'); const createCache = (err, data) => { return { organizations: { + list: { + 'global': { + data: [ + { + "organizationId": "123456", + "displayName": "myorg", + "creationTime": "2018-03-03T17:56:10.122Z", + "lifecycleState": "ACTIVE", + "name": "organizations/123456" + } + ], + err: null + } + }, listOrgPolicies: { 'global': { err: err, From e5ac3fb002d68a64483eff6532bd76aa57d8ce18 Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Mon, 7 Feb 2022 02:41:32 +0500 Subject: [PATCH 022/350] GCP Remediation for Bucket Uniform Level Access plugin --- plugins/google/storage/bucketUniformAccess.js | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/plugins/google/storage/bucketUniformAccess.js b/plugins/google/storage/bucketUniformAccess.js index 130dbd7f4a..a923f8f3bd 100644 --- a/plugins/google/storage/bucketUniformAccess.js +++ b/plugins/google/storage/bucketUniformAccess.js @@ -10,6 +10,12 @@ module.exports = { link: 'https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use', recommended_action: 'Make sure that storage buckets have uniform level access enabled', apis: ['buckets:list'], + remediation_min_version: '202202071836', + remediation_description: 'Unfiorm Level Access will be enabled on all storage buckets', + apis_remediate: ['buckets:list'], + actions: {remediate:['storage.buckets.update'], rollback:['storage.buckets.update']}, + permissions: {remediate: ['storage.buckets.setIamPolicy', 'storage.buckets.update'], rollback: ['storage.buckets.setIamPolicy','storage.buckets.update']}, + realtime_triggers: ['storage.buckets.update', 'storage.buckets.create'], run: function(cache, settings, callback) { var results = []; @@ -56,5 +62,40 @@ module.exports = { // Global checking goes here callback(null, results, source); }); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'bucketUniformAccess'; + var baseUrl = 'https://storage.googleapis.com/storage/v1/{resource}'; + var method = 'PUT'; + var putCall = this.actions.remediate; + + // create the params necessary for the remediation + var body = { + iamConfiguration: { + uniformBucketLevelAccess: { + enabled: true + } + } + }; + // logging + remediation_file['pre_remediate']['actions'][pluginName][resource] = { + 'UniformBucketLevelAccess': 'Disabled' + }; + + helpers.remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } -}; \ No newline at end of file +}; From a48bc4cceaa8988e3ca5e66c753534d219ab8711 Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Tue, 8 Feb 2022 04:18:13 +0500 Subject: [PATCH 023/350] GCP Remediation for Instance Automatic Restart Enabled plugin --- .../google/compute/automaticRestartEnabled.js | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/plugins/google/compute/automaticRestartEnabled.js b/plugins/google/compute/automaticRestartEnabled.js index 0ea3309d94..43969d075d 100644 --- a/plugins/google/compute/automaticRestartEnabled.js +++ b/plugins/google/compute/automaticRestartEnabled.js @@ -10,6 +10,12 @@ module.exports = { link: 'https://cloud.google.com/compute/docs/instances/setting-instance-scheduling-options#autorestart', recommended_action: 'Ensure automatic restart is enabled for all virtual machine instances.', apis: ['instances:compute:list', 'projects:get'], + remediation_min_version: '202202080432', + remediation_description: 'Automatic Restart will be enabled for all virtual machine instances.', + apis_remediate: ['instances:compute:list', 'projects:get'], + actions: {remediate:['compute.instances.setScheduling'], rollback:['compute.instances.setScheduling']}, + permissions: {remediate: ['compute.instances.setScheduling'], rollback: ['compute.instances.setScheduling']}, + realtime_triggers: ['compute.instances.setScheduling', 'compute.instances.insert'], run: function(cache, settings, callback) { var results = []; @@ -65,5 +71,36 @@ module.exports = { }, function() { callback(null, results, source); }); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'automaticRestartEnabled'; + var baseUrl = 'https://compute.googleapis.com/compute/v1/{resource}/setScheduling'; + var method = 'POST'; + var putCall = this.actions.remediate; + + // create the params necessary for the remediation + var body = { + automaticRestart: true + }; + // logging + remediation_file['pre_remediate']['actions'][pluginName][resource] = { + 'automaticRestart': 'Disabled' + }; + + helpers.remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } }; \ No newline at end of file From 3237603063af2c65fa622f9b317b8f19219c5512 Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Mon, 14 Feb 2022 00:19:41 +0500 Subject: [PATCH 024/350] GCP Remediation for Http Trigger Require Https plugin --- .../cloudfunctions/httpTriggerRequireHttps.js | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/plugins/google/cloudfunctions/httpTriggerRequireHttps.js b/plugins/google/cloudfunctions/httpTriggerRequireHttps.js index 14fabcff29..7208b403ce 100644 --- a/plugins/google/cloudfunctions/httpTriggerRequireHttps.js +++ b/plugins/google/cloudfunctions/httpTriggerRequireHttps.js @@ -10,6 +10,13 @@ module.exports = { link: 'https://cloud.google.com/functions/docs/writing/http', recommended_action: 'Ensure that your Google Cloud functions always require HTTPS.', apis: ['functions:list', 'projects:get'], + remediation_min_version: '202202132132', + remediation_description: 'All Google Cloud Functions will be configured to require HTTPS for HTTP invocations.', + apis_remediate: ['functions:list', 'projects:get'], + actions: {remediate:['CloudFunctionsService.UpdateFunction'], rollback:['CloudFunctionsService.UpdateFunction']}, + permissions: {remediate: ['cloudfunctions.functions.update'], rollback: ['cloudfunctions.functions.create ']}, + realtime_triggers: ['google.cloud.functions.v1.CloudFunctionsService.UpdateFunction', 'google.cloud.functions.v1.CloudFunctionsService.CreateFunction'], + run: function(cache, settings, callback) { var results = []; @@ -53,5 +60,39 @@ module.exports = { }, function() { callback(null, results, source); }); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + + // inputs specific to the plugin + var pluginName = 'httpTriggerRequireHttps'; + var baseUrl = 'https://cloudfunctions.googleapis.com/v1/{resource}?updateMask=httpsTrigger.securityLevel'; + var method = 'PATCH'; + var putCall = this.actions.remediate; + + // create the params necessary for the remediation + var body = { + httpsTrigger: { + securityLevel: 'SECURE_ALWAYS' + } + }; + // logging + remediation_file['pre_remediate']['actions'][pluginName][resource] = { + 'httpTriggerRequireHttps': 'Disabled' + }; + + helpers.remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, function(err, action) { + if (err) return callback(err); + if (action) action.action = putCall; + + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'Action': 'Enabled' + }; + + callback(null, action); + }); } + }; \ No newline at end of file From c54e2bd2ebd264f5baf3252d701d5269fdbbc747 Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Sat, 5 Mar 2022 05:42:42 +0500 Subject: [PATCH 025/350] GCP Plugin - Instance Group Auto Healing --- collectors/google/collector.js | 7 + exports.js | 1 + helpers/google/regions.js | 1 + .../compute/instanceGroupAutoHealing.js | 73 +++++++++++ .../compute/instanceGroupAutoHealing.spec.js | 120 ++++++++++++++++++ 5 files changed, 202 insertions(+) create mode 100644 plugins/google/compute/instanceGroupAutoHealing.js create mode 100644 plugins/google/compute/instanceGroupAutoHealing.spec.js diff --git a/collectors/google/collector.js b/collectors/google/collector.js index 227bbb29d4..75c07c9d5d 100644 --- a/collectors/google/collector.js +++ b/collectors/google/collector.js @@ -111,6 +111,13 @@ var calls = { pagination: true } }, + instanceGroupManagers: { + list: { + url: 'https://compute.googleapis.com/compute/v1/projects/{projectId}/zones/{locationId}/instanceGroupManagers', + location: 'zone', + pagination: true + } + }, functions: { list : { url: 'https://cloudfunctions.googleapis.com/v1/projects/{projectId}/locations/{locationId}/functions', diff --git a/exports.js b/exports.js index 36d4be0d16..f57b6333d5 100644 --- a/exports.js +++ b/exports.js @@ -877,6 +877,7 @@ module.exports = { 'applicationConsistentSnapshots': require(__dirname + '/plugins/google/compute/applicationConsistentSnapshots.js'), 'deprecatedImages' : require(__dirname + '/plugins/google/compute/deprecatedImages.js'), 'enableUsageExport' : require(__dirname + '/plugins/google/compute/enableUsageExport.js'), + 'instanceGroupAutoHealing' : require(__dirname + '/plugins/google/compute/instanceGroupAutoHealing.js'), 'keyRotation' : require(__dirname + '/plugins/google/cryptographickeys/keyRotation.js'), 'keyProtectionLevel' : require(__dirname + '/plugins/google/cryptographickeys/keyProtectionLevel.js'), diff --git a/helpers/google/regions.js b/helpers/google/regions.js index 39b468f98b..224cc04524 100644 --- a/helpers/google/regions.js +++ b/helpers/google/regions.js @@ -81,6 +81,7 @@ module.exports = { sql: ['global'], spanner: ['global'] }, + instanceGroupManagers: regions, functions: [ 'us-east1', 'us-east4', 'us-west2', 'us-west3', 'us-west4', 'us-central1', 'northamerica-northeast1', 'southamerica-east1', 'europe-west1', 'europe-west2', 'europe-west3', 'europe-west6', 'europe-central2', 'asia-south1', 'asia-southeast1', 'asia-southeast2', diff --git a/plugins/google/compute/instanceGroupAutoHealing.js b/plugins/google/compute/instanceGroupAutoHealing.js new file mode 100644 index 0000000000..0b530bb5d9 --- /dev/null +++ b/plugins/google/compute/instanceGroupAutoHealing.js @@ -0,0 +1,73 @@ +var async = require('async'); +var helpers = require('../../../helpers/google'); + +module.exports = { + title: 'Instance Group Auto Healing Enabled', + category: 'Compute', + domain: 'Compute', + description: 'Ensures instance groups have auto-healing enabled for high availability.', + more_info: 'To improve the availability of your application, configure a health check to verify that the application is responding as expected.', + link: 'https://cloud.google.com/compute/docs/instance-groups/autohealing-instances-in-migs', + recommended_action: 'Ensure autohealing is enabled for all instance groups.', + apis: ['instanceGroupManagers:list', 'projects:get'], + + 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.instanceGroupManagers, (region, rcb) => { + var zones = regions.zones; + var noInstanceGroups = []; + async.each(zones[region], function(zone, zcb) { + var instanceGroupManagers = helpers.addSource(cache, source, + ['instanceGroupManagers', 'list', zone]); + + if (!instanceGroupManagers) return zcb(); + + if (instanceGroupManagers.err || !instanceGroupManagers.data) { + helpers.addResult(results, 3, 'Unable to query instance groups', region, null, null, instanceGroupManagers.err); + return zcb(); + } + + if (!instanceGroupManagers.data.length) { + noInstanceGroups.push(zone); + return zcb(); + } + + instanceGroupManagers.data.forEach(instanceGroupManager => { + if (!instanceGroupManager.id || !instanceGroupManager.creationTimestamp) return; + + let resource = helpers.createResourceName('instanceGroupManagers', instanceGroupManager.name, project, 'zone', zone); + + if (instanceGroupManager.autoHealingPolicies && instanceGroupManager.autoHealingPolicies.length) { + helpers.addResult(results, 0, + 'Instance Group has auto healing enabled', region, resource); + } else { + helpers.addResult(results, 2, + 'Instance Group does not have auto healing enabled', region, resource); + } + }); + zcb(); + }, function() { + if (noInstanceGroups.length) { + helpers.addResult(results, 0, `No instance groups found in following zones: ${noInstanceGroups.join(', ')}`, region); + } + rcb(); + }); + }, function() { + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/google/compute/instanceGroupAutoHealing.spec.js b/plugins/google/compute/instanceGroupAutoHealing.spec.js new file mode 100644 index 0000000000..fc11d33fa7 --- /dev/null +++ b/plugins/google/compute/instanceGroupAutoHealing.spec.js @@ -0,0 +1,120 @@ +var assert = require('assert'); +var expect = require('chai').expect; +var plugin = require('./instanceGroupAutoHealing'); + +const createCache = (instanceData, error) => { + return { + instanceGroupManagers: { + list: { + 'us-central1-a': { + data: instanceData, + err: error + } + } + }, + projects: { + get: { + 'global': { + data: 'tets-proj' + } + } + } + } +}; + +describe('instanceGroupAutohealing', function () { + describe('run', function () { + const settings = { instance_desired_machine_types: 'e2-micro' }; + it('should give unknown if an instance group error occurs', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('Unable to query instance groups'); + expect(results[0].region).to.equal('us-central1'); + done() + }; + + const cache = createCache( + [], + ['error'] + ); + + plugin.run(cache, settings, callback); + }); + + it('should pass no VM Instances', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No instance groups found'); + expect(results[0].region).to.equal('us-central1'); + done() + }; + + const cache = createCache( + [], + null + ); + + plugin.run(cache, settings, callback); + }); + + it('should FAIL if instance group does not have auto healing enabled', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Instance Group does not have auto healing enabled'); + done() + }; + const cache = createCache( + [ + { + "id": '11111111', + "creationTimestamp": '2022-01-05T12:19:12.147-08:00', + "name": 'instance-group-1', + "description": '', + "zone": 'https://www.googleapis.com/compute/v1/projects/my-project-1/zones/us-central1-a', + "instanceGroup": 'https://www.googleapis.com/compute/v1/projects/my-project-1/zones/us-central1-a/instanceGroups/instance-group-1', + "baseInstanceName": 'instance-group-1', + "autoHealingPolicies": [] + } + ], + null + ); + + plugin.run(cache, settings, callback); + }) + + it('should PASS if instance group has auto healing enabled', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.equal('Instance Group has auto healing enabled'); + done() + }; + + const cache = createCache( + [ + { + "id": '11111111', + "creationTimestamp": '2022-01-05T12:19:12.147-08:00', + "name": 'instance-group-1', + "description": '', + "zone": 'https://www.googleapis.com/compute/v1/projects/my-project-1/zones/us-central1-a', + "instanceGroup": 'https://www.googleapis.com/compute/v1/projects/my-project-1/zones/us-central1-a/instanceGroups/instance-group-1', + "baseInstanceName": 'instance-group-1', + "autoHealingPolicies": [ + { + "healthCheck": 'https://www.googleapis.com/compute/v1/projects/my-project/global/healthChecks/hc-1', + "initialDelaySec": 300 + } + ] + } + ] + ); + + plugin.run(cache, settings, callback); + }) + + }) +}); \ No newline at end of file From 68524e4741c2eeaa73913092fcf1470aa6ee5330 Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Thu, 10 Mar 2022 17:30:05 +0500 Subject: [PATCH 026/350] GCP Refactoring Post Calls --- helpers/google/index.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/helpers/google/index.js b/helpers/google/index.js index a84a922d33..01b4765aea 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -282,6 +282,7 @@ var execute = async function(LocalGoogleConfig, collection, service, callObj, ca } else if (!myEngine && !(collection[service][callKey][region].data.length)) { collection[service][callKey][region].data = []; } + resultItems = setData(collectionItems, data.data, postCall, parent); } else { set = false; myEngine ? collection[service][myEngine][callKey][region].data = [] : collection[service][callKey][region].data = []; @@ -385,10 +386,14 @@ function setData(collection, dataToAdd, postCall, parent) { } } if (postCall && !!parent) { - collection.data.map(item => { - item.parent = parent; - return item; - }); + if (collection.data && collection.data.length) { + collection.data.map(item => { + item.parent = parent; + return item; + }); + } else if (Object.keys(collection.data) && Object.keys(collection.data).length) { + collection.data.parent = parent; + } } return collection; } From e824c65209fbc25d2de41fd9a8af855a4d068af2 Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Thu, 10 Mar 2022 17:30:05 +0500 Subject: [PATCH 027/350] GCP Refactoring Post Calls --- helpers/google/index.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/helpers/google/index.js b/helpers/google/index.js index a84a922d33..01b4765aea 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -282,6 +282,7 @@ var execute = async function(LocalGoogleConfig, collection, service, callObj, ca } else if (!myEngine && !(collection[service][callKey][region].data.length)) { collection[service][callKey][region].data = []; } + resultItems = setData(collectionItems, data.data, postCall, parent); } else { set = false; myEngine ? collection[service][myEngine][callKey][region].data = [] : collection[service][callKey][region].data = []; @@ -385,10 +386,14 @@ function setData(collection, dataToAdd, postCall, parent) { } } if (postCall && !!parent) { - collection.data.map(item => { - item.parent = parent; - return item; - }); + if (collection.data && collection.data.length) { + collection.data.map(item => { + item.parent = parent; + return item; + }); + } else if (Object.keys(collection.data) && Object.keys(collection.data).length) { + collection.data.parent = parent; + } } return collection; } From 2095e083e0c5bb32c81ab09fd1d6dbda66933004 Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Fri, 11 Mar 2022 02:16:41 +0500 Subject: [PATCH 028/350] GCP Public Disk Images Plugin --- collectors/google/collector.js | 9 + exports.js | 1 + helpers/google/index.js | 20 +- plugins/google/compute/publicDiskImages.js | 81 ++++++ .../google/compute/publicDiskImages.spec.js | 241 ++++++++++++++++++ 5 files changed, 342 insertions(+), 10 deletions(-) create mode 100644 plugins/google/compute/publicDiskImages.js create mode 100644 plugins/google/compute/publicDiskImages.spec.js diff --git a/collectors/google/collector.js b/collectors/google/collector.js index 227bbb29d4..e86e372cb4 100644 --- a/collectors/google/collector.js +++ b/collectors/google/collector.js @@ -398,6 +398,15 @@ var postcalls = { pagination: true, paginationKey: 'pageSize' } + }, + images: { + getIamPolicy: { + url: 'https://compute.googleapis.com/compute/v1/projects/{projectId}/global/images/{name}/getIamPolicy', + reliesOnService: ['images'], + reliesOnCall: ['list'], + properties: ['name'], + pagination: false + } } }; diff --git a/exports.js b/exports.js index 36d4be0d16..0bd6712736 100644 --- a/exports.js +++ b/exports.js @@ -877,6 +877,7 @@ module.exports = { 'applicationConsistentSnapshots': require(__dirname + '/plugins/google/compute/applicationConsistentSnapshots.js'), 'deprecatedImages' : require(__dirname + '/plugins/google/compute/deprecatedImages.js'), 'enableUsageExport' : require(__dirname + '/plugins/google/compute/enableUsageExport.js'), + 'publicDiskImages' : require(__dirname + '/plugins/google/compute/publicDiskImages.js'), 'keyRotation' : require(__dirname + '/plugins/google/cryptographickeys/keyRotation.js'), 'keyProtectionLevel' : require(__dirname + '/plugins/google/cryptographickeys/keyProtectionLevel.js'), diff --git a/helpers/google/index.js b/helpers/google/index.js index 01b4765aea..685e5fd8ec 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -375,6 +375,16 @@ function makeApiCall(client, originalUrl, callCb, nextToken, config) { } function setData(collection, dataToAdd, postCall, parent) { + if (postCall && !!parent) { + if (dataToAdd && dataToAdd.length) { + dataToAdd.map(item => { + item.parent = parent; + return item; + }); + } else if (Object.keys(dataToAdd) && Object.keys(dataToAdd).length) { + dataToAdd.parent = parent; + } + } if (dataToAdd.constructor.name === 'Array') { collection.data = collection.data.concat(dataToAdd); } else { @@ -385,16 +395,6 @@ function setData(collection, dataToAdd, postCall, parent) { collection.data = dataToAdd; } } - if (postCall && !!parent) { - if (collection.data && collection.data.length) { - collection.data.map(item => { - item.parent = parent; - return item; - }); - } else if (Object.keys(collection.data) && Object.keys(collection.data).length) { - collection.data.parent = parent; - } - } return collection; } diff --git a/plugins/google/compute/publicDiskImages.js b/plugins/google/compute/publicDiskImages.js new file mode 100644 index 0000000000..5c80e55790 --- /dev/null +++ b/plugins/google/compute/publicDiskImages.js @@ -0,0 +1,81 @@ +var helpers = require('../../../helpers/google'); + +module.exports = { + title: 'Public Disk Images', + category: 'Compute', + domain: 'Compute', + description: 'Ensure that your disk images are not being shared publicly.', + more_info: 'To avoid exposing sensitive information, make sure that your virtual machine disk images are not being publicly shared with all other GCP accounts.', + link: 'https://cloud.google.com/compute/docs/images', + recommended_action: 'Ensure that your VM disk images are not accessible by allUsers or allAuthenticatedUsers.', + apis: ['images:list', 'images:getIamPolicy', 'projects:get'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + + 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; + + let images = helpers.addSource(cache, source, + ['images', 'list', 'global']); + + if (!images || images.err || !images.data) { + helpers.addResult(results, 3, 'Unable to query Disk Images: ' + helpers.addError(images), 'global'); + return callback(null, results, source); + } + + if (!images.data.length) { + helpers.addResult(results, 0, 'No Disk Images found', 'global'); + return callback(null, results, source); + } + + let getImagesIamPolicies = helpers.addSource(cache, source, + ['images', 'getIamPolicy', 'global']); + + if (!getImagesIamPolicies || getImagesIamPolicies.err || !getImagesIamPolicies.data) { + helpers.addResult(results, 3, 'Unable to query IAM Policies for Disk Images: ' + helpers.addError(getImagesIamPolicies), 'global'); + return callback(null, results, source); + } + + if (!getImagesIamPolicies.data.length) { + helpers.addResult(results, 0, 'No IAM Policies found', 'global'); + return callback(null, results, source); + } + + getImagesIamPolicies = getImagesIamPolicies.data; + + images.data.forEach(image => { + + let imageIamPolicy = getImagesIamPolicies.find(iamPolicy => iamPolicy.parent && iamPolicy.parent.id === image.id); + + let resource = helpers.createResourceName('images', image.name, project, 'global'); + + if (!imageIamPolicy || !imageIamPolicy.bindings || !imageIamPolicy.bindings.length) { + helpers.addResult(results, 0, + 'No IAM Policies found for disk image', 'global', resource); + } else { + var allowedAllUsers = false; + imageIamPolicy.bindings.forEach(roleBinding => { + if (roleBinding.role && roleBinding.members && roleBinding.members.length && (roleBinding.members.includes('allUsers') || roleBinding.members.includes('allAuthenticatedUsers'))) { + allowedAllUsers = true; + } + }); + if (!allowedAllUsers) { + helpers.addResult(results, 0, 'Disk Image is not publicly accessible', 'global', resource); + } else { + helpers.addResult(results, 2, 'Disk Image is publicly accessible', 'global', resource); + } + } + }); + callback(null, results, source); + } +}; \ No newline at end of file diff --git a/plugins/google/compute/publicDiskImages.spec.js b/plugins/google/compute/publicDiskImages.spec.js new file mode 100644 index 0000000000..2cb9d2d35e --- /dev/null +++ b/plugins/google/compute/publicDiskImages.spec.js @@ -0,0 +1,241 @@ +var expect = require('chai').expect; +var plugin = require('./publicDiskImages'); + +const imagePolicies = [ + { + "version": 1, + "etag": "BwXZ3RM6WFs=", + "bindings": [ + { + "role": "roles/compute.imageUser", + "members": [ + "allUsers", + ] + }, + ], + "parent": { + "id": "1231", + "creationTimestamp": "2022-03-09T16:05:01.878-08:00", + "name": "image-1", + "sourceDisk": "https://www.googleapis.com/compute/v1/projects/test-proj/zones/us-central1-a/disks/disk-1", + "sourceDiskId": "4476293856257965646", + "selfLink": "https://www.googleapis.com/compute/v1/projects/test-proj/global/images/image-1", + + "kind": "compute#image" + } + }, + { + "version": 1, + "etag": "BwXZ3RM6WFs=", + "bindings": [ + { + "role": "roles/compute.imageUser", + "members": [ + "myserviceaccount@gmail.com", + ] + }, + ], + "parent": { + "id": 1232, + "creationTimestamp": "2022-03-09T16:05:01.878-08:00", + "name": "image-2", + "sourceDisk": "https://www.googleapis.com/compute/v1/projects/test-proj/zones/us-central1-a/disks/disk-2", + "sourceDiskId": "4476293856257965646", + "selfLink": "https://www.googleapis.com/compute/v1/projects/test-proj/global/images/image-2", + "kind": "compute#image" + } + } +] +const images = [ + { + "id": "1231", + "creationTimestamp": "2022-03-09T16:05:01.878-08:00", + "name": "image-1", + "sourceDisk": "https://www.googleapis.com/compute/v1/projects/test-proj/zones/us-central1-a/disks/disk-1", + "sourceDiskId": "4476293856257965646", + "selfLink": "https://www.googleapis.com/compute/v1/projects/test-proj/global/images/image-1", + "kind": "compute#image" + }, + { + "id": 1232, + "creationTimestamp": "2022-03-09T16:05:01.878-08:00", + "name": "image-2", + "sourceDisk": "https://www.googleapis.com/compute/v1/projects/test-proj/zones/us-central1-a/disks/disk-2", + "sourceDiskId": "4476293856257965646", + "selfLink": "https://www.googleapis.com/compute/v1/projects/test-proj/global/images/image-2", + "kind": "compute#image" + }, + { + "id": "1233", + "creationTimestamp": "2022-03-09T16:05:01.878-08:00", + "name": "image-3", + "sourceDisk": "https://www.googleapis.com/compute/v1/projects/test-proj/zones/us-central1-a/disks/disk-3", + "sourceDiskId": "4476293856257965646", + "selfLink": "https://www.googleapis.com/compute/v1/projects/test-proj/global/images/image-3", + "kind": "compute#image" + } +]; +const createCache = (imageData, error, policyData, policyErr) => { + return { + images: { + list: { + 'global': { + data: imageData, + err: error + } + }, + getIamPolicy: { + 'global': { + data: policyData, + err: policyErr + + } + } + }, + projects: { + get: { + 'global': { + data: 'test-proj' + } + } + } + } +}; + +describe('publicDiskImages', function () { + describe('run', function () { + + it('should give unknown if unable to query disk images', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('Unable to query Disk Images'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + [], + ['error'], + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should pass if no disk images found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No Disk Images found'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + [], + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query IAM Policies for disk images', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('Unable to query IAM Policies for Disk Images'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + images, + null, + [], + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should pass if no IAM Policies found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No IAM Policies found'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + images, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should fail if disk image is publicly accessible', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Disk Image is publicly accessible'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + [images[0]], + null, + [imagePolicies[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should pass if no IAM policies are found for disk image', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No IAM Policies found for disk image'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + [images[2]], + null, + [imagePolicies], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should pass if disk image is not publicly accessible', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Disk Image is not publicly accessible'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + [images[1]], + null, + [imagePolicies[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }) +}); \ No newline at end of file From 3b5fa5ae2fac0de41e8732f8f3d1f5cae8a05e52 Mon Sep 17 00:00:00 2001 From: Mehak Seedat Date: Thu, 10 Mar 2022 17:30:05 +0500 Subject: [PATCH 029/350] GCP Refactoring Post Calls --- helpers/google/index.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/helpers/google/index.js b/helpers/google/index.js index a84a922d33..685e5fd8ec 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -282,6 +282,7 @@ var execute = async function(LocalGoogleConfig, collection, service, callObj, ca } else if (!myEngine && !(collection[service][callKey][region].data.length)) { collection[service][callKey][region].data = []; } + resultItems = setData(collectionItems, data.data, postCall, parent); } else { set = false; myEngine ? collection[service][myEngine][callKey][region].data = [] : collection[service][callKey][region].data = []; @@ -374,6 +375,16 @@ function makeApiCall(client, originalUrl, callCb, nextToken, config) { } function setData(collection, dataToAdd, postCall, parent) { + if (postCall && !!parent) { + if (dataToAdd && dataToAdd.length) { + dataToAdd.map(item => { + item.parent = parent; + return item; + }); + } else if (Object.keys(dataToAdd) && Object.keys(dataToAdd).length) { + dataToAdd.parent = parent; + } + } if (dataToAdd.constructor.name === 'Array') { collection.data = collection.data.concat(dataToAdd); } else { @@ -384,12 +395,6 @@ function setData(collection, dataToAdd, postCall, parent) { collection.data = dataToAdd; } } - if (postCall && !!parent) { - collection.data.map(item => { - item.parent = parent; - return item; - }); - } return collection; } From d991bbfb2772924e7c49af147a1c8cd54877a9bb Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Tue, 15 Mar 2022 15:25:22 -0700 Subject: [PATCH 030/350] Added backupRetentionPeriod plugin for app service --- collectors/azure/collector.js | 5 + exports.js | 1 + .../azure/appservice/backupRetentionPeriod.js | 64 ++++++++ .../appservice/backupRetentionPeriod.spec.js | 143 ++++++++++++++++++ 4 files changed, 213 insertions(+) create mode 100644 plugins/azure/appservice/backupRetentionPeriod.js create mode 100644 plugins/azure/appservice/backupRetentionPeriod.spec.js diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index c7fc096367..38da229e79 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -388,6 +388,11 @@ var postcalls = { reliesOnPath: 'webApps.list', properties: ['id'], url: 'https://management.azure.com/{id}/config?api-version=2019-08-01' + }, + getBackupConfigurations: { + reliesOnPath: 'webApps.list', + properties: ['resourceGroupName', 'name'], + url: 'https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{name}/config/backup/list?api-version=2021-02-01' } }, endpoints: { diff --git a/exports.js b/exports.js index 36d4be0d16..a1715a745c 100644 --- a/exports.js +++ b/exports.js @@ -683,6 +683,7 @@ module.exports = { 'certificateExpiry' : require(__dirname + '/plugins/azure/appservice/certificateExpiry.js'), 'scmSiteAccessRestriction' : require(__dirname + '/plugins/azure/appservice/scmSiteAccessRestriction.js'), 'appServiceAccessRestriction' : require(__dirname + '/plugins/azure/appservice/appServiceAccessRestriction.js'), + 'backupRetentionPeriod' : require(__dirname + '/plugins/azure/appservice/backupRetentionPeriod.js'), 'rbacEnabled' : require(__dirname + '/plugins/azure/kubernetesservice/rbacEnabled.js'), 'aksLatestVersion' : require(__dirname + '/plugins/azure/kubernetesservice/aksLatestVersion.js'), diff --git a/plugins/azure/appservice/backupRetentionPeriod.js b/plugins/azure/appservice/backupRetentionPeriod.js new file mode 100644 index 0000000000..42ccd8d069 --- /dev/null +++ b/plugins/azure/appservice/backupRetentionPeriod.js @@ -0,0 +1,64 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Web Apps Always On Enabled', + category: 'App Service', + domain: 'Application Integration', + description: 'Ensures that Azure Web Apps have Always On feature enabled.', + more_info: 'Always On feature keeps the app loaded even when there\'s no traffic. It\'s required for continuous WebJobs or for WebJobs that are triggered using a CRON expression.', + recommended_action: 'Enable Always On feature for Azure Web Apps', + link: 'https://docs.microsoft.com/en-us/azure/app-service/configure-common', + apis: ['webApps:list', 'webApps:listConfigurations'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.webApps, function(location, rcb) { + const webApps = helpers.addSource(cache, source, + ['webApps', 'list', location]); + + if (!webApps) return rcb(); + + if (webApps.err || !webApps.data) { + helpers.addResult(results, 3, 'Unable to query for Web Apps: ' + helpers.addError(webApps), location); + return rcb(); + } + + if (!webApps.data.length) { + helpers.addResult(results, 0, 'No existing Web Apps found', location); + return rcb(); + } + + async.each(webApps.data, function(webApp, scb) { + if (webApp && webApp.kind && webApp.kind === 'functionapp') { + helpers.addResult(results, 0, 'Always On feature can not be configured for the function App', location, webApp.id); + return scb(); + } + + const configs = helpers.addSource(cache, source, + ['webApps', 'getBackupConfigurations', location, 'akhtar-rg', 'akhtar-test']); + + if (!configs || configs.err || !configs.data || !configs.data.length) { + helpers.addResult(results, 3, 'Unable to query for Web App Configs: ' + helpers.addError(configs), location); + return scb(); + } + const alwaysOnEnabled = configs.find(config => config.backupSchedule); + if (alwaysOnEnabled) { + helpers.addResult(results, 0, 'Always On feature is enabled for the Web App', location, webApp.id); + } else { + helpers.addResult(results, 2, 'Always On feature is disabled for the Web App', location, webApp.id); + } + + scb(); + }, function() { + rcb(); + }); + }, function() { + // Global checking goes here + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/appservice/backupRetentionPeriod.spec.js b/plugins/azure/appservice/backupRetentionPeriod.spec.js new file mode 100644 index 0000000000..0b6ca5d19e --- /dev/null +++ b/plugins/azure/appservice/backupRetentionPeriod.spec.js @@ -0,0 +1,143 @@ +var expect = require('chai').expect; +var alwaysOnEnabled = require('./alwaysOnEnabled'); + +const webApps = [ + { + 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/test-app', + 'name': 'test-app', + 'type': 'Microsoft.Web/sites', + 'kind': 'app,linux', + 'location': 'East US' + }, + { + 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/test-app', + 'name': 'test-app', + 'type': 'Microsoft.Web/sites', + 'kind': 'functionapp', + 'location': 'East US' + } +]; + +const configs = [ + { + 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/test-app', + 'name': 'test-app', + 'type': 'Microsoft.Web/sites', + 'location': 'East US', + 'alwaysOn': true + }, + { + 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/test-app', + 'name': 'test-app', + 'type': 'Microsoft.Web/sites', + 'location': 'East US', + 'alwaysOn': false + } +]; + +const createCache = (webApps, configs) => { + let app = {}; + let config = {}; + + if (webApps) { + app['data'] = webApps; + if (webApps && webApps.length) { + config[webApps[0].id] = { + 'data': configs + }; + } + } + + return { + webApps: { + list: { + 'eastus': app + }, + listConfigurations: { + 'eastus': config + } + } + }; +}; + +describe('alwaysOnEnabled', function() { + describe('run', function() { + it('should give passing result if no web apps', function(done) { + const cache = createCache([]); + alwaysOnEnabled.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 Web Apps found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for web apps', function(done) { + const cache = createCache(); + alwaysOnEnabled.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 Web Apps'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if always on can not be configured', function(done) { + const cache = createCache([webApps[1]], []); + alwaysOnEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Always On feature can not be configured for the function App'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + + it('should give unknown result if no web app configs', function(done) { + const cache = createCache([webApps[0]], []); + alwaysOnEnabled.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 Web App Configs:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for web app configs', function(done) { + const cache = createCache([webApps[0]]); + alwaysOnEnabled.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 Web App Configs:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if always on is enabled', function(done) { + const cache = createCache([webApps[0]], [configs[0]]); + alwaysOnEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Always On feature is enabled for the Web App'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if always on is disabled', function(done) { + const cache = createCache([webApps[0]], [configs[1]]); + alwaysOnEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Always On feature is disabled for the Web App'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); From 08417f2c129d3d2c4074da8ff281e41dd8b14f7d Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Wed, 16 Mar 2022 02:42:25 -0700 Subject: [PATCH 031/350] Refactored code --- collectors/azure/collector.js | 7 +- .../azure/appservice/backupRetentionPeriod.js | 37 ++++++--- .../appservice/backupRetentionPeriod.spec.js | 79 ++++++++++--------- 3 files changed, 73 insertions(+), 50 deletions(-) diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index 38da229e79..b9a63c9599 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -389,10 +389,11 @@ var postcalls = { properties: ['id'], url: 'https://management.azure.com/{id}/config?api-version=2019-08-01' }, - getBackupConfigurations: { + getBackupConfiguration: { reliesOnPath: 'webApps.list', - properties: ['resourceGroupName', 'name'], - url: 'https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{name}/config/backup/list?api-version=2021-02-01' + properties: ['id'], + url: 'https://management.azure.com/{id}/config/backup/list?api-version=2021-02-01', + post: true } }, endpoints: { diff --git a/plugins/azure/appservice/backupRetentionPeriod.js b/plugins/azure/appservice/backupRetentionPeriod.js index 42ccd8d069..4dde51dd06 100644 --- a/plugins/azure/appservice/backupRetentionPeriod.js +++ b/plugins/azure/appservice/backupRetentionPeriod.js @@ -9,12 +9,21 @@ module.exports = { more_info: 'Always On feature keeps the app loaded even when there\'s no traffic. It\'s required for continuous WebJobs or for WebJobs that are triggered using a CRON expression.', recommended_action: 'Enable Always On feature for Azure Web Apps', link: 'https://docs.microsoft.com/en-us/azure/app-service/configure-common', - apis: ['webApps:list', 'webApps:listConfigurations'], + apis: ['webApps:list', 'webApps:getBackupConfiguration'], + settings: { + webapps_backup_retention_period: { + name: 'Backup retention period in days', + description: 'Backup retention period for web apps in days.', + regex: '^[1-9]{1}[0-9]{0,3}$', + default: 7 + } + }, run: function(cache, settings, callback) { var results = []; var source = {}; var locations = helpers.locations(settings.govcloud); + var webapps_backup_retention_period = parseInt(settings.webapps_backup_retention_period || this.settings.webapps_backup_retention_period.default); async.each(locations.webApps, function(location, rcb) { const webApps = helpers.addSource(cache, source, @@ -34,22 +43,32 @@ module.exports = { async.each(webApps.data, function(webApp, scb) { if (webApp && webApp.kind && webApp.kind === 'functionapp') { - helpers.addResult(results, 0, 'Always On feature can not be configured for the function App', location, webApp.id); + helpers.addResult(results, 0, 'WebApps backup can not be configured for the function App', location, webApp.id); return scb(); } const configs = helpers.addSource(cache, source, - ['webApps', 'getBackupConfigurations', location, 'akhtar-rg', 'akhtar-test']); + ['webApps', 'getBackupConfiguration', location, webApp.id]); - if (!configs || configs.err || !configs.data || !configs.data.length) { - helpers.addResult(results, 3, 'Unable to query for Web App Configs: ' + helpers.addError(configs), location); + if (!configs || configs.err || !configs.data) { + helpers.addResult(results, 3, 'Unable to query for Web App Backup Configs: ' + helpers.addError(configs), location); return scb(); } - const alwaysOnEnabled = configs.find(config => config.backupSchedule); - if (alwaysOnEnabled) { - helpers.addResult(results, 0, 'Always On feature is enabled for the Web App', location, webApp.id); + + const { backupSchedule } = configs.data; + if (backupSchedule && backupSchedule.retentionPeriodInDays) { + if (backupSchedule.retentionPeriodInDays >= webapps_backup_retention_period) { + helpers.addResult(results, 0, + `WebApp has a backup retention period of ${backupSchedule.retentionPeriodInDays} of ${webapps_backup_retention_period} days limit`, + location, webApp.id); + } else { + helpers.addResult(results, 2, + `WebApp has a backup retention period of ${backupSchedule.retentionPeriodInDays} of ${webapps_backup_retention_period} days limit`, + location, webApp.id); + } } else { - helpers.addResult(results, 2, 'Always On feature is disabled for the Web App', location, webApp.id); + helpers.addResult(results, 2, + 'No backup configurations found for this WebApp', location, webApp.id); } scb(); diff --git a/plugins/azure/appservice/backupRetentionPeriod.spec.js b/plugins/azure/appservice/backupRetentionPeriod.spec.js index 0b6ca5d19e..d7a2a06b5b 100644 --- a/plugins/azure/appservice/backupRetentionPeriod.spec.js +++ b/plugins/azure/appservice/backupRetentionPeriod.spec.js @@ -1,5 +1,5 @@ var expect = require('chai').expect; -var alwaysOnEnabled = require('./alwaysOnEnabled'); +var backupRetentionPeriod = require('./backupRetentionPeriod'); const webApps = [ { @@ -18,22 +18,25 @@ const webApps = [ } ]; -const configs = [ - { - 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/test-app', - 'name': 'test-app', - 'type': 'Microsoft.Web/sites', - 'location': 'East US', - 'alwaysOn': true +const backupConfigs = { + id: '/subscriptions/dce7d0ad-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/akhtar-rg/providers/Microsoft.Web/sites/akhtar-test', + name: 'akhtar-test', + type: 'Default', + location: 'Central US', + backupName: 'akhtar-test', + enabled: true, + storageAccountUrl: 'https://akhtarrgdiag.blob.core.windows.net/appbackup?sp=rwdl&st=2022-03-16T07:51:37Z&se=2295-12-29T08:51:37Z&sv=2020-08-04&sr=c&sig=FeC0hGUrqJb6b%2Bh5qbIif84725sMjeqyNUzWa4tL3L4%3D', + backupSchedule: { + frequencyInterval: 7, + frequencyUnit: 'Day', + keepAtLeastOneBackup: true, + retentionPeriodInDays: 7, + startTime: '2022-03-16T07:51:38.699', + lastExecutionTime: '2022-03-16T07:53:38.4131659' }, - { - 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/test-app', - 'name': 'test-app', - 'type': 'Microsoft.Web/sites', - 'location': 'East US', - 'alwaysOn': false - } -]; + databases: [], + mySqlDumpParams: null +}; const createCache = (webApps, configs) => { let app = {}; @@ -53,18 +56,18 @@ const createCache = (webApps, configs) => { list: { 'eastus': app }, - listConfigurations: { + getBackupConfiguration: { 'eastus': config } } }; }; -describe('alwaysOnEnabled', function() { +describe('backupRetentionPeriod', function() { describe('run', function() { it('should give passing result if no web apps', function(done) { const cache = createCache([]); - alwaysOnEnabled.run(cache, {}, (err, results) => { + backupRetentionPeriod.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 Web Apps found'); @@ -75,7 +78,7 @@ describe('alwaysOnEnabled', function() { it('should give unknown result if unable to query for web apps', function(done) { const cache = createCache(); - alwaysOnEnabled.run(cache, {}, (err, results) => { + backupRetentionPeriod.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 Web Apps'); @@ -84,57 +87,57 @@ describe('alwaysOnEnabled', function() { }); }); - it('should give passing result if always on can not be configured', function(done) { + it('should give passing result if web apps backups can not be configured', function(done) { const cache = createCache([webApps[1]], []); - alwaysOnEnabled.run(cache, {}, (err, results) => { + backupRetentionPeriod.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('Always On feature can not be configured for the function App'); + expect(results[0].message).to.include('WebApps backup can not be configured for the function App'); expect(results[0].region).to.equal('eastus'); done(); }); }); - it('should give unknown result if no web app configs', function(done) { + it('should give failing result if no web app backup config found', function(done) { const cache = createCache([webApps[0]], []); - alwaysOnEnabled.run(cache, {}, (err, results) => { + backupRetentionPeriod.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 Web App Configs:'); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('No backup configurations found for this WebApp'); expect(results[0].region).to.equal('eastus'); done(); }); }); - it('should give unknown result if unable to query for web app configs', function(done) { + it('should give unknown result if unable to query for web app backup configs', function(done) { const cache = createCache([webApps[0]]); - alwaysOnEnabled.run(cache, {}, (err, results) => { + backupRetentionPeriod.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 Web App Configs:'); + expect(results[0].message).to.include('Unable to query for Web App Backup Configs'); expect(results[0].region).to.equal('eastus'); done(); }); }); - it('should give passing result if always on is enabled', function(done) { - const cache = createCache([webApps[0]], [configs[0]]); - alwaysOnEnabled.run(cache, {}, (err, results) => { + it('should give passing result if web app backup retention period is within the recommended threshold', function(done) { + const cache = createCache([webApps[0]], backupConfigs); + backupRetentionPeriod.run(cache, { webapps_backup_retention_period: 7 }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('Always On feature is enabled for the Web App'); + expect(results[0].message).to.include('WebApp has a backup retention period of 7 of 7 days'); expect(results[0].region).to.equal('eastus'); done(); }); }); - it('should give failing result if always on is disabled', function(done) { - const cache = createCache([webApps[0]], [configs[1]]); - alwaysOnEnabled.run(cache, {}, (err, results) => { + it('should give failing result if web app backup retention period is below the recommended threshold', function(done) { + const cache = createCache([webApps[0]], backupConfigs); + backupRetentionPeriod.run(cache, { webapps_backup_retention_period: 10 }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('Always On feature is disabled for the Web App'); + expect(results[0].message).to.include('WebApp has a backup retention period of 7 of 10 days limit'); expect(results[0].region).to.equal('eastus'); done(); }); From 65733ef479a694b0b7b569780f45c67993a4d76d Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Wed, 16 Mar 2022 02:50:23 -0700 Subject: [PATCH 032/350] Added checkAdvisorRecommendations plugin and spec --- collectors/azure/collector.js | 5 ++ exports.js | 2 + helpers/azure/locations.js | 3 +- .../advisor/checkAdvisorRecommendations.js | 42 ++++++++++ .../checkAdvisorRecommendations.spec.js | 82 +++++++++++++++++++ 5 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 plugins/azure/advisor/checkAdvisorRecommendations.js create mode 100644 plugins/azure/advisor/checkAdvisorRecommendations.spec.js diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index c7fc096367..03acb92328 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -26,6 +26,11 @@ var calls = { url: 'https://management.azure.com/subscriptions/{subscriptionId}/resourcegroups?api-version=2019-10-01' } }, + advisor: { + recommendationsList: { + url: 'https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Advisor/recommendations?api-version=2020-01-01' + } + }, activityLogAlerts: { listBySubscriptionId: { url: 'https://management.azure.com/subscriptions/{subscriptionId}/providers/microsoft.insights/activityLogAlerts?api-version=2020-10-01' diff --git a/exports.js b/exports.js index 36d4be0d16..1e84a4398b 100644 --- a/exports.js +++ b/exports.js @@ -716,6 +716,8 @@ module.exports = { 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), 'automaticFailoverEnabled' : require(__dirname + '/plugins/azure/cosmosdb/automaticFailoverEnabled.js'), + + 'checkAdvisorRecommendations' : require(__dirname + '/plugins/azure/advisor/checkAdvisorRecommendations.js'), }, github: { 'publicKeysRotated' : require(__dirname + '/plugins/github/users/publicKeysRotated.js'), diff --git a/helpers/azure/locations.js b/helpers/azure/locations.js index c43b4d9b4f..9e54316fd4 100644 --- a/helpers/azure/locations.js +++ b/helpers/azure/locations.js @@ -90,5 +90,6 @@ module.exports = { resourceGroups: locations, policyDefinitions: locations, diagnosticSettingsOperations: ['global'], - databaseAccounts: locations + databaseAccounts: locations, + advisor: ['global'] }; diff --git a/plugins/azure/advisor/checkAdvisorRecommendations.js b/plugins/azure/advisor/checkAdvisorRecommendations.js new file mode 100644 index 0000000000..d5456bdb4e --- /dev/null +++ b/plugins/azure/advisor/checkAdvisorRecommendations.js @@ -0,0 +1,42 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Advisor Recommendations', + category: 'Advisor', + domain: 'Application Integration', + description: 'Ensure that all Microsoft Azure Advisor recommendations found are implemented to optimize your cloud deployments, increase security, and reduce costs.', + more_info: 'Advisor service analyzes your Azure cloud configurations and resource usage telemetry to provide personalized and actionable recommendations that can help you optimize your cloud resources for security, reliability and high availability, operational excellence, performance efficiency, and cost.', + recommended_action: 'Implement all Microsoft Azurer Adivsor recommendations.', + link: 'https://docs.microsoft.com/en-us/azure/advisor/advisor-get-started', + apis: ['advisor:recommendationsList'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.advisor, function(location, rcb) { + const recommendationList = helpers.addSource(cache, source, + ['advisor', 'recommendationsList', location]); + + if (!recommendationList) return rcb(); + + if (recommendationList.err || !recommendationList.data) { + helpers.addResult(results, 3, 'Unable to query for Advisor Recommendations: ' + helpers.addError(recommendationList), location); + return rcb(); + } + + if (!recommendationList.data.length) { + helpers.addResult(results, 0, 'No Advisor Recommendations found', location); + return rcb(); + } else { + helpers.addResult(results, 2, 'Advisor Recommendations found', location); + } + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/advisor/checkAdvisorRecommendations.spec.js b/plugins/azure/advisor/checkAdvisorRecommendations.spec.js new file mode 100644 index 0000000000..c8443c839c --- /dev/null +++ b/plugins/azure/advisor/checkAdvisorRecommendations.spec.js @@ -0,0 +1,82 @@ +var expect = require('chai').expect; +var checkAdvisorRecommendations = require('./checkAdvisorRecommendations'); + +const recommendationsList = [ + { + "category": "HighAvailability", + "extendedProperties": { + "assessmentKey": "abcd1234-abcd-1234-abcd-abcd1234abcd", + "score": "50" + }, + "id": "/subscriptions/abcdabcd-1234-abcd-1234-abcdabcdabcd/providers/Microsoft.Advisor/recommendations/abcdabcd-abcd-abcd-abcd-abcdabcdabcd", + "impact": "High", + "impactedField": "Microsoft.Subscriptions/subscriptions", + "impactedValue": "abcdabcd-1234-abcd-1234-abcdabcdabcd", + "lastUpdated": "2020-06-02T15:10:46.164346+00:00", + "metadata": null, + "name": "abcdabcd-abcd-abcd-abcd-abcdabcdabcd", + "recommendationTypeId": "abcd1234-abcd-1234-abcd-abcd1234abcd", + "risk": null, + "shortDescription": { + "problem": "Enable Soft Delete", + "solution": "Use soft delete on your Azure Storage Account to save and recover data after accidental overwrite or deletion" + }, + "suppressionIds": null, + "type": "Microsoft.Advisor/recommendations" + }, +]; + +const createCache = (err, recommendationsList) => { + return { + advisor: { + recommendationsList: { + 'global': { + data: recommendationsList + } + } + } + } +}; + +describe('checkAdvisorRecommendations', function() { + describe('run', function() { + it('should give passing result if no Adivsor Recommendations are 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 Advisor Recommendations found') + expect(results[0].region).to.equal('global') + done() + }; + + const cache = createCache(null, []); + checkAdvisorRecommendations.run(cache, {}, callback); + }); + + it('should give failing result if Advisor Recommendations found', 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('Advisor Recommendations found') + expect(results[0].region).to.equal('global') + done() + }; + + const cache = createCache(null, recommendationsList); + checkAdvisorRecommendations.run(cache, {}, callback); + }); + + it('should give UNKNOWN result if unable to queyr for Advisor Recommendations', 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 Advisor Recommendations') + expect(results[0].region).to.equal('global') + done() + }; + + const cache = createCache(null); + checkAdvisorRecommendations.run(cache, {}, callback); + }); + }) +}) \ No newline at end of file From bb06cc7ccad37277517e152e8d0d6b487e274871 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Wed, 16 Mar 2022 02:56:40 -0700 Subject: [PATCH 033/350] Modified description --- plugins/azure/appservice/backupRetentionPeriod.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/azure/appservice/backupRetentionPeriod.js b/plugins/azure/appservice/backupRetentionPeriod.js index 4dde51dd06..4ee6335f16 100644 --- a/plugins/azure/appservice/backupRetentionPeriod.js +++ b/plugins/azure/appservice/backupRetentionPeriod.js @@ -2,13 +2,13 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); module.exports = { - title: 'Web Apps Always On Enabled', + title: 'Web Apps Backup Retention Period', category: 'App Service', domain: 'Application Integration', - description: 'Ensures that Azure Web Apps have Always On feature enabled.', - more_info: 'Always On feature keeps the app loaded even when there\'s no traffic. It\'s required for continuous WebJobs or for WebJobs that are triggered using a CRON expression.', - recommended_action: 'Enable Always On feature for Azure Web Apps', - link: 'https://docs.microsoft.com/en-us/azure/app-service/configure-common', + description: 'Ensures that Azure Web Apps have recommended backup retention period.', + more_info: 'Retaining application backups for a longer period of time will allow you to handle more efficiently your app data restoration process..', + recommended_action: 'Configure backup retention period for Azure Web Apps', + link: 'https://docs.microsoft.com/en-us/azure/app-service/manage-backup', apis: ['webApps:list', 'webApps:getBackupConfiguration'], settings: { webapps_backup_retention_period: { From acf7483de34716df97dd2aab5531767f5622e538 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Wed, 16 Mar 2022 04:47:17 -0700 Subject: [PATCH 034/350] Added appInsightsEnabled plugin and spec --- collectors/azure/collector.js | 6 + exports.js | 1 + .../azure/appservice/appInsightsEnabled.js | 63 ++++++++ .../appservice/appInsightsEnabled.spec.js | 151 ++++++++++++++++++ 4 files changed, 221 insertions(+) create mode 100644 plugins/azure/appservice/appInsightsEnabled.js create mode 100644 plugins/azure/appservice/appInsightsEnabled.spec.js diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index c7fc096367..1dd29d880d 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -388,6 +388,12 @@ var postcalls = { reliesOnPath: 'webApps.list', properties: ['id'], url: 'https://management.azure.com/{id}/config?api-version=2019-08-01' + }, + listAppSettings: { + reliesOnPath: 'webApps.list', + properties: ['id'], + url: 'https://management.azure.com/{id}/config/appsettings/list?api-version=2021-02-01', + post: true } }, endpoints: { diff --git a/exports.js b/exports.js index 36d4be0d16..c64fb44ea5 100644 --- a/exports.js +++ b/exports.js @@ -683,6 +683,7 @@ module.exports = { 'certificateExpiry' : require(__dirname + '/plugins/azure/appservice/certificateExpiry.js'), 'scmSiteAccessRestriction' : require(__dirname + '/plugins/azure/appservice/scmSiteAccessRestriction.js'), 'appServiceAccessRestriction' : require(__dirname + '/plugins/azure/appservice/appServiceAccessRestriction.js'), + 'appInsightsEnabled' : require(__dirname + '/plugins/azure/appservice/appInsightsEnabled.js'), 'rbacEnabled' : require(__dirname + '/plugins/azure/kubernetesservice/rbacEnabled.js'), 'aksLatestVersion' : require(__dirname + '/plugins/azure/kubernetesservice/aksLatestVersion.js'), diff --git a/plugins/azure/appservice/appInsightsEnabled.js b/plugins/azure/appservice/appInsightsEnabled.js new file mode 100644 index 0000000000..9cde9c166d --- /dev/null +++ b/plugins/azure/appservice/appInsightsEnabled.js @@ -0,0 +1,63 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Web Apps Insights Enabled', + category: 'App Service', + domain: 'Application Integration', + description: 'Ensures that Application Insights feature is enabled.', + more_info: 'Application insights provide advanced application monitoring. Application Insights is an extensible Application Performance Management (APM) service for developers and DevOps professionals available as monitoring feature within Azure cloud.', + recommended_action: 'Enable Application insights for Azure Web Apps', + link: 'https://docs.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview', + apis: ['webApps:list', 'webApps:listAppSettings'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.webApps, function(location, rcb) { + const webApps = helpers.addSource(cache, source, + ['webApps', 'list', location]); + + if (!webApps) return rcb(); + + if (webApps.err || !webApps.data) { + helpers.addResult(results, 3, 'Unable to query for Web Apps: ' + helpers.addError(webApps), location); + return rcb(); + } + + if (!webApps.data.length) { + helpers.addResult(results, 0, 'No existing Web Apps found', location); + return rcb(); + } + + async.each(webApps.data, function(webApp, scb) { + if (webApp && webApp.kind && webApp.kind === 'functionapp') { + helpers.addResult(results, 0, 'Application insights feature cannot be configured for the function App', location, webApp.id); + return scb(); + } + + const configs = helpers.addSource(cache, source, + ['webApps', 'listAppSettings', location, webApp.id]); + + if (!configs || configs.err || !configs.data) { + helpers.addResult(results, 3, 'Unable to query for Web App Insights: ' + helpers.addError(configs), location); + return scb(); + } + + if (configs.data.ApplicationInsightsAgent_EXTENSION_VERSION && configs.data.ApplicationInsightsAgent_EXTENSION_VERSION.toLowerCase() !== 'default') { + helpers.addResult(results, 0, 'App Insights feature is enabled for the Web App', location, webApp.id); + } else { + helpers.addResult(results, 2, 'App Insights feature is disabled for the Web App', location, webApp.id); + } + + scb(); + }, function() { + rcb(); + }); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/appservice/appInsightsEnabled.spec.js b/plugins/azure/appservice/appInsightsEnabled.spec.js new file mode 100644 index 0000000000..06dfa08694 --- /dev/null +++ b/plugins/azure/appservice/appInsightsEnabled.spec.js @@ -0,0 +1,151 @@ +var expect = require('chai').expect; +var appInsightsEnabled = require('./appInsightsEnabled'); + +const webApps = [ + { + 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/test-app', + 'name': 'test-app', + 'type': 'Microsoft.Web/sites', + 'kind': 'app,linux', + 'location': 'East US' + }, + { + 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/test-app', + 'name': 'test-app', + 'type': 'Microsoft.Web/sites', + 'kind': 'functionapp', + 'location': 'East US' + } +]; + +const appSettings = [ + { + id: '/subscriptions/dce7d0ad-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/akhtar-rg/providers/Microsoft.Web/sites/akhtar-test/config/appsettings', + name: 'appsettings', + type: 'Microsoft.Web/sites/config', + location: 'Central US', + APPINSIGHTS_INSTRUMENTATIONKEY: '2f521d9c-2a65-4ab2-8108-8b8a0902790e', + APPLICATIONINSIGHTS_CONNECTION_STRING: 'InstrumentationKey=2f521d9c-2a65-4ab2-8108-8b8a0902790e;IngestionEndpoint=https://centralus-2.in.applicationinsights.azure.com/', + ApplicationInsightsAgent_EXTENSION_VERSION: '~3', + XDT_MicrosoftApplicationInsights_Mode: 'default', + APPINSIGHTS_PROFILERFEATURE_VERSION: 'disabled', + DiagnosticServices_EXTENSION_VERSION: 'disabled', + APPINSIGHTS_SNAPSHOTFEATURE_VERSION: 'disabled', + SnapshotDebugger_EXTENSION_VERSION: 'disabled', + InstrumentationEngine_EXTENSION_VERSION: 'disabled', + XDT_MicrosoftApplicationInsights_BaseExtensions: 'disabled', + XDT_MicrosoftApplicationInsights_PreemptSdk: 'disabled' + }, + { + id: '/subscriptions/dce7d0ad-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/akhtar-rg/providers/Microsoft.Web/sites/akhtar-test/config/appsettings', + name: 'appsettings', + type: 'Microsoft.Web/sites/config', + location: 'Central US', + APPINSIGHTS_INSTRUMENTATIONKEY: '2f521d9c-2a65-4ab2-8108-8b8a0902790e', + APPLICATIONINSIGHTS_CONNECTION_STRING: 'InstrumentationKey=2f521d9c-2a65-4ab2-8108-8b8a0902790e;IngestionEndpoint=https://centralus-2.in.applicationinsights.azure.com/', + ApplicationInsightsAgent_EXTENSION_VERSION: 'default', + XDT_MicrosoftApplicationInsights_Mode: 'default', + APPINSIGHTS_PROFILERFEATURE_VERSION: 'disabled', + DiagnosticServices_EXTENSION_VERSION: 'disabled', + APPINSIGHTS_SNAPSHOTFEATURE_VERSION: 'disabled', + SnapshotDebugger_EXTENSION_VERSION: 'disabled', + InstrumentationEngine_EXTENSION_VERSION: 'disabled', + XDT_MicrosoftApplicationInsights_BaseExtensions: 'disabled', + XDT_MicrosoftApplicationInsights_PreemptSdk: 'disabled' + } +]; + +const createCache = (webApps, configs) => { + let app = {}; + let config = {}; + + if (webApps) { + app['data'] = webApps; + if (webApps && webApps.length) { + config[webApps[0].id] = { + 'data': configs + }; + } + } + + return { + webApps: { + list: { + 'eastus': app + }, + listAppSettings: { + 'eastus': config + } + } + }; +}; + +describe('appInsightsEnabled', function() { + describe('run', function() { + it('should give passing result if no web apps', function(done) { + const cache = createCache([]); + appInsightsEnabled.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 Web Apps found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for web apps', function(done) { + const cache = createCache(); + appInsightsEnabled.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 Web Apps'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if application insights can not be configured', function(done) { + const cache = createCache([webApps[1]], []); + appInsightsEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Application insights feature cannot be configured for the function App'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for web app settings', function(done) { + const cache = createCache([webApps[0]]); + appInsightsEnabled.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 Web App Insights:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if application insights is enabled', function(done) { + const cache = createCache([webApps[0]], appSettings[0]); + appInsightsEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('App Insights feature is enabled for the Web App'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if always on is disabled', function(done) { + const cache = createCache([webApps[0]], appSettings[1]); + appInsightsEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('App Insights feature is disabled for the Web App'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file From 00276cc6aeaed579ea3928db45ed676b660b3db3 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Wed, 16 Mar 2022 05:14:40 -0700 Subject: [PATCH 035/350] Added automatedBackupsEnabled plugin and spec --- collectors/azure/collector.js | 8 +- exports.js | 1 + .../appservice/automatedBackupsEnabled.js | 63 +++++++++ .../automatedBackupsEnabled.spec.js | 123 ++++++++++++++++++ 4 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 plugins/azure/appservice/automatedBackupsEnabled.js create mode 100644 plugins/azure/appservice/automatedBackupsEnabled.spec.js diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index c7fc096367..c8c99e97c7 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -388,7 +388,13 @@ var postcalls = { reliesOnPath: 'webApps.list', properties: ['id'], url: 'https://management.azure.com/{id}/config?api-version=2019-08-01' - } + }, + getBackupConfiguration: { + reliesOnPath: 'webApps.list', + properties: ['id'], + url: 'https://management.azure.com/{id}/config/backup/list?api-version=2021-02-01', + post: true + }, }, endpoints: { listByProfile: { diff --git a/exports.js b/exports.js index 36d4be0d16..e1dbb78901 100644 --- a/exports.js +++ b/exports.js @@ -683,6 +683,7 @@ module.exports = { 'certificateExpiry' : require(__dirname + '/plugins/azure/appservice/certificateExpiry.js'), 'scmSiteAccessRestriction' : require(__dirname + '/plugins/azure/appservice/scmSiteAccessRestriction.js'), 'appServiceAccessRestriction' : require(__dirname + '/plugins/azure/appservice/appServiceAccessRestriction.js'), + 'automatedBackupsEnabled' : require(__dirname + '/plugins/azure/appservice/automatedBackupsEnabled.js'), 'rbacEnabled' : require(__dirname + '/plugins/azure/kubernetesservice/rbacEnabled.js'), 'aksLatestVersion' : require(__dirname + '/plugins/azure/kubernetesservice/aksLatestVersion.js'), diff --git a/plugins/azure/appservice/automatedBackupsEnabled.js b/plugins/azure/appservice/automatedBackupsEnabled.js new file mode 100644 index 0000000000..ad5fe789a8 --- /dev/null +++ b/plugins/azure/appservice/automatedBackupsEnabled.js @@ -0,0 +1,63 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Web Apps Backup Enabled', + category: 'App Service', + domain: 'Application Integration', + description: 'Ensures that Azure Web Apps have automated backupsenabled.', + more_info: 'Protect your Azure App Services web applications against accidental deletion and/or corruption, you can configure application backups to create restorable copies of your app content.', + recommended_action: 'Configure backup for Azure Web Apps', + link: 'https://docs.microsoft.com/en-us/azure/app-service/manage-backup', + apis: ['webApps:list', 'webApps:getBackupConfiguration'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.webApps, function(location, rcb) { + const webApps = helpers.addSource(cache, source, + ['webApps', 'list', location]); + + if (!webApps) return rcb(); + + if (webApps.err || !webApps.data) { + helpers.addResult(results, 3, 'Unable to query for Web Apps: ' + helpers.addError(webApps), location); + return rcb(); + } + + if (!webApps.data.length) { + helpers.addResult(results, 0, 'No existing Web Apps found', location); + return rcb(); + } + + async.each(webApps.data, function(webApp, scb) { + if (webApp && webApp.kind && webApp.kind === 'functionapp') { + helpers.addResult(results, 0, 'WebApps backup can not be configured for the function App', location, webApp.id); + return scb(); + } + + const configs = helpers.addSource(cache, source, + ['webApps', 'getBackupConfiguration', location, webApp.id]); + + if (configs && configs.err) { + helpers.addResult(results, 3, 'Unable to query for Web App Backup Configs: ' + helpers.addError(configs), location); + return scb(); + } + + if (!configs || !configs.data) { + helpers.addResult(results, 2, 'Backups are not configured for this WebApp', location, webApp.id); + } else { + helpers.addResult(results, 0, 'Backups are configured for this WebApp', location, webApp.id); + } + + scb(); + }, function() { + rcb(); + }); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/appservice/automatedBackupsEnabled.spec.js b/plugins/azure/appservice/automatedBackupsEnabled.spec.js new file mode 100644 index 0000000000..4be2f3a7e5 --- /dev/null +++ b/plugins/azure/appservice/automatedBackupsEnabled.spec.js @@ -0,0 +1,123 @@ +var expect = require('chai').expect; +var automatedBackupsEnabled = require('./automatedBackupsEnabled'); + +const webApps = [ + { + 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/test-app', + 'name': 'test-app', + 'type': 'Microsoft.Web/sites', + 'kind': 'app,linux', + 'location': 'East US' + }, + { + 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/test-app', + 'name': 'test-app', + 'type': 'Microsoft.Web/sites', + 'kind': 'functionapp', + 'location': 'East US' + } +]; + +const backupConfigs = { + id: '/subscriptions/dce7d0ad-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/akhtar-rg/providers/Microsoft.Web/sites/akhtar-test', + name: 'akhtar-test', + type: 'Default', + location: 'Central US', + backupName: 'akhtar-test', + enabled: true, + storageAccountUrl: 'https://akhtarrgdiag.blob.core.windows.net/appbackup?sp=rwdl&st=2022-03-16T07:51:37Z&se=2295-12-29T08:51:37Z&sv=2020-08-04&sr=c&sig=FeC0hGUrqJb6b%2Bh5qbIif84725sMjeqyNUzWa4tL3L4%3D', + backupSchedule: { + frequencyInterval: 7, + frequencyUnit: 'Day', + keepAtLeastOneBackup: true, + retentionPeriodInDays: 7, + startTime: '2022-03-16T07:51:38.699', + lastExecutionTime: '2022-03-16T07:53:38.4131659' + }, + databases: [], + mySqlDumpParams: null +}; + +const createCache = (webApps, configs) => { + let app = {}; + let config = {}; + + if (webApps) { + app['data'] = webApps; + if (webApps && webApps.length) { + config[webApps[0].id] = { + 'data': configs + }; + } + } + + return { + webApps: { + list: { + 'eastus': app + }, + getBackupConfiguration: { + 'eastus': config + } + } + }; +}; + +describe('automatedBackupsEnabled', function() { + describe('run', function() { + it('should give passing result if no web apps', function(done) { + const cache = createCache([]); + automatedBackupsEnabled.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 Web Apps found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for web apps', function(done) { + const cache = createCache(); + automatedBackupsEnabled.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 Web Apps'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if web apps backups can not be configured', function(done) { + const cache = createCache([webApps[1]], []); + automatedBackupsEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('WebApps backup can not be configured for the function App'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if no web app backup config found', function(done) { + const cache = createCache([webApps[0]], null); + automatedBackupsEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Backups are not configured for this WebApp'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if web app backup is configured', function(done) { + const cache = createCache([webApps[0]], backupConfigs); + automatedBackupsEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Backups are configured for this WebApp'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); From c753b9d39df85c063756571511c73bec7732a959 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Wed, 16 Mar 2022 06:07:44 -0700 Subject: [PATCH 036/350] Added ftpsOnlyAccessEnabled plugin and spec --- exports.js | 1 + .../azure/appservice/ftpsOnlyAccessEnabled.js | 65 ++++++++ .../appservice/ftpsOnlyAccessEnabled.spec.js | 143 ++++++++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 plugins/azure/appservice/ftpsOnlyAccessEnabled.js create mode 100644 plugins/azure/appservice/ftpsOnlyAccessEnabled.spec.js diff --git a/exports.js b/exports.js index 36d4be0d16..f46fe91546 100644 --- a/exports.js +++ b/exports.js @@ -683,6 +683,7 @@ module.exports = { 'certificateExpiry' : require(__dirname + '/plugins/azure/appservice/certificateExpiry.js'), 'scmSiteAccessRestriction' : require(__dirname + '/plugins/azure/appservice/scmSiteAccessRestriction.js'), 'appServiceAccessRestriction' : require(__dirname + '/plugins/azure/appservice/appServiceAccessRestriction.js'), + 'ftpsOnlyAccessEnabled' : require(__dirname + '/plugins/azure/appservice/ftpsOnlyAccessEnabled.js'), 'rbacEnabled' : require(__dirname + '/plugins/azure/kubernetesservice/rbacEnabled.js'), 'aksLatestVersion' : require(__dirname + '/plugins/azure/kubernetesservice/aksLatestVersion.js'), diff --git a/plugins/azure/appservice/ftpsOnlyAccessEnabled.js b/plugins/azure/appservice/ftpsOnlyAccessEnabled.js new file mode 100644 index 0000000000..6d82403a15 --- /dev/null +++ b/plugins/azure/appservice/ftpsOnlyAccessEnabled.js @@ -0,0 +1,65 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Web Apps FTPS-only access Enabled', + category: 'App Service', + domain: 'Application Integration', + description: 'Ensures that Azure Web Apps have FTPS only access enabled.', + more_info: 'FTPS-only access for your Azure App Services applications, can guarantee that the encrypted traffic between the web application servers and the FTP clients cannot be decrypted by malicious actors.', + recommended_action: 'Enable FTPS-only access for Azure Web Apps', + link: 'https://docs.microsoft.com/en-us/azure/app-service/deploy-ftp?tabs=portal#enforce-ftps', + apis: ['webApps:list', 'webApps:listConfigurations'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.webApps, function(location, rcb) { + const webApps = helpers.addSource(cache, source, + ['webApps', 'list', location]); + + if (!webApps) return rcb(); + + if (webApps.err || !webApps.data) { + helpers.addResult(results, 3, 'Unable to query for Web Apps: ' + helpers.addError(webApps), location); + return rcb(); + } + + if (!webApps.data.length) { + helpers.addResult(results, 0, 'No existing Web Apps found', location); + return rcb(); + } + + async.each(webApps.data, function(webApp, scb) { + if (webApp && webApp.kind && webApp.kind === 'functionapp') { + helpers.addResult(results, 0, 'Always On feature can not be configured for the function App', location, webApp.id); + return scb(); + } + + const configs = helpers.addSource(cache, source, + ['webApps', 'listConfigurations', location, webApp.id]); + + if (!configs || configs.err || !configs.data || !configs.data.length) { + helpers.addResult(results, 3, 'Unable to query for Web App Configs: ' + helpers.addError(configs), location); + return scb(); + } + + const ftpsOnlyAcces = configs.data[0] && configs.data[0].ftpsState; + + if (ftpsOnlyAcces && ftpsOnlyAcces.toLowerCase() === 'ftpsonly') { + helpers.addResult(results, 0, 'FTPS-only access is enabled for the Web App', location, webApp.id); + } else { + helpers.addResult(results, 2, 'FTPS-only access is disabled for the Web App', location, webApp.id); + } + + scb(); + }, function() { + rcb(); + }); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/appservice/ftpsOnlyAccessEnabled.spec.js b/plugins/azure/appservice/ftpsOnlyAccessEnabled.spec.js new file mode 100644 index 0000000000..a03f62011a --- /dev/null +++ b/plugins/azure/appservice/ftpsOnlyAccessEnabled.spec.js @@ -0,0 +1,143 @@ +var expect = require('chai').expect; +var ftpsOnlyAccessEnabled = require('./ftpsOnlyAccessEnabled'); + +const webApps = [ + { + 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/test-app', + 'name': 'test-app', + 'type': 'Microsoft.Web/sites', + 'kind': 'app,linux', + 'location': 'East US' + }, + { + 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/test-app', + 'name': 'test-app', + 'type': 'Microsoft.Web/sites', + 'kind': 'functionapp', + 'location': 'East US' + } +]; + +const configs = [ + { + 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/test-app', + 'name': 'test-app', + 'type': 'Microsoft.Web/sites', + 'location': 'East US', + 'ftpsState': 'FtpsOnly' + }, + { + 'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/test-app', + 'name': 'test-app', + 'type': 'Microsoft.Web/sites', + 'location': 'East US', + 'ftpsState': 'AllAlowed' + } +]; + +const createCache = (webApps, configs) => { + let app = {}; + let config = {}; + + if (webApps) { + app['data'] = webApps; + if (webApps && webApps.length) { + config[webApps[0].id] = { + 'data': configs + }; + } + } + + return { + webApps: { + list: { + 'eastus': app + }, + listConfigurations: { + 'eastus': config + } + } + }; +}; + +describe('ftpsOnlyAccessEnabled', function() { + describe('run', function() { + it('should give passing result if no web apps', function(done) { + const cache = createCache([]); + ftpsOnlyAccessEnabled.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 Web Apps found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for web apps', function(done) { + const cache = createCache(); + ftpsOnlyAccessEnabled.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 Web Apps'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if always on can not be configured', function(done) { + const cache = createCache([webApps[1]], []); + ftpsOnlyAccessEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Always On feature can not be configured for the function App'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + + it('should give unknown result if no web app configs', function(done) { + const cache = createCache([webApps[0]], []); + ftpsOnlyAccessEnabled.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 Web App Configs:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for web app configs', function(done) { + const cache = createCache([webApps[0]]); + ftpsOnlyAccessEnabled.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 Web App Configs:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if FTPS-only access is enabled', function(done) { + const cache = createCache([webApps[0]], [configs[0]]); + ftpsOnlyAccessEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('FTPS-only access is enabled for the Web App'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if FTPS-only access is disabled', function(done) { + const cache = createCache([webApps[0]], [configs[1]]); + ftpsOnlyAccessEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('FTPS-only access is disabled for the Web App'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); From fb77280c48d2bb521e4bb27770ae2984d6f661b9 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Thu, 17 Mar 2022 03:06:42 -0700 Subject: [PATCH 037/350] Added azureActiveDirectoryEnabled plugin and spec --- exports.js | 1 + .../appservice/azureActiveDirectoryEnabled.js | 48 +++++++++ .../azureActiveDirectoryEnabled.spec.js | 97 +++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 plugins/azure/appservice/azureActiveDirectoryEnabled.js create mode 100644 plugins/azure/appservice/azureActiveDirectoryEnabled.spec.js diff --git a/exports.js b/exports.js index b554a422dd..1fb8a2b297 100644 --- a/exports.js +++ b/exports.js @@ -701,6 +701,7 @@ module.exports = { 'certificateExpiry' : require(__dirname + '/plugins/azure/appservice/certificateExpiry.js'), 'scmSiteAccessRestriction' : require(__dirname + '/plugins/azure/appservice/scmSiteAccessRestriction.js'), 'appServiceAccessRestriction' : require(__dirname + '/plugins/azure/appservice/appServiceAccessRestriction.js'), + 'azureActiveDirectoryEnabled' : require(__dirname + '/plugins/azure/appservice/azureActiveDirectoryEnabled.js'), 'rbacEnabled' : require(__dirname + '/plugins/azure/kubernetesservice/rbacEnabled.js'), 'aksLatestVersion' : require(__dirname + '/plugins/azure/kubernetesservice/aksLatestVersion.js'), diff --git a/plugins/azure/appservice/azureActiveDirectoryEnabled.js b/plugins/azure/appservice/azureActiveDirectoryEnabled.js new file mode 100644 index 0000000000..6e379e2277 --- /dev/null +++ b/plugins/azure/appservice/azureActiveDirectoryEnabled.js @@ -0,0 +1,48 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Web Apps Azure Active Directory Enabled', + category: 'App Service', + domain: 'Application Integration', + description: 'Ensures that Azure Web Apps have Registration with Azure Active Directory is Enabled.', + more_info: 'Registration with Azure Active Directory (AAD) enables App Service web applications to connect to other Azure cloud services securely without the need of access credentials such as user names and passwords.', + recommended_action: 'Enable Registration with Azurre Active Directory for Azure Web Apps', + link: 'https://docs.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=portal%2Chttp#add-a-system-assigned-identity', + apis: ['webApps:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.webApps, function(location, rcb) { + const webApps = helpers.addSource(cache, source, + ['webApps', 'list', location]); + + if (!webApps) return rcb(); + + if (webApps.err || !webApps.data) { + helpers.addResult(results, 3, 'Unable to query for Web Apps: ' + helpers.addError(webApps), location); + return rcb(); + } + + if (!webApps.data.length) { + helpers.addResult(results, 0, 'No existing Web Apps found', location); + return rcb(); + } + + for (let app of webApps.data) { + if (app.identity && app.identity.principalId) { + helpers.addResult(results, 0, 'Registration with Azure Active Directory is enabled for the Web App', location, app.id); + } else { + helpers.addResult(results, 2, 'Registration with Azure Active Directory is disabled for the Web App', location, app.id); + } + } + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/appservice/azureActiveDirectoryEnabled.spec.js b/plugins/azure/appservice/azureActiveDirectoryEnabled.spec.js new file mode 100644 index 0000000000..9b7421962e --- /dev/null +++ b/plugins/azure/appservice/azureActiveDirectoryEnabled.spec.js @@ -0,0 +1,97 @@ +var expect = require('chai').expect; +var azureActiveDirectoryEnabled = require('./azureActiveDirectoryEnabled'); + +const webApps = [ + { + id: '/subscriptions/abcdefg-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/test/providers/Microsoft.Web/sites/test', + name: 'test', + type: 'Microsoft.Web/sites', + kind: 'app,linux', + location: 'Central US', + state: 'Running', + hostNames: [ 'test.azurewebsites.net' ], + webSpace: 'test-CentralUSwebspace-Linux', + selfLink: 'https://waws-prod-dm1-213.api.azurewebsites.windows.net:454/subscriptions/abcdefg-ebf6-437f-a3b0-28fc0d22117e/webspaces/test-CentralUSwebspace-Linux/sites/test', + repositorySiteName: 'test', + owner: null, + usageState: 'Normal', + enabled: true, + adminEnabled: true, + enabledHostNames: [ + 'test.azurewebsites.net', + 'test.scm.azurewebsites.net' + ] + }, + { + id: '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Web/sites/test-app', + name: 'test-app', + type: 'Microsoft.Web/sites', + kind: 'functionapp', + location: 'East US', + identity: { + type: 'SystemAssigned', + tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', + principalId: '66cddca0-05fa-4ef7-a219-b145f7d9dc6d' + }, + } +]; + +const createCache = (apps) => { + return { + webApps: { + list: { + 'eastus': { + data: apps + } + } + } + }; +}; + +describe('azureActiveDirectoryEnabled', function() { + describe('run', function() { + it('should give passing result if no web apps', function(done) { + const cache = createCache([]); + azureActiveDirectoryEnabled.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 Web Apps found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for web apps', function(done) { + const cache = createCache(null); + azureActiveDirectoryEnabled.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 Web Apps'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if Registration with Azure Active Directory is enabled', function(done) { + const cache = createCache([webApps[1]]); + azureActiveDirectoryEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Registration with Azure Active Directory is enabled for the Web App'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if Registration with Azure Active Directory is disabled', function(done) { + const cache = createCache([webApps[0]]); + azureActiveDirectoryEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Registration with Azure Active Directory is disabled for the Web App'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); From 8c0c2f8a0cc7c750835ce05c048b65556873c20f Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Fri, 18 Mar 2022 23:21:07 +0500 Subject: [PATCH 038/350] updated config-example file for google remediations --- config_example.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/config_example.js b/config_example.js index f4380f0b4f..e11d0e7bfd 100644 --- a/config_example.js +++ b/config_example.js @@ -37,6 +37,14 @@ module.exports = { // directory_id: process.env.AZURE_DIRECTORY_ID || '', // subscription_id: process.env.AZURE_SUBSCRIPTION_ID || '' }, + google_remediate: { + // OPTION 1: If using a credential JSON file, enter the path below + // credential_file: process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/file.json', + // OPTION 2: If using hard-coded credentials, enter them below + // project: process.env.GOOGLE_PROJECT_ID || 'my-project', + // client_email: process.env.GOOGLE_CLIENT_EMAIL || 'cloudsploit@your-project-name.iam.gserviceaccount.com', + // private_key: process.env.GOOGLE_PRIVATE_KEY || '-----BEGIN PRIVATE KEY-----\nYOUR-PRIVATE-KEY-GOES-HERE\n-----END PRIVATE KEY-----\n' + }, google: { // OPTION 1: If using a credential JSON file, enter the path below // credential_file: process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/file.json', From c670e61350fc35332bb57a0f0ddceea17e419828 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sat, 19 Mar 2022 14:53:21 +0500 Subject: [PATCH 039/350] GCP Plugin for KMS Public Access --- collectors/google/collector.js | 23 +- exports.js | 1 + .../cryptographickeys/kmsPublicAccess.js | 92 +++++++ .../cryptographickeys/kmsPublicAccess.spec.js | 231 ++++++++++++++++++ 4 files changed, 344 insertions(+), 3 deletions(-) create mode 100644 plugins/google/cryptographickeys/kmsPublicAccess.js create mode 100644 plugins/google/cryptographickeys/kmsPublicAccess.spec.js diff --git a/collectors/google/collector.js b/collectors/google/collector.js index 227bbb29d4..9c70450b18 100644 --- a/collectors/google/collector.js +++ b/collectors/google/collector.js @@ -316,7 +316,7 @@ var postcalls = { properties: ['name'], pagination: true, paginationKey: 'pageSize' - } + } }, buckets: { getIamPolicy: { @@ -400,6 +400,17 @@ var postcalls = { } } }; +var tertiarycalls = { + cryptoKeys: { + getIamPolicy: { + url: 'https://cloudkms.googleapis.com/v1/{name}:getIamPolicy', + location: 'region', + reliesOnService: ['cryptoKeys'], + reliesOnCall: ['list'], + properties: ['name'], + } + }, +}; var collect = function(GoogleConfig, settings, callback) { var collection = {}; @@ -423,8 +434,14 @@ var collect = function(GoogleConfig, settings, callback) { postcallCb(); }); }, function() { - JSON.stringify(collection, null, 2); - callback(null, collection); + async.eachOfLimit(tertiarycalls, 10, function(tertiaryCallObj, service, tertiaryCallCb) { + helpers.processCall(GoogleConfig, collection, settings, regions, tertiaryCallObj, service, client, function() { + tertiaryCallCb(); + }); + }, function() { + JSON.stringify(collection, null, 2); + callback(null, collection); + }); }); }); }); diff --git a/exports.js b/exports.js index 36d4be0d16..cca15b8dd1 100644 --- a/exports.js +++ b/exports.js @@ -880,6 +880,7 @@ module.exports = { 'keyRotation' : require(__dirname + '/plugins/google/cryptographickeys/keyRotation.js'), 'keyProtectionLevel' : require(__dirname + '/plugins/google/cryptographickeys/keyProtectionLevel.js'), + 'kmsPublicAccess' : require(__dirname + '/plugins/google/cryptographickeys/kmsPublicAccess.js'), 'dbRestorable' : require(__dirname + '/plugins/google/sql/dbRestorable.js'), 'dbAutomatedBackups' : require(__dirname + '/plugins/google/sql/dbAutomatedBackups.js'), diff --git a/plugins/google/cryptographickeys/kmsPublicAccess.js b/plugins/google/cryptographickeys/kmsPublicAccess.js new file mode 100644 index 0000000000..02f9a5d28c --- /dev/null +++ b/plugins/google/cryptographickeys/kmsPublicAccess.js @@ -0,0 +1,92 @@ +var async = require('async'); +var helpers = require('../../../helpers/google'); + +module.exports = { + title: 'KMS Public Access', + category: 'Cryptographic Keys', + domain: 'Identity and Access Management', + description: 'Ensures cryptographic keys are not publicly accessible.', + more_info: 'To prevent exposing sensitive data and information leaks, make sure that your cryptokeys do not allow access from anonymous and public users.', + link: 'https://cloud.google.com/kms/docs/reference/permissions-and-roles', + recommended_action: 'Ensure that your cryptographic keys are not accessible by allUsers or allAuthenticatedUsers.', + apis: ['keyRings:list', 'cryptoKeys:list', 'cryptoKeys:getIamPolicy'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(); + + async.each(regions.keyRings, function(region, rcb) { + let keyRings = helpers.addSource( + cache, source, ['keyRings', 'list', region]); + + if (!keyRings) return rcb(); + + if (keyRings.err || !keyRings.data) { + helpers.addResult(results, 3, 'Unable to query key rings', region, null, null, keyRings.err); + return rcb(); + } + + if (!keyRings.data.length) { + helpers.addResult(results, 0, 'No key rings found', region); + return rcb(); + } + + let cryptoKeys = helpers.addSource( + cache, source, ['cryptoKeys', 'list', region]); + + if (!cryptoKeys) return rcb(); + + if (cryptoKeys.err || !cryptoKeys.data) { + helpers.addResult(results, 3, 'Unable to query cryptographic keys', region, null, null, cryptoKeys.err); + return rcb(); + } + + if (!cryptoKeys.data.length) { + helpers.addResult(results, 0, 'No cryptographic keys found', region); + return rcb(); + } + + let cryptoKeysIamPolicies = helpers.addSource( + cache, source, ['cryptoKeys', 'getIamPolicy', region]); + + if (!cryptoKeysIamPolicies || cryptoKeysIamPolicies.err || !cryptoKeysIamPolicies.data) { + helpers.addResult(results, 3, 'Unable to query IAM Policies for Cryptographic Keys: ' + helpers.addError(cryptoKeysIamPolicies), region); + return callback(null, results, source); + } + + if (!cryptoKeysIamPolicies.data.length) { + helpers.addResult(results, 0, 'No IAM Policies found', region); + return callback(null, results, source); + } + + cryptoKeysIamPolicies = cryptoKeysIamPolicies.data; + + cryptoKeys.data.forEach(cryptoKey => { + let keyIamPolicy = cryptoKeysIamPolicies.find(iamPolicy => iamPolicy.parent && iamPolicy.parent.name === cryptoKey.name); + + if (!keyIamPolicy || !keyIamPolicy.bindings || !keyIamPolicy.bindings.length) { + helpers.addResult(results, 0, + 'No IAM Policies found for cryptographic key', region, cryptoKey.name); + } else { + var allowedAllUsers = false; + keyIamPolicy.bindings.forEach(roleBinding => { + if (roleBinding.role && roleBinding.members && roleBinding.members.length && (roleBinding.members.includes('allUsers') || roleBinding.members.includes('allAuthenticatedUsers'))) { + allowedAllUsers = true; + } + }); + if (!allowedAllUsers) { + helpers.addResult(results, 0, 'Cryptographic Key is not publicly accessible', region, cryptoKey.name); + } else { + helpers.addResult(results, 2, 'Cryptographic Key is publicly accessible', region, cryptoKey.name); + } + } + }); + + rcb(); + }, function() { + // Global checking goes here + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/google/cryptographickeys/kmsPublicAccess.spec.js b/plugins/google/cryptographickeys/kmsPublicAccess.spec.js new file mode 100644 index 0000000000..95d11cc5f2 --- /dev/null +++ b/plugins/google/cryptographickeys/kmsPublicAccess.spec.js @@ -0,0 +1,231 @@ +var expect = require('chai').expect; +var plugin = require('./kmsPublicAccess'); + +const cryptoKeys = [ + { + "name": "projects/test-project/locations/us-central1/keyRings/test-kr-1/cryptoKeys/test-cmek", + "rotationPeriod": '7776000s', + "purpose": "ENCRYPT_DECRYPT", + "createTime": "2021-06-15T13:22:44.808595111Z" + }, + { + "name": "projects/test-project/locations/us-central1/keyRings/test-kr-1/cryptoKeys/test-cmek-1", + "primary": { + "name": "projects/test-project/locations/us-central1/keyRings/test-kr-1/cryptoKeys/test-cmek-1/cryptoKeyVersions/1", + "createTime": "2021-06-15T13:27:10.444152476Z", + "protectionLevel": "SOFTWARE", + "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION", + "generateTime": "2021-06-15T13:27:10.444152476Z" + }, + }, + { + "name": "projects/test-project/locations/us-central1/keyRings/test-kr-1/cryptoKeys/test-csek-1", + "purpose": "ENCRYPT_DECRYPT", + "createTime": "2021-06-15T14:05:00.127824829Z" + } +]; + +const keyPolicies = [ + { + "version": 1, + "etag": "BwXZ3RM6WFs=", + "bindings": [ + { + "role": "roles/cloudkms.cryptoKeyEncrypterDecrypter", + "members": [ + "allUsers", + ] + }, + ], + "parent": { + "id": "1231", + "creationTimestamp": "2022-03-09T16:05:01.878-08:00", + "name": "projects/test-project/locations/us-central1/keyRings/test-kr-1/cryptoKeys/test-cmek" + } + }, + { + "version": 1, + "etag": "BwXZ3RM6WFs=", + "bindings": [ + { + "role": "roles/cloudkms.cryptoKeyEncrypterDecrypter", + "members": [ + "myserviceaccount@gmail.com", + ] + }, + ], + "parent": { + "id": 1232, + "creationTimestamp": "2022-03-09T16:05:01.878-08:00", + "name": "projects/test-project/locations/us-central1/keyRings/test-kr-1/cryptoKeys/test-cmek-1", + } + } +] + +const createCache = (data, err, policyData, policyErr) => { + return { + keyRings: { + list: { + 'us-central1': { + data: [ + { + 'name': 'projects/test-project/locations/us-central1/keyRings/test-kr-1', + 'createTime': '2021-06-14T13:58:29.562215224Z' + } + ] + }, + } + }, + cryptoKeys: { + list: { + 'us-central1': { + err: err, + data: data + } + }, + getIamPolicy: { + 'us-central1': { + err: policyErr, + data: policyData + } + } + } + } +}; + +describe('kmsPublicAccess', function () { + describe('run', function () { + it('should give unknown result if unable to query cryptographic keys', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('Unable to query cryptographic keys'); + expect(results[0].region).to.equal('us-central1'); + done() + }; + + const cache = createCache( + null, + ['error'], + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if no cryptographic keys found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No cryptographic keys found'); + expect(results[0].region).to.equal('us-central1'); + done() + }; + + const cache = createCache( + [], + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query IAM Policies for cryptographic keys', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('Unable to query IAM Policies for Cryptographic Keys'); + expect(results[0].region).to.equal('us-central1'); + done() + }; + + const cache = createCache( + cryptoKeys, + null, + [], + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if no IAM Policies found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No IAM Policies found'); + expect(results[0].region).to.equal('us-central1'); + done() + }; + + const cache = createCache( + cryptoKeys, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should fail if crypto key is publicly accessible', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Cryptographic Key is publicly accessible'); + expect(results[0].region).to.equal('us-central1'); + done() + }; + + const cache = createCache( + [cryptoKeys[0]], + null, + [keyPolicies[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should pass if no IAM policies are found for cryptographic key', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No IAM Policies found for cryptographic key'); + expect(results[0].region).to.equal('us-central1'); + done() + }; + + const cache = createCache( + [cryptoKeys[2]], + null, + [keyPolicies], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should pass if cryptographic key is not publicly accessible', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Cryptographic Key is not publicly accessible'); + expect(results[0].region).to.equal('us-central1'); + done() + }; + + const cache = createCache( + [cryptoKeys[1]], + null, + [keyPolicies[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }) +}); \ No newline at end of file From f10d4c0bd22524c7072192ae5d4698b0a4002c2c Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sun, 20 Mar 2022 04:19:15 +0500 Subject: [PATCH 040/350] GCP Disable Service Account Creation Plugin --- exports.js | 4 +- .../disableServiceAccountCreation.js | 37 ++++++ .../disableServiceAccountCreation.spec.js | 113 ++++++++++++++++++ 3 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 plugins/google/cloudresourcemanager/disableServiceAccountCreation.js create mode 100644 plugins/google/cloudresourcemanager/disableServiceAccountCreation.spec.js diff --git a/exports.js b/exports.js index 36d4be0d16..e28f05c859 100644 --- a/exports.js +++ b/exports.js @@ -1002,7 +1002,9 @@ module.exports = { 'disableVMIPForwarding' : require(__dirname + '/plugins/google/cloudresourcemanager/disableVMIPForwarding.js'), 'trustedImageProjects' : require(__dirname + '/plugins/google/cloudresourcemanager/trustedImageProjects.js'), 'skipDefaultNetworkCreation' : require(__dirname + '/plugins/google/cloudresourcemanager/skipDefaultNetworkCreation.js'), - 'locationBasedRestriction' : require(__dirname + '/plugins/google/cloudresourcemanager/locationBasedRestriction.js') + 'locationBasedRestriction' : require(__dirname + '/plugins/google/cloudresourcemanager/locationBasedRestriction.js'), + 'disableServiceAccountCreation' : require(__dirname + '/plugins/google/cloudresourcemanager/disableServiceAccountCreation.js'), + }, alibaba: { 'passwordMinLength' : require(__dirname + '/plugins/alibaba/ram/passwordMinLength.js'), diff --git a/plugins/google/cloudresourcemanager/disableServiceAccountCreation.js b/plugins/google/cloudresourcemanager/disableServiceAccountCreation.js new file mode 100644 index 0000000000..47ca9bc6c8 --- /dev/null +++ b/plugins/google/cloudresourcemanager/disableServiceAccountCreation.js @@ -0,0 +1,37 @@ +var helpers = require('../../../helpers/google'); + +module.exports = { + title: 'Disable Service Account Creation', + category: 'Resource Manager', + domain: 'Management and Governance', + description: 'Determine if "Disable Service Account Creation" policy is enforced at the GCP organization level.', + more_info: 'Enforcing the "Disable Service Account Creation" policy allows you to centrally manage your service accounts and reduces the chances of compromised service accounts being used to access your GCP resources.', + link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', + recommended_action: 'Ensure that "Disable Service Account Creation" constraint is enforced at the organization level.', + apis: ['organizations:list', 'organizations:listOrgPolicies'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + + let listOrgPolicies = helpers.addSource(cache, source, + ['organizations', 'listOrgPolicies', 'global']); + + if (!listOrgPolicies) return callback(null, results, source); + + if (listOrgPolicies.err || !listOrgPolicies.data) { + helpers.addResult(results, 3, 'Unable to query organization policies', 'global', null, null, listOrgPolicies.err); + return callback(null, results, source); + } + + if (!listOrgPolicies.data.length) { + helpers.addResult(results, 0, 'No organization policies found', 'global'); + return callback(null, results, source); + } + let orgPolicies = listOrgPolicies.data[0]; + + helpers.checkOrgPolicy(orgPolicies, 'iam.disableServiceAccountCreation', 'booleanPolicy', true, false, 'Disable Service Account Creation', results); + + return callback(null, results, source); + } +}; \ No newline at end of file diff --git a/plugins/google/cloudresourcemanager/disableServiceAccountCreation.spec.js b/plugins/google/cloudresourcemanager/disableServiceAccountCreation.spec.js new file mode 100644 index 0000000000..554e627ff0 --- /dev/null +++ b/plugins/google/cloudresourcemanager/disableServiceAccountCreation.spec.js @@ -0,0 +1,113 @@ +var expect = require('chai').expect; +var plugin = require('./disableServiceAccountCreation'); + +const createCache = (err, data) => { + return { + organizations: { + listOrgPolicies: { + 'global': { + err: err, + data: data + } + }, + }, + } +}; + +describe('disableServiceAccountCreation', function () { + describe('run', function () { + + it('should give unknow if an organization policies error occurs', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('Unable to query organization policies'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + 'error', + [], + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if no organization policies are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No organization policies found'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [], + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if service account creation is disabled', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('is enforced'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [ + { + "policies": [ + { + "constraint": "constraints/iam.disableServiceAccountCreation", + "updateTime": "2021-10-19T20:42:37.813762Z", + "booleanPolicy": { + "enforced": true + } + }, + ] + } + + ] + ); + + plugin.run(cache, {}, callback); + }); + + it('should give failing result if service account creation is enabled', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('is not enforced'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [ + { + "policies": [ + { + "constraint": "constraints/iam.disableServiceAccountCreation", + "updateTime": "2021-10-19T20:42:37.813762Z", + "booleanPolicy": {} + }, + ] + } + + ] + ); + + plugin.run(cache, {}, callback); + }) + + }) +}); \ No newline at end of file From 4f0d8603c30e9046f62f04094b11d51d480e7ac5 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 22 Mar 2022 20:48:37 +0500 Subject: [PATCH 041/350] Added Enhanced Metadata Collection Enabled Plugin --- collectors/aws/collector.js | 6 + exports.js | 3 + helpers/aws/regions.js | 3 +- helpers/aws/regions_china.js | 3 +- helpers/aws/regions_gov.js | 3 +- .../imagebuilder/enhancedMetadataEnabled.js | 56 ++++++++++ .../enhancedMetadataEnabled.spec.js | 105 ++++++++++++++++++ 7 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 plugins/aws/imagebuilder/enhancedMetadataEnabled.js create mode 100644 plugins/aws/imagebuilder/enhancedMetadataEnabled.spec.js diff --git a/collectors/aws/collector.js b/collectors/aws/collector.js index 2b0c18c647..71c7d3c5cc 100644 --- a/collectors/aws/collector.js +++ b/collectors/aws/collector.js @@ -688,6 +688,12 @@ var calls = { override: true } }, + Imagebuilder: { + listImagePipelines: { + property: 'imagePipelineList', + paginate: 'nextToken' + } + }, IoTSiteWise: { describeDefaultEncryptionConfiguration: { } diff --git a/exports.js b/exports.js index 92cedb06ae..4f3d90956c 100644 --- a/exports.js +++ b/exports.js @@ -103,6 +103,9 @@ module.exports = { 'unassociatedElasticIp' : require(__dirname + '/plugins/aws/ec2/unassociatedElasticIp.js'), 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), + + 'enhancedMetadataEnabled' : require(__dirname + '/plugins/aws/imagebuilder/enhancedMetadataEnabled.js'), + 'instanceLimit' : require(__dirname + '/plugins/aws/ec2/instanceLimit.js'), 'instanceVcpusLimit' : require(__dirname + '/plugins/aws/ec2/instanceVcpusLimit.js'), 'instanceMaxCount' : require(__dirname + '/plugins/aws/ec2/instanceMaxCount.js'), diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index c0e55edf35..c49372f556 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -189,5 +189,6 @@ module.exports = { appmesh: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1'], - frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'] + frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'], + imagebuilder: regions }; diff --git a/helpers/aws/regions_china.js b/helpers/aws/regions_china.js index 2a2b9af6de..d42be6339b 100644 --- a/helpers/aws/regions_china.js +++ b/helpers/aws/regions_china.js @@ -116,5 +116,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + imagebuilder: regions }; diff --git a/helpers/aws/regions_gov.js b/helpers/aws/regions_gov.js index 1eaf28407b..81c2f2ebd9 100644 --- a/helpers/aws/regions_gov.js +++ b/helpers/aws/regions_gov.js @@ -115,5 +115,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + imagebuilder: regions }; diff --git a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js new file mode 100644 index 0000000000..c4355d9423 --- /dev/null +++ b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js @@ -0,0 +1,56 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'Enhanced Metadata Collection Enabled', + category: 'Imagebuilder', + domain: 'compute', + description: 'Ensure that enhanced metadata collection is enabled for image pipeline.', + more_info: 'Image Builder is a fully managed AWS service that makes it easier to automate the creation, management, and deployment of customized, secure, and up-to-date server images that are pre-installed and pre-configured with software and settings to meet specific IT standards.', + link: 'https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html', + recommended_action: 'Enable enhanced metadata collection for image pipeline.', + apis: ['Imagebuilder:listImagePipelines'], + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + async.each(regions.imagebuilder, function(region, rcb){ + var listImagePipelines = helpers.addSource(cache, source, + ['imagebuilder', 'listImagePipelines', region]); + + if (!listImagePipelines) return rcb(); + + if (listImagePipelines.err || !listImagePipelines.data) { + helpers.addResult(results, 3, + 'Unable to list image pipeline: ' + helpers.addError(listImagePipelines), region); + return rcb(); + } + + if (!listImagePipelines.data.length) { + helpers.addResult(results, 0, + 'No image pipeline list found', region); + return rcb(); + } + + for (let image of listImagePipelines.data) { + if (!image.arn) continue; + + let resource = image.arn; + + if (image.enhancedImageMetadataEnabled == true) { + helpers.addResult(results, 0, + 'Image pipeline has enhanced metadata collection enabled', + region, resource); + } else { + helpers.addResult(results, 2, + 'Image pipeline does not have enhanced metadata collection enabled', + region, resource); + } + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; diff --git a/plugins/aws/imagebuilder/enhancedMetadataEnabled.spec.js b/plugins/aws/imagebuilder/enhancedMetadataEnabled.spec.js new file mode 100644 index 0000000000..c0c35b276e --- /dev/null +++ b/plugins/aws/imagebuilder/enhancedMetadataEnabled.spec.js @@ -0,0 +1,105 @@ +var expect = require('chai').expect;; +var enhancedMetadataEnabled = require('./enhancedMetadataEnabled'); + +const listImagePipelines = [ + { + "arn": "arn:aws:imagebuilder:us-east-1:000011112222:image-pipeline/akhtar-img-pipeline", + "name": "akhtar-img-pipeline", + "platform": "Linux", + "enhancedImageMetadataEnabled": true, + "imageRecipeArn": "arn:aws:imagebuilder:us-east-1:000011112222:image-recipe/akhtar-img-rc/1.0.0", + "infrastructureConfigurationArn": "arn:aws:imagebuilder:us-east-1:000011112222:infrastructure-configuration/akhtar-img-pipeline-914d5fdf-45db-4231-ae0e-991c39f9e594", + "distributionConfigurationArn": "arn:aws:imagebuilder:us-east-1:000011112222:distribution-configuration/akhtar-img-pipeline-914d5fdf-45db-4231-ae0e-991c39f9e594", + "imageTestsConfiguration": { + "imageTestsEnabled": true, + "timeoutMinutes": 720 + }, + "status": "ENABLED", + "dateCreated": "2022-03-08T11:20:43.395Z", + "dateUpdated": "2022-03-08T11:20:43.395Z", + "tags": {} + }, + { + "arn": "arn:aws:imagebuilder:us-east-1:000011112222:image-pipeline/akhtar-img-pipeline", + "name": "akhtar-img-pipeline", + "platform": "Linux", + "enhancedImageMetadataEnabled": false, + "imageRecipeArn": "arn:aws:imagebuilder:us-east-1:000011112222:image-recipe/akhtar-img-rc/1.0.0", + "infrastructureConfigurationArn": "arn:aws:imagebuilder:us-east-1:000011112222:infrastructure-configuration/akhtar-img-pipeline-914d5fdf-45db-4231-ae0e-991c39f9e594", + "distributionConfigurationArn": "arn:aws:imagebuilder:us-east-1:000011112222:distribution-configuration/akhtar-img-pipeline-914d5fdf-45db-4231-ae0e-991c39f9e594", + "imageTestsConfiguration": { + "imageTestsEnabled": true, + "timeoutMinutes": 720 + }, + "status": "ENABLED", + "dateCreated": "2022-03-08T11:20:43.395Z", + "dateUpdated": "2022-03-08T11:20:43.395Z", + "tags": {} + } +]; + +const createCache = (images) => { + return { + imagebuilder: { + listImagePipelines: { + "us-east-1": { + data: images + } + } + } + } +} + +const createNullCache = () => { + return { + imagebuilder: { + listImagePipelines: { + "us-east-1": { + data: null + } + } + } + } +} + +describe('enhancedMetadataEnabled', () => { + describe('run', () => { + it('should PASS if Image pipeline has enhanced metadata collection enabled', () => { + const cache = createCache([listImagePipelines[0]]); + enhancedMetadataEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Image pipeline has enhanced metadata collection enabled') + }) + }); + it('should FAIL if Image pipeline does not have enhanced metadata collection enabled', () => { + const cache = createCache([listImagePipelines[1]]); + enhancedMetadataEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Image pipeline does not have enhanced metadata collection enabled') + }) + }); + it('should PASS if No image pipeline list found', () => { + const cache = createCache([]); + enhancedMetadataEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No image pipeline list found') + }) + }); + it('should UNKNOWN if Unable to list image pipeline', () => { + const cache = createNullCache(); + enhancedMetadataEnabled.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 list image pipeline') + }) + }); + it('should not return anything if list image pipeline response is not found', () => { + enhancedMetadataEnabled.run({}, {}, (err, results) => { + expect(results.length).to.equal(0); + }) + }); + }); +}); \ No newline at end of file From 721a1be0d9aba2de8f1df97b7a553b7f2f11566b Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 24 Mar 2022 15:10:12 +0500 Subject: [PATCH 042/350] Update plugins/aws/imagebuilder/enhancedMetadataEnabled.js --- plugins/aws/imagebuilder/enhancedMetadataEnabled.js | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js index c4355d9423..dcb8d9b16a 100644 --- a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js +++ b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js @@ -5,6 +5,7 @@ module.exports = { title: 'Enhanced Metadata Collection Enabled', category: 'Imagebuilder', domain: 'compute', + severity: 'LOW' description: 'Ensure that enhanced metadata collection is enabled for image pipeline.', more_info: 'Image Builder is a fully managed AWS service that makes it easier to automate the creation, management, and deployment of customized, secure, and up-to-date server images that are pre-installed and pre-configured with software and settings to meet specific IT standards.', link: 'https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html', From f1f04407584884405232d3a1a00adae95dd34886 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 24 Mar 2022 15:10:21 +0500 Subject: [PATCH 043/350] Update plugins/aws/imagebuilder/enhancedMetadataEnabled.js --- plugins/aws/imagebuilder/enhancedMetadataEnabled.js | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js index dcb8d9b16a..0d36cb7e26 100644 --- a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js +++ b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js @@ -6,6 +6,7 @@ module.exports = { category: 'Imagebuilder', domain: 'compute', severity: 'LOW' + severity: 'LOW' description: 'Ensure that enhanced metadata collection is enabled for image pipeline.', more_info: 'Image Builder is a fully managed AWS service that makes it easier to automate the creation, management, and deployment of customized, secure, and up-to-date server images that are pre-installed and pre-configured with software and settings to meet specific IT standards.', link: 'https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html', From d2ce7d181377c7c6e8b5fbd4b1124d46c81bf927 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 24 Mar 2022 15:27:17 +0500 Subject: [PATCH 044/350] Update plugins/aws/imagebuilder/enhancedMetadataEnabled.js --- plugins/aws/imagebuilder/enhancedMetadataEnabled.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js index 0d36cb7e26..dcb8d9b16a 100644 --- a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js +++ b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js @@ -6,7 +6,6 @@ module.exports = { category: 'Imagebuilder', domain: 'compute', severity: 'LOW' - severity: 'LOW' description: 'Ensure that enhanced metadata collection is enabled for image pipeline.', more_info: 'Image Builder is a fully managed AWS service that makes it easier to automate the creation, management, and deployment of customized, secure, and up-to-date server images that are pre-installed and pre-configured with software and settings to meet specific IT standards.', link: 'https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html', From 56cca09cfce52d63da80976479646f67ed34ad6a Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 24 Mar 2022 15:27:38 +0500 Subject: [PATCH 045/350] Update plugins/aws/imagebuilder/enhancedMetadataEnabled.js --- plugins/aws/imagebuilder/enhancedMetadataEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js index dcb8d9b16a..8f1b03728b 100644 --- a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js +++ b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js @@ -5,7 +5,7 @@ module.exports = { title: 'Enhanced Metadata Collection Enabled', category: 'Imagebuilder', domain: 'compute', - severity: 'LOW' + severity: 'LOW', description: 'Ensure that enhanced metadata collection is enabled for image pipeline.', more_info: 'Image Builder is a fully managed AWS service that makes it easier to automate the creation, management, and deployment of customized, secure, and up-to-date server images that are pre-installed and pre-configured with software and settings to meet specific IT standards.', link: 'https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html', From 866efae3a7da9159bfca8bb9fdaf794ad9a0efbb Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:38:50 +0500 Subject: [PATCH 046/350] Added Image Builder Components Encrypted Plugin --- collectors/aws/collector.js | 14 ++ exports.js | 2 + helpers/aws/regions.js | 3 +- helpers/aws/regions_china.js | 3 +- helpers/aws/regions_gov.js | 3 +- .../imgBuilderComponentsEncrypted.js | 133 +++++++++++ .../imgBuilderComponentsEncrypted.spec.js | 226 ++++++++++++++++++ 7 files changed, 381 insertions(+), 3 deletions(-) create mode 100644 plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js create mode 100644 plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.spec.js diff --git a/collectors/aws/collector.js b/collectors/aws/collector.js index 044d29ff6e..ffa2e0e51c 100644 --- a/collectors/aws/collector.js +++ b/collectors/aws/collector.js @@ -654,6 +654,12 @@ var calls = { paginate: 'NextToken' } }, + Imagebuilder: { + listComponents: { + property: 'componentVersionList', + paginate: 'nextToken' + } + }, IAM: { listServerCertificates: { property: 'ServerCertificateMetadataList', @@ -1572,6 +1578,14 @@ var postcalls = [ filterValue: 'VaultName' } }, + Imagebuilder: { + getComponent: { + reliesOnService: 'imagebuilder', + reliesOnCall: 'listComponents', + filterKey: 'componentBuildVersionArn', + filterValue: 'arn' + }, + }, IAM: { getGroup: { reliesOnService: 'iam', diff --git a/exports.js b/exports.js index c6fbcc9507..7efe9e1c1c 100644 --- a/exports.js +++ b/exports.js @@ -252,6 +252,8 @@ module.exports = { 'bookmarkEncryptionEnabled' : require(__dirname + '/plugins/aws/glue/bookmarkEncryptionEnabled.js'), 'dataCatalogEncryptionEnabled' : require(__dirname + '/plugins/aws/glue/dataCatalogEncryptionEnabled.js'), + 'imgBuilderComponentsEncrypted' : require(__dirname + '/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js'), + 'accessKeysExtra' : require(__dirname + '/plugins/aws/iam/accessKeysExtra.js'), 'accessKeysLastUsed' : require(__dirname + '/plugins/aws/iam/accessKeysLastUsed.js'), 'accessKeysRotated' : require(__dirname + '/plugins/aws/iam/accessKeysRotated.js'), diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index c0e55edf35..c49372f556 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -189,5 +189,6 @@ module.exports = { appmesh: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1'], - frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'] + frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'], + imagebuilder: regions }; diff --git a/helpers/aws/regions_china.js b/helpers/aws/regions_china.js index 2a2b9af6de..d42be6339b 100644 --- a/helpers/aws/regions_china.js +++ b/helpers/aws/regions_china.js @@ -116,5 +116,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + imagebuilder: regions }; diff --git a/helpers/aws/regions_gov.js b/helpers/aws/regions_gov.js index 1eaf28407b..81c2f2ebd9 100644 --- a/helpers/aws/regions_gov.js +++ b/helpers/aws/regions_gov.js @@ -115,5 +115,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + imagebuilder: regions }; diff --git a/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js new file mode 100644 index 0000000000..b7ddaeded6 --- /dev/null +++ b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js @@ -0,0 +1,133 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'Image Builder Components Encrypted', + category: 'Imagebuilder', + domain: 'compute', + severity: 'LOW', + description: 'Ensure that Imagebuilder components are encrypted.', + more_info: 'Image Builder is a fully managed AWS service that makes it easier to automate the creation, management, and deployment of customized, secure, and up-to-date server images that are pre-installed and pre-configured with software and settings to meet specific IT standards.', + link: 'https://docs.aws.amazon.com/imagebuilder/latest/userguide/data-protection.html', + recommended_action: 'Ensure that components are encrypted using AWS keys or customer managed keys in Imagebuilder service', + apis: ['Imagebuilder:listComponents', 'Imagebuilder:getComponent', 'KMS:listAliases', 'KMS:listKeys', + 'KMS:describeKey'], + settings: { + image_component_desired_encryption_level: { + name: 'Imagebuilder 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' + } + }, + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + var config = { + desiredEncryptionLevelString: settings.image_component_desired_encryption_level || this.settings.image_component_desired_encryption_level.default + }; + + var desiredEncryptionLevel = helpers.ENCRYPTION_LEVELS.indexOf(config.desiredEncryptionLevelString); + var currentEncryptionLevel; + + async.each(regions.imagebuilder, function(region, rcb){ + var listComponents = helpers.addSource(cache, source, + ['imagebuilder', 'listComponents', region]); + + if (!listComponents) return rcb(); + + if (listComponents.err) { + helpers.addResult(results, 3, + 'Unable to query component version list: ' + helpers.addError(listComponents), region); + return rcb(); + } + + if (!listComponents.data || !listComponents.data.length) { + helpers.addResult(results, 0, 'No component version list found', region); + return rcb(); + } + + var listKeys = helpers.addSource(cache, source, + ['kms', 'listKeys', region]); + + if (!listKeys || listKeys.err || !listKeys.data) { + helpers.addResult(results, 3, + `Unable to list KMS keys: ${helpers.addError(listKeys)}`, region); + return rcb(); + } + + var listAliases = helpers.addSource(cache, source, + ['kms', 'listAliases', region]); + + if (!listAliases || listAliases.err || !listAliases.data) { + helpers.addResult(results, 3, + `Unable to query for KMS aliases: ${helpers.addError(listAliases)}`, + region); + return rcb(); + } + + var keyArn; + var kmsAliasArnMap = {}; + listAliases.data.forEach(function(alias){ + keyArn = alias.AliasArn.replace(/:alias\/.*/, ':key/' + alias.TargetKeyId); + kmsAliasArnMap[alias.AliasArn] = keyArn; + }); + + for (let recipe of listComponents.data) { + let resource = recipe.arn; + + var getComponent = helpers.addSource(cache, source, + ['imagebuilder', 'getComponent', region, recipe.arn]); + + if (!getComponent || getComponent.err || !getComponent.data || + !getComponent.data.component) { + helpers.addResult(results, 3, + `Unable to query for component description: ${helpers.addError(getComponent)}`, + region, resource); + continue; + } + + if (getComponent.data.component.kmsKeyId) { + var encryptionKey = getComponent.data.component.kmsKeyId; + let kmsKeyArn = (encryptionKey.includes('alias/')) ? + (kmsAliasArnMap[encryptionKey]) ? kmsAliasArnMap[encryptionKey] : + encryptionKey : encryptionKey; + + var keyId = kmsKeyArn.split('/')[1] ? kmsKeyArn.split('/')[1] : kmsKeyArn; + + var describeKey = helpers.addSource(cache, source, + ['kms', 'describeKey', region, keyId]); + + if (!describeKey || describeKey.err || !describeKey.data || !describeKey.data.KeyMetadata) { + helpers.addResult(results, 3, + `Unable to query KMS key: ${helpers.addError(describeKey)}`, + region, kmsKeyArn); + continue; + } + currentEncryptionLevel = helpers.getEncryptionLevel(describeKey.data.KeyMetadata, helpers.ENCRYPTION_LEVELS); + + } else currentEncryptionLevel = 2; //awskms + + let currentEncryptionLevelString = helpers.ENCRYPTION_LEVELS[currentEncryptionLevel]; + + if (currentEncryptionLevel >= desiredEncryptionLevel) { + helpers.addResult(results, 0, + `Imagebuilder component is encrypted with ${currentEncryptionLevelString} \ + which is greater than or equal to the desired encryption level ${config.desiredEncryptionLevelString}`, + region, resource); + } else { + helpers.addResult(results, 2, + `Imagebuilder component is encrypted with ${currentEncryptionLevelString} \ + which is less than the desired encryption level ${config.desiredEncryptionLevelString}`, + region, resource); + } + } + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.spec.js b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.spec.js new file mode 100644 index 0000000000..55160ad987 --- /dev/null +++ b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.spec.js @@ -0,0 +1,226 @@ +var expect = require('chai').expect; +var imgBuilderComponentsEncrypted = require('./imgBuilderComponentsEncrypted'); + +const listComponents = [ + { + "arn": "arn:aws:imagebuilder:us-east-1:000011112222:component/akhtar-compo/1.0.0", + "name": "akhtar-compo", + "version": "1.0.0", + "platform": "Linux", + "type": "BUILD", + "owner": "000011112222", + "dateCreated": "2022-03-29T10:42:58.859Z" + }, + { + "arn": "arn:aws:imagebuilder:us-east-1:000011112222:component/sadeedcomponent/1.0.0", + "name": "sadeedcomponent", + "version": "1.0.0", + "platform": "Linux", + "supportedOsVersions": [ + "Amazon Linux 2" + ], + "type": "BUILD", + "owner": "000011112222", + "dateCreated": "2022-03-24T15:31:10.328Z" + } +]; + + +const getComponent = [ + { + "requestId": "c061f565-2a9c-4fb5-9eb3-be2da3816257", + "component": { + "arn": "arn:aws:imagebuilder:us-east-1:000011112222:component/akhtar-compo/1.0.0/1", + "name": "akhtar-compo", + "version": "1.0.0", + "type": "BUILD", + "platform": "Linux", + "owner": "000011112222", + "data": "name: HelloWorldTestingDocument\ndescription: This is hello world testing document.\nschemaVersion: 1.0\n\nphases:\n - name: build\n steps:\n - name: HelloWorldStep\n action: ExecuteBash\n inputs:\n commands:\n - echo \"Hello World! Build.\"\n\n - name: validate\n steps:\n - name: HelloWorldStep\n action: ExecuteBash\n inputs:\n commands:\n - echo \"Hello World! Validate.\"\n\n - name: test\n steps:\n - name: HelloWorldStep\n action: ExecuteBash\n inputs:\n commands:\n - echo \"Hello World! Test.\"\n", + "kmsKeyId": "arn:aws:kms:us-east-1:000011112222:alias/akhtar-key", + "encrypted": true, + "dateCreated": "2022-03-29T10:42:58.859Z", + "tags": {} + } + }, + { + "requestId": "9705dd22-00d6-4e31-beec-37b3d025e943", + "component": { + "arn": "arn:aws:imagebuilder:us-east-1:000011112222:component/sadeedcomponent/1.0.0/1", + "name": "sadeedcomponent", + "version": "1.0.0", + "type": "BUILD", + "platform": "Linux", + "supportedOsVersions": [ + "Amazon Linux 2" + ], + "owner": "000011112222", + "data": "name: HelloWorldTestingDocument\ndescription: This is hello world testing document.\nschemaVersion: 1.0\n\nphases:\n - name: build\n steps:\n - name: HelloWorldStep\n action: ExecuteBash\n inputs:\n commands:\n - echo \"Hello World! Build.\"\n\n - name: validate\n steps:\n - name: HelloWorldStep\n action: ExecuteBash\n inputs:\n commands:\n - echo \"Hello World! Validate.\"\n\n - name: test\n steps:\n - name: HelloWorldStep\n action: ExecuteBash\n inputs:\n commands:\n - echo \"Hello World! Test.\"\n", + "encrypted": true, + "dateCreated": "2022-03-24T15:31:10.328Z", + "tags": {} + } + } +]; + +const listAliases = [ + { + 'AliasName': 'alias/akhtar-key', + 'AliasArn': 'arn:aws:kms:us-east-1:000011112222:alias/akhtar-key', + 'TargetKeyId': '1425f881-3b10-486a-aca8-14d2649881e3', + 'CreationDate': '2022-03-29T10:22:52.016Z', + 'LastUpdatedDate': '2022-03-29T10:22:52.016Z' + } +]; + +const describeKey = [ + { + 'KeyMetadata': { + 'AWSAccountId': '000011112222', + 'KeyId': '1425f881-3b10-486a-aca8-14d2649881e3', + 'Arn': 'arn:aws:kms:us-east-1:000011112222:key/1425f881-3b10-486a-aca8-14d2649881e3', + 'CreationDate': '2022-03-29T10:22:51.516Z', + 'Enabled': true, + 'Description': '', + 'KeyUsage': 'ENCRYPT_DECRYPT', + 'KeyState': 'Enabled', + 'Origin': 'AWS_KMS', + 'KeyManager': 'CUSTOMER', + 'CustomerMasterKeySpec': 'SYMMETRIC_DEFAULT', + 'KeySpec': 'SYMMETRIC_DEFAULT', + 'EncryptionAlgorithms': [Array], + 'MultiRegion': false + } + }, + { + "KeyMetadata": { + "AWSAccountId": "000011112222", + "KeyId": "1425f881-3b10-486a-aca8-14d2649881e3", + "Arn": "arn:aws:kms:us-east-1:000011112222:key/1425f881-3b10-486a-aca8-14d2649881e3", + "CreationDate": "2020-12-15T01:16:53.045000+05:00", + "Enabled": true, + "Description": "Default master key that protects my Glue data when no other key is defined", + "KeyUsage": "ENCRYPT_DECRYPT", + "KeyState": "Enabled", + "Origin": "AWS_KMS", + "KeyManager": "AWS", + "CustomerMasterKeySpec": "SYMMETRIC_DEFAULT", + "EncryptionAlgorithms": [ + "SYMMETRIC_DEFAULT" + ] + } + } +]; + +const listKeys = [ + { + "KeyId": "1425f881-3b10-486a-aca8-14d2649881e3", + "KeyArn": "arn:aws:kms:us-east-1:000011112222:key/1425f881-3b10-486a-aca8-14d2649881e3" + } +] + +const createCache = (recipe, keys, kmsAliases, getComponent, describeKey, recipeErr, kmsAliasesErr, keysErr, describeKeyErr, getComponentErr) => { + + var keyId = (keys && keys.length ) ? keys[0].KeyId : null; + var recipeArn = (recipe && recipe.length) ? recipe[0].arn: null; + return { + imagebuilder: { + listComponents: { + 'us-east-1': { + err: recipeErr, + data: recipe + }, + }, + getComponent: { + 'us-east-1': { + [recipeArn]: { + data: getComponent, + err: getComponentErr + } + } + } + }, + kms: { + listAliases: { + 'us-east-1': { + data: kmsAliases, + err: kmsAliasesErr + }, + }, + listKeys: { + 'us-east-1': { + data: keys, + err: keysErr + } + }, + describeKey: { + 'us-east-1': { + [keyId]: { + err: describeKeyErr, + data: describeKey + }, + }, + }, + }, + }; +}; + +describe('imgBuilderComponentsEncrypted', function () { + describe('run', function () { + it('should PASS if Imagebuilder component is encrypted with awscmk', function (done) { + const cache = createCache([listComponents[0]], listKeys, listAliases, getComponent[0], describeKey[0]); + imgBuilderComponentsEncrypted.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Imagebuilder component is encrypted with awscmk'); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + + it('should FAIL if Imagebuilder component is encrypted with awskms', function (done) { + const cache = createCache([listComponents[1]], listKeys, listAliases, getComponent[1], describeKey[1]); + imgBuilderComponentsEncrypted.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Imagebuilder component is encrypted with'); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + + it('should PASS if no component version list found', function (done) { + const cache = createCache([]); + imgBuilderComponentsEncrypted.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No component version list found'); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + + it('should UNKNOWN if unable to query for component description', function (done) { + const cache = createCache([listComponents[0]], listKeys, listAliases, null, null, null, null, + null, null, { message: "Unable to query for component description" }); + imgBuilderComponentsEncrypted.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 component description'); + expect(results[0].region).to.equal('us-east-1'); + done(); + }); + }); + + it('should UNKNOWN if unable to list KMS keys', function (done) { + const cache = createCache(listComponents, null, null, null, null, null, null, { message: "Unable to list KMS keys" }); + imgBuilderComponentsEncrypted.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 KMS keys'); + done(); + }); + }); + }); +}) \ No newline at end of file From d848e9cfe2fb58d73b7115269c41f52209e0b06f Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Wed, 6 Apr 2022 20:21:09 +0500 Subject: [PATCH 047/350] Added MSK Cluster Unauthenticated Access Plugin --- exports.js | 1 + plugins/aws/msk/mskClusterUnauthAccess.js | 58 +++++++ .../aws/msk/mskClusterUnauthAccess.spec.js | 144 ++++++++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 plugins/aws/msk/mskClusterUnauthAccess.js create mode 100644 plugins/aws/msk/mskClusterUnauthAccess.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..c2f504ce93 100644 --- a/exports.js +++ b/exports.js @@ -422,6 +422,7 @@ module.exports = { 'memorydbClusterEncrypted' : require(__dirname + '/plugins/aws/memorydb/memorydbClusterEncrypted.js'), + 'mskClusterUnauthAccess' : require(__dirname + '/plugins/aws/msk/mskClusterUnauthAccess.js'), 'mskClusterEncryptionAtRest' : require(__dirname + '/plugins/aws/msk/mskClusterEncryptionAtRest.js'), 'mskClusterEncryptionInTransit' : require(__dirname + '/plugins/aws/msk/mskClusterEncryptionInTransit.js'), diff --git a/plugins/aws/msk/mskClusterUnauthAccess.js b/plugins/aws/msk/mskClusterUnauthAccess.js new file mode 100644 index 0000000000..5bac7ad6dc --- /dev/null +++ b/plugins/aws/msk/mskClusterUnauthAccess.js @@ -0,0 +1,58 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'MSK Cluster Unauthenticated Access', + category: 'MSK', + domain: 'Compute', + severity: 'Medium', + description: 'Ensure that Unauthentication is disabled within the cluster feature for your Amazon MSK clusters.', + more_info: 'Amazon MSK authenticate clients to allow or deny Apache Kafka actions. Alternatively, TLS or SASL/SCRAM can be used to authenticate clients, and Apache Kafka ACLs to allow or deny actions.', + link: 'https://docs.aws.amazon.com/msk/latest/developerguide/msk-authentication.html', + recommended_action: 'Check for Unauthentication disabled within the cluster for all MSK clusters to allow or deny actions for clients', + apis: ['Kafka:listClusters'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + async.each(regions.kafka, function(region, rcb){ + var listClusters = helpers.addSource(cache, source, + ['kafka', 'listClusters', region]); + + if (!listClusters) return rcb(); + + if (listClusters.err || !listClusters.data) { + helpers.addResult(results, 3, + 'Unable to query for MSK clusters: ' + helpers.addError(listClusters), region); + return rcb(); + } + + if (!listClusters.data.length) { + helpers.addResult(results, 0, 'No MSK clusters found', region); + return rcb(); + } + + for (var cluster of listClusters.data) { + if (!cluster.ClusterArn) continue; + + var resource = cluster.ClusterArn; + + if (cluster.ClientAuthentication && + cluster.ClientAuthentication.Unauthenticated && + cluster.ClientAuthentication.Unauthenticated.Enabled == true) { + helpers.addResult(results, 2, + 'Unauthentication is enabled for clients, and all actions are allowed', region, resource); + } else { + helpers.addResult(results, 0, + 'Unauthentication is disabled for clients, and all actions are not allowed', region, resource); + } + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; diff --git a/plugins/aws/msk/mskClusterUnauthAccess.spec.js b/plugins/aws/msk/mskClusterUnauthAccess.spec.js new file mode 100644 index 0000000000..b8adce496e --- /dev/null +++ b/plugins/aws/msk/mskClusterUnauthAccess.spec.js @@ -0,0 +1,144 @@ +var expect = require('chai').expect; +const mskClusterUnauthAccess = require('./mskClusterUnauthAccess'); + +const listClusters = [ + { + "ClientAuthentication": { + "Sasl": { + "Scram": { + "Enabled": false + }, + "Iam": { + "Enabled": true + } + }, + "Tls": { + "CertificateAuthorityArnList": [], + "Enabled": false + }, + "Unauthenticated": { + "Enabled": false + } + }, + "ClusterArn": "arn:aws:kafka:us-east-1:000011112222:cluster/myCluster/794ab280-627c-4705-aaab-9f5b944fb9e3-25", + "ClusterName": "myCluster", + "CreationTime": "2022-04-06T14:16:16.579000+00:00", + "CurrentBrokerSoftwareInfo": { + "KafkaVersion": "2.6.2" + }, + }, + { + + "ClientAuthentication": { + "Sasl": { + "Scram": { + "Enabled": false + }, + "Iam": { + "Enabled": true + } + }, + "Tls": { + "CertificateAuthorityArnList": [], + "Enabled": false + }, + "Unauthenticated": { + "Enabled": true + } + }, + "ClusterArn": "arn:aws:kafka:us-east-1:000011112222:cluster/sadeedcluster/b08122a8-7104-476a-b6ee-c59444fb04d5-25", + "ClusterName": "sadeedcluster", + "CreationTime": "2022-04-06T14:19:41.573000+00:00", + "CurrentBrokerSoftwareInfo": { + "KafkaVersion": "2.6.2" + }, + } +]; + +const createCache = (clusters) => { + return { + kafka: { + listClusters: { + 'us-east-1': { + data: clusters, + }, + }, + }, + }; +}; + +const createErrorCache = () => { + return { + kafka: { + listClusters: { + 'us-east-1': { + err: { + message: 'error listing clusters' + }, + }, + }, + }, + }; +}; + +const createNullCache = () => { + return { + kafka: { + listClusters: { + 'us-east-1': null, + }, + }, + }; +}; + +describe('mskClusterUnauthAccess', function () { + describe('run', function () { + it('should FAIL if Unauthentication is enabled for clients, and all actions are allowed', function (done) { + const cache = createCache([listClusters[1]]); + mskClusterUnauthAccess.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Unauthentication is enabled for clients, and all actions are allowed'); + done(); + }); + }); + + it('should PASS if Unauthentication is disabled for clients, and all actions are not allowed', function (done) { + const cache = createCache([listClusters[0]]); + mskClusterUnauthAccess.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Unauthentication is disabled for clients, and all actions are not allowed'); + done(); + }); + }); + + it('should PASS no MSK clusters found', function (done) { + const cache = createCache([]); + mskClusterUnauthAccess.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No MSK clusters found'); + done(); + }); + }); + + it('should UNKNOWN if Unable to query for MSK clusters', function (done) { + const cache = createErrorCache(); + mskClusterUnauthAccess.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 MSK clusters'); + done(); + }); + }); + + it('should not return any results if there was an error querying for MSK clusters', function (done) { + const cache = createNullCache(); + mskClusterUnauthAccess.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + }); +}); From f7d13ae73d32891f11411a75db3b99ef1f655c98 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 7 Apr 2022 14:41:52 +0500 Subject: [PATCH 048/350] Added MSK Cluster Public Access Plugin --- exports.js | 1 + plugins/aws/msk/mskClusterPublicAccess.js | 60 ++++++++ .../aws/msk/mskClusterPublicAccess.spec.js | 145 ++++++++++++++++++ 3 files changed, 206 insertions(+) create mode 100644 plugins/aws/msk/mskClusterPublicAccess.js create mode 100644 plugins/aws/msk/mskClusterPublicAccess.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..acdead3587 100644 --- a/exports.js +++ b/exports.js @@ -422,6 +422,7 @@ module.exports = { 'memorydbClusterEncrypted' : require(__dirname + '/plugins/aws/memorydb/memorydbClusterEncrypted.js'), + 'mskClusterPublicAccess' : require(__dirname + '/plugins/aws/msk/mskClusterPublicAccess.js'), 'mskClusterEncryptionAtRest' : require(__dirname + '/plugins/aws/msk/mskClusterEncryptionAtRest.js'), 'mskClusterEncryptionInTransit' : require(__dirname + '/plugins/aws/msk/mskClusterEncryptionInTransit.js'), diff --git a/plugins/aws/msk/mskClusterPublicAccess.js b/plugins/aws/msk/mskClusterPublicAccess.js new file mode 100644 index 0000000000..9250bdcc37 --- /dev/null +++ b/plugins/aws/msk/mskClusterPublicAccess.js @@ -0,0 +1,60 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'MSK Cluster Public Access', + category: 'MSK', + domain: 'Compute', + severity: 'Medium', + description: 'Ensure that public access feature within the cluster is disabled for your Amazon MSK clusters.', + more_info: 'Amazon MSK gives you the option to turn on public access to the brokers of MSK clusters running Apache Kafka 2.6.0 or later versions. For security reasons, you can'/'t turn on public access while creating an MSK cluster. However, you can update an existing cluster to make it publicly accessible.', + link: 'https://docs.aws.amazon.com/msk/latest/developerguide/msk-encryption.html', + recommended_action: 'Check for public access feature within the cluster for all MSK clusters', + apis: ['Kafka:listClusters'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + async.each(regions.kafka, function(region, rcb){ + var listClusters = helpers.addSource(cache, source, + ['kafka', 'listClusters', region]); + + if (!listClusters) return rcb(); + + if (listClusters.err || !listClusters.data) { + helpers.addResult(results, 3, + 'Unable to query for MSK clusters: ' + helpers.addError(listClusters), region); + return rcb(); + } + + if (!listClusters.data.length) { + helpers.addResult(results, 0, 'No MSK clusters found', region); + return rcb(); + } + + for (var cluster of listClusters.data) { + if (!cluster.ClusterArn) continue; + + var resource = cluster.ClusterArn; + + if (cluster.BrokerNodeGroupInfo && + cluster.BrokerNodeGroupInfo.ConnectivityInfo && + cluster.BrokerNodeGroupInfo.ConnectivityInfo.PublicAccess && + cluster.BrokerNodeGroupInfo.ConnectivityInfo.PublicAccess.Type && + cluster.BrokerNodeGroupInfo.ConnectivityInfo.PublicAccess.Type.toUpperCase() === 'DISABLED') { + helpers.addResult(results, 0, + 'msk cluster does not have public access enabled', region, resource); + } else { + helpers.addResult(results, 2, + 'msk cluster has public access enabled', region, resource); + } + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; diff --git a/plugins/aws/msk/mskClusterPublicAccess.spec.js b/plugins/aws/msk/mskClusterPublicAccess.spec.js new file mode 100644 index 0000000000..83a9d7eac4 --- /dev/null +++ b/plugins/aws/msk/mskClusterPublicAccess.spec.js @@ -0,0 +1,145 @@ +var expect = require('chai').expect; +const mskClusterPublicAccess = require('./mskClusterPublicAccess'); + +const listClusters = [ + { + "BrokerNodeGroupInfo": { + "BrokerAZDistribution": "DEFAULT", + "ClientSubnets": [ + "subnet-02ed4181800d4658b", + "subnet-04464dfb7e3dfe1ff", + "subnet-04604cc007728c2a7" + ], + "InstanceType": "kafka.m5.large", + "SecurityGroups": [ + "sg-0cb6c99daaa6b73c5" + ], + "StorageInfo": { + "EbsStorageInfo": { + "ProvisionedThroughput": { + "Enabled": false + }, + "VolumeSize": 1 + } + }, + "ConnectivityInfo": { + "PublicAccess": { + "Type": "SERVICE_PROVIDED_EIPS" + } + } + }, + + "ClusterArn": "arn:aws:kafka:us-east-1:000011112222:cluster/myCluster/794ab280-627c-4705-aaab-9f5b944fb9e3-25", + "ClusterName": "myCluster" + }, + { + "BrokerNodeGroupInfo": { + "BrokerAZDistribution": "DEFAULT", + "ClientSubnets": [ + "subnet-02ed4181800d4658b", + "subnet-04464dfb7e3dfe1ff", + "subnet-06629b4200870c740" + ], + "InstanceType": "kafka.m5.large", + "SecurityGroups": [ + "sg-0cb6c99daaa6b73c5" + ], + "StorageInfo": { + "EbsStorageInfo": { + "ProvisionedThroughput": { + "Enabled": false + }, + "VolumeSize": 1000 + } + }, + "ConnectivityInfo": { + "PublicAccess": { + "Type": "DISABLED" + } + } + }, + + "ClusterArn": "arn:aws:kafka:us-east-1:000011112222:cluster/sadeedcluster/b08122a8-7104-476a-b6ee-c59444fb04d5-25", + "ClusterName": "sadeedcluster" + + } +]; + +const createCache = (clusters) => { + return { + kafka: { + listClusters: { + 'us-east-1': { + data: clusters, + }, + }, + }, + }; +}; + +const createErrorCache = () => { + return { + kafka: { + listClusters: { + 'us-east-1': { + err: { + message: 'error listing clusters' + }, + }, + }, + }, + }; +}; + + +describe('mskClusterPublicAccess', function () { + describe('run', function () { + it('should FAIL if msk cluster has public access enabled', function (done) { + const cache = createCache([listClusters[0]]); + mskClusterPublicAccess.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('msk cluster has public access enabled'); + done(); + }); + }); + + it('should PASS if msk cluster does not have public access enabled', function (done) { + const cache = createCache([listClusters[1]]); + mskClusterPublicAccess.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('msk cluster does not have public access enabled'); + done(); + }); + }); + + it('should PASS no MSK clusters found', function (done) { + const cache = createCache([]); + mskClusterPublicAccess.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No MSK clusters found'); + done(); + }); + }); + + it('should UNKNOWN if Unable to query for MSK clusters', function (done) { + const cache = createCache(null); + mskClusterPublicAccess.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 MSK clusters'); + done(); + }); + }); + + it('should not return any results if there was an error querying for MSK clusters', function (done) { + const cache = createErrorCache(); + mskClusterPublicAccess.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + done(); + }); + }); + }); +}); \ No newline at end of file From 11d6464f999576be985069ab9a5cb16e075b7f7e Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 7 Apr 2022 15:15:21 +0500 Subject: [PATCH 049/350] Update plugins/aws/msk/mskClusterPublicAccess.js --- plugins/aws/msk/mskClusterPublicAccess.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/msk/mskClusterPublicAccess.js b/plugins/aws/msk/mskClusterPublicAccess.js index 9250bdcc37..426a741c3c 100644 --- a/plugins/aws/msk/mskClusterPublicAccess.js +++ b/plugins/aws/msk/mskClusterPublicAccess.js @@ -8,7 +8,7 @@ module.exports = { severity: 'Medium', description: 'Ensure that public access feature within the cluster is disabled for your Amazon MSK clusters.', more_info: 'Amazon MSK gives you the option to turn on public access to the brokers of MSK clusters running Apache Kafka 2.6.0 or later versions. For security reasons, you can'/'t turn on public access while creating an MSK cluster. However, you can update an existing cluster to make it publicly accessible.', - link: 'https://docs.aws.amazon.com/msk/latest/developerguide/msk-encryption.html', + link: 'https://docs.aws.amazon.com/msk/latest/developerguide/public-access.html', recommended_action: 'Check for public access feature within the cluster for all MSK clusters', apis: ['Kafka:listClusters'], From 7dab950d30183054ba38545cc536f667fd5908a5 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 7 Apr 2022 15:24:03 +0500 Subject: [PATCH 050/350] Added MSK Cluster Client Broker Encryption Plugin --- exports.js | 1 + plugins/aws/msk/mskClusterCBEncryption.js | 59 +++++++++ .../aws/msk/mskClusterCBEncryption.spec.js | 120 ++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 plugins/aws/msk/mskClusterCBEncryption.js create mode 100644 plugins/aws/msk/mskClusterCBEncryption.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..eaaba737a9 100644 --- a/exports.js +++ b/exports.js @@ -422,6 +422,7 @@ module.exports = { 'memorydbClusterEncrypted' : require(__dirname + '/plugins/aws/memorydb/memorydbClusterEncrypted.js'), + 'mskClusterCBEncryption' : require(__dirname + '/plugins/aws/msk/mskClusterCBEncryption.js'), 'mskClusterEncryptionAtRest' : require(__dirname + '/plugins/aws/msk/mskClusterEncryptionAtRest.js'), 'mskClusterEncryptionInTransit' : require(__dirname + '/plugins/aws/msk/mskClusterEncryptionInTransit.js'), diff --git a/plugins/aws/msk/mskClusterCBEncryption.js b/plugins/aws/msk/mskClusterCBEncryption.js new file mode 100644 index 0000000000..ed43b8f3d9 --- /dev/null +++ b/plugins/aws/msk/mskClusterCBEncryption.js @@ -0,0 +1,59 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'MSK Cluster Client Broker Encryption', + category: 'MSK', + domain: 'Compute', + severity: 'LOW', + description: 'Ensure that only TLS encryption between the client and broker feature is enabled for your Amazon MSK clusters.', + more_info: 'Amazon MSK in-transit encryption is an optional feature which encrypts data in transit between the client and brokers. Select the Transport Layer Security (TLS) protocol to encrypt data as it travels between brokers and clients within the cluster.', + link: 'https://docs.aws.amazon.com/msk/latest/developerguide/msk-encryption.html', + recommended_action: 'Enable only TLS encryption between the client and broker for all MSK clusters', + apis: ['Kafka:listClusters'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + async.each(regions.kafka, function(region, rcb){ + var listClusters = helpers.addSource(cache, source, + ['kafka', 'listClusters', region]); + + if (!listClusters) return rcb(); + + if (listClusters.err || !listClusters.data) { + helpers.addResult(results, 3, + 'Unable to query for MSK clusters: ' + helpers.addError(listClusters), region); + return rcb(); + } + + if (!listClusters.data.length) { + helpers.addResult(results, 0, 'No MSK clusters found', region); + return rcb(); + } + + for (var cluster of listClusters.data) { + if (!cluster.ClusterArn) continue; + + var resource = cluster.ClusterArn; + + if (cluster.EncryptionInfo && + cluster.EncryptionInfo.EncryptionInTransit && + cluster.EncryptionInfo.EncryptionInTransit.ClientBroker && + cluster.EncryptionInfo.EncryptionInTransit.ClientBroker.toUpperCase() === 'TLS') { + helpers.addResult(results, 0, + 'Encryption between the client and broker is only TLS encrypted', region, resource); + } else { + helpers.addResult(results, 2, + 'Encryption between the client and broker is not only TLS encrypted', region, resource); + } + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; diff --git a/plugins/aws/msk/mskClusterCBEncryption.spec.js b/plugins/aws/msk/mskClusterCBEncryption.spec.js new file mode 100644 index 0000000000..33c40e5964 --- /dev/null +++ b/plugins/aws/msk/mskClusterCBEncryption.spec.js @@ -0,0 +1,120 @@ +var expect = require('chai').expect; +const mskClusterCBEncryption = require('./mskClusterCBEncryption'); + +const listClusters = [ + { + "ClusterArn": "arn:aws:kafka:us-east-1:000011112222:cluster/sadeedcluster/b08122a8-7104-476a-b6ee-c59444fb04d5-25", + "ClusterName": "sadeedcluster", + "CreationTime": "2022-04-06T14:19:41.573000+00:00", + "CurrentBrokerSoftwareInfo": { + "KafkaVersion": "2.6.2" + }, + "CurrentVersion": "K3R76HOPU0Z2CB", + "EncryptionInfo": { + "EncryptionAtRest": { + "DataVolumeKMSKeyId": "arn:aws:kms:us-east-1:000011112222:key/39009d78-b364-4a0b-937f-c89a2c2b473f" + }, + "EncryptionInTransit": { + "ClientBroker": "TLS", + "InCluster": true + } + }, + }, + { + "ClusterArn": "arn:aws:kafka:us-east-1:000011112222:cluster/sadeedcluster/b08122a8-7104-476a-b6ee-c59444fb04d5-25", + "ClusterName": "sadeedcluster", + "CreationTime": "2022-04-06T14:19:41.573000+00:00", + "CurrentBrokerSoftwareInfo": { + "KafkaVersion": "2.6.2" + }, + "CurrentVersion": "K3R76HOPU0Z2CB", + "EncryptionInfo": { + "EncryptionAtRest": { + "DataVolumeKMSKeyId": "arn:aws:kms:us-east-1:000011112222:key/39009d78-b364-4a0b-937f-c89a2c2b473f" + }, + "EncryptionInTransit": { + "ClientBroker": "TLS_PLAINTEXT", + "InCluster": true + } + }, + } +]; + +const createCache = (clusters) => { + return { + kafka: { + listClusters: { + 'us-east-1': { + data: clusters, + }, + }, + }, + }; +}; + +const createErrorCache = () => { + return { + kafka: { + listClusters: { + 'us-east-1': { + err: { + message: 'error listing clusters' + }, + }, + }, + }, + }; +}; + + +describe('mskClusterCBEncryption', function () { + describe('run', function () { + it('should FAIL if Encryption between the client and broker is not only TLS encrypted', function (done) { + const cache = createCache([listClusters[1]]); + mskClusterCBEncryption.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Encryption between the client and broker is not only TLS encrypted'); + done(); + }); + }); + + it('should PASS if Encryption between the client and broker is only TLS encrypted', function (done) { + const cache = createCache([listClusters[0]]); + mskClusterCBEncryption.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Encryption between the client and broker is only TLS encrypted'); + done(); + }); + }); + + it('should PASS if no MSK clusters found', function (done) { + const cache = createCache([]); + mskClusterCBEncryption.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No MSK clusters found'); + done(); + }); + }); + + it('should UNKNOWN if Unable to query for MSK clusters', function (done) { + const cache = createCache(null); + mskClusterCBEncryption.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 MSK clusters'); + done(); + }); + }); + + it('should not return any results if there was an error querying for MSK clusters', function (done) { + const cache = createErrorCache(); + mskClusterCBEncryption.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + done(); + }); + }); + }); +}); From 7d92aff4f2d06890d91254d5d8d223e251919f15 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 7 Apr 2022 21:21:06 +0500 Subject: [PATCH 051/350] Update plugins/aws/msk/mskClusterUnauthAccess.js --- plugins/aws/msk/mskClusterUnauthAccess.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/aws/msk/mskClusterUnauthAccess.js b/plugins/aws/msk/mskClusterUnauthAccess.js index 5bac7ad6dc..c990b4b136 100644 --- a/plugins/aws/msk/mskClusterUnauthAccess.js +++ b/plugins/aws/msk/mskClusterUnauthAccess.js @@ -49,7 +49,6 @@ module.exports = { 'Unauthentication is disabled for clients, and all actions are not allowed', region, resource); } } - rcb(); }, function(){ callback(null, results, source); From 45ec1ece976dab136852027cfacaba2ee5c044a8 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 7 Apr 2022 21:23:01 +0500 Subject: [PATCH 052/350] Update plugins/aws/msk/mskClusterUnauthAccess.js --- plugins/aws/msk/mskClusterUnauthAccess.js | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/aws/msk/mskClusterUnauthAccess.js b/plugins/aws/msk/mskClusterUnauthAccess.js index c990b4b136..7fee953e35 100644 --- a/plugins/aws/msk/mskClusterUnauthAccess.js +++ b/plugins/aws/msk/mskClusterUnauthAccess.js @@ -49,6 +49,7 @@ module.exports = { 'Unauthentication is disabled for clients, and all actions are not allowed', region, resource); } } + rcb(); }, function(){ callback(null, results, source); From 37924b539f1eec40c2bd5823c390f60629895304 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Fri, 8 Apr 2022 00:45:49 +0500 Subject: [PATCH 053/350] GCP Restricted API Keys Plugin --- collectors/google/collector.js | 20 ++++ exports.js | 2 + helpers/google/index.js | 4 +- helpers/google/regions.js | 1 + plugins/google/api/restrictedAPIKeys.js | 58 +++++++++ plugins/google/api/restrictedAPIKeys.spec.js | 118 +++++++++++++++++++ 6 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 plugins/google/api/restrictedAPIKeys.js create mode 100644 plugins/google/api/restrictedAPIKeys.spec.js diff --git a/collectors/google/collector.js b/collectors/google/collector.js index 227bbb29d4..7c1123d4ca 100644 --- a/collectors/google/collector.js +++ b/collectors/google/collector.js @@ -293,6 +293,12 @@ var calls = { location: null, pagination: true } + }, + apiKeys: { + list: { + url: 'https://apikeys.googleapis.com/v2/projects/{projectId}/locations/global/keys', + location: null + } } }; @@ -397,6 +403,20 @@ var postcalls = { method: 'POST', pagination: true, paginationKey: 'pageSize' + }, + getCmekSettings: { + url: 'https://logging.googleapis.com/v2/organizations/{organizationId}/cmekSettings', + reliesOnService: ['organizations'], + reliesOnCall: ['list'], + properties: ['organizationId'] + } + }, + apiKeys: { + get: { + url: 'https://apikeys.googleapis.com/v2/{name}', + reliesOnService: ['apiKeys'], + reliesOnCall: ['list'], + properties: ['name'] } } }; diff --git a/exports.js b/exports.js index 36d4be0d16..17a2d10251 100644 --- a/exports.js +++ b/exports.js @@ -928,6 +928,8 @@ module.exports = { 'serviceAccountTokenCreator' : require(__dirname + '/plugins/google/iam/serviceAccountTokenCreator.js'), 'memberAdmin' : require(__dirname + '/plugins/google/iam/memberAdmin.js'), + + 'restrictedAPIKeys' : require(__dirname + '/plugins/google/api/restrictedAPIKeys.js'), 'privateEndpoint' : require(__dirname + '/plugins/google/kubernetes/privateEndpoint.js'), 'monitoringEnabled' : require(__dirname + '/plugins/google/kubernetes/monitoringEnabled.js'), diff --git a/helpers/google/index.js b/helpers/google/index.js index 2669aa88e5..fbc80bad20 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -161,7 +161,7 @@ var run = function(GoogleConfig, collection, settings, service, callObj, callKey records = collection[callObj.reliesOnService[reliedService]][callObj.reliesOnCall[reliedService]][region].data; if (callObj.subObj) records = records.filter(record => !!record[callObj.subObj]); - async.eachLimit(records, 10, function(record, recordCb) { + async.eachLimit(records, 10, function(record, recordCb) { for (var property in callObj.properties) { callObj.urlToCall = callObj.url.replace(`{${callObj.properties[property]}}`, !callObj.subObj ? record[callObj.properties[property]] : record[callObj.subObj][callObj.properties[property]]); } @@ -273,6 +273,8 @@ var execute = async function(LocalGoogleConfig, collection, service, callObj, ca resultItems = setData(collectionItems, data.data[service], postCall, parent); } else if (!myEngine && data.data.accounts) { resultItems = setData(collectionItems, data.data.accounts, postCall, parent); + } else if (!myEngine && data.data.keys) { + resultItems = setData(collectionItems, data.data.keys, postCall, parent); } else if (!myEngine && data.data) { set = false; if (data.data.constructor.name === 'Array') { diff --git a/helpers/google/regions.js b/helpers/google/regions.js index 39b468f98b..46cf572a61 100644 --- a/helpers/google/regions.js +++ b/helpers/google/regions.js @@ -112,4 +112,5 @@ module.exports = { organizations: ['global'], deployments: ['global'], urlMaps: ['global'], + apiKeys: ['global'] }; diff --git a/plugins/google/api/restrictedAPIKeys.js b/plugins/google/api/restrictedAPIKeys.js new file mode 100644 index 0000000000..f390f087c5 --- /dev/null +++ b/plugins/google/api/restrictedAPIKeys.js @@ -0,0 +1,58 @@ +var helpers = require('../../../helpers/google'); + +module.exports = { + title: 'Restricted API Keys', + category: 'API', + domain: 'API', + description: 'Ensure that your Google Cloud API Keys are restricted to only those APIs that your application needs access to.', + more_info: 'API keys are unrestricted by default. Unrestricted keys are insecure because they can be used by anyone from anywhere. To reduce the risk of attacks, Google Cloud API keys should be restricted to call only the APIs required by your application.', + link: 'https://cloud.google.com/docs/authentication/api-keys#api_key_restrictions', + recommended_action: 'Ensure that API restrictions are set for all Google Cloud API Keys.', + apis: ['apiKeys:list', 'projects:get'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + + let projects = helpers.addSource(cache, source, + ['projects', 'get', 'global']); + + if (!projects || projects.err || !projects.data) { + helpers.addResult(results, 3, + 'Unable to query for projects: ' + helpers.addError(projects), 'global', null, null, projects.err); + return callback(null, results, source); + } + + let apiKeys = helpers.addSource(cache, source, + ['apiKeys', 'list', 'global']); + + if (!apiKeys) return callback(null, results, source); + + if (apiKeys.err || !apiKeys.data) { + helpers.addResult(results, 3, 'Unable to query API Keys for project', 'global', null, null, apiKeys.err); + return callback(null, results, source); + } + + if (!apiKeys.data.length) { + helpers.addResult(results, 0, 'No API Keys found', 'global'); + return callback(null, results, source); + } + + apiKeys.data.forEach(key => { + if (key.restrictions && key.restrictions.apiTargets && key.restrictions.apiTargets.length && + !key.restrictions.apiTargets.find(target => target.service && target.service === 'cloudapis.googleapis.com')) { + helpers.addResult(results, 0, + 'API Key is restricted', 'global', key.name); + } else { + helpers.addResult(results, 2, + 'API Key is not restricted', 'global', key.name); + } + }); + + return callback(null, results, source); + } +}; + + + + diff --git a/plugins/google/api/restrictedAPIKeys.spec.js b/plugins/google/api/restrictedAPIKeys.spec.js new file mode 100644 index 0000000000..5a669bd0d8 --- /dev/null +++ b/plugins/google/api/restrictedAPIKeys.spec.js @@ -0,0 +1,118 @@ +var expect = require('chai').expect; +var plugin = require('./restrictedAPIKeys'); + + +const apiKeys = [ + { + "name": "projects/my-project/locations/global/keys/my-key-1", + "displayName": "API Key 1", + "restrictions": { + "apiTargets": [ + { + "service": "apigateway.googleapis.com" + }, + { + "service": "apikeys" + } + ] + }, + }, + { + "name": "projects/my-project/locations/global/keys/my-key-2", + "displayName": "API key 2", + } +]; + +const createCache = (list, err) => { + return { + apiKeys: { + list: { + 'global': { + err: err, + data: list + } + }, + }, + projects: { + get: { + 'global': { + data: [ { name: 'testproj' } ] + } + } + } + } +}; + +describe('restrictedAPIKeys', function () { + describe('run', function () { + + it('should give unknown result if unable to query api keys', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('Unable to query API Keys for project'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if no api keys found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No API Keys found'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if google cloud api key is restricted', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('API Key is restricted'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + [apiKeys[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give failing result if google cloud api key is not restricted', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('API Key is not restricted'); + expect(results[0].region).to.equal('global') + done(); + }; + + const cache = createCache( + [apiKeys[1]], + null); + + plugin.run(cache, {}, callback); + }); + + }) +}); + From 524268a8c4c1a0caed2bf675232b1b06af898f01 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Fri, 8 Apr 2022 01:56:26 +0500 Subject: [PATCH 054/350] GCP API Key Rotation Plugin --- exports.js | 1 + plugins/google/api/apiKeyRotation.js | 69 ++++++++++++++ plugins/google/api/apiKeyRotation.spec.js | 111 ++++++++++++++++++++++ 3 files changed, 181 insertions(+) create mode 100644 plugins/google/api/apiKeyRotation.js create mode 100644 plugins/google/api/apiKeyRotation.spec.js diff --git a/exports.js b/exports.js index 17a2d10251..687916559b 100644 --- a/exports.js +++ b/exports.js @@ -930,6 +930,7 @@ module.exports = { 'memberAdmin' : require(__dirname + '/plugins/google/iam/memberAdmin.js'), 'restrictedAPIKeys' : require(__dirname + '/plugins/google/api/restrictedAPIKeys.js'), + 'apiKeyRotation' : require(__dirname + '/plugins/google/api/apiKeyRotation.js'), 'privateEndpoint' : require(__dirname + '/plugins/google/kubernetes/privateEndpoint.js'), 'monitoringEnabled' : require(__dirname + '/plugins/google/kubernetes/monitoringEnabled.js'), diff --git a/plugins/google/api/apiKeyRotation.js b/plugins/google/api/apiKeyRotation.js new file mode 100644 index 0000000000..1054378f64 --- /dev/null +++ b/plugins/google/api/apiKeyRotation.js @@ -0,0 +1,69 @@ +var helpers = require('../../../helpers/google'); + +module.exports = { + title: 'Restricted API Keys', + category: 'API', + domain: 'API', + description: 'Ensure that your Google Cloud API Keys are periodically regenerated.', + more_info: 'Make sure that your Google API Keys are regenerated regularly to avoid data leaks and unauthorized access through outdated API Keys.', + link: 'https://cloud.google.com/docs/authentication/api-keys', + recommended_action: 'Ensure that all your Google Cloud API keys are regenerated (rotated) after a specific period.', + apis: ['apiKeys:list', 'projects:get'], + settings: { + api_keys_rotation_interval: { + name: 'API Keys Rotation Interval', + description: 'Return a failing result when api keys exceed this number of days without being rotated', + regex: '^[1-9]{1}[0-9]{0,3}$', + default: '90' + } + }, + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + + var apiKeyRotationInterval = parseInt(settings.api_keys_rotation_interval || this.settings.api_keys_rotation_interval.default); + + let projects = helpers.addSource(cache, source, + ['projects', 'get', 'global']); + + if (!projects || projects.err || !projects.data) { + helpers.addResult(results, 3, + 'Unable to query for projects: ' + helpers.addError(projects), 'global', null, null, projects.err); + return callback(null, results, source); + } + + let apiKeys = helpers.addSource(cache, source, + ['apiKeys', 'list', 'global']); + + if (!apiKeys) return callback(null, results, source); + + if (apiKeys.err || !apiKeys.data) { + helpers.addResult(results, 3, 'Unable to query API Keys for project', 'global', null, null, apiKeys.err); + return callback(null, results, source); + } + + if (!apiKeys.data.length) { + helpers.addResult(results, 0, 'No API Keys found', 'global'); + return callback(null, results, source); + } + + apiKeys.data.forEach(key => { + var diffInDays = helpers.daysBetween(key.createTime, new Date()); + + if (diffInDays > apiKeyRotationInterval) { + helpers.addResult(results, 2, + `API Key was last rotated ${diffInDays} days ago which is greater than ${apiKeyRotationInterval}`, 'global', key.name); + } else { + helpers.addResult(results, 0, + `API Key was last rotated ${diffInDays} days ago which is equal to or less than ${apiKeyRotationInterval}`, 'global', key.name); + } + }); + + return callback(null, results, source); + } +}; + + + + diff --git a/plugins/google/api/apiKeyRotation.spec.js b/plugins/google/api/apiKeyRotation.spec.js new file mode 100644 index 0000000000..cb41b3da39 --- /dev/null +++ b/plugins/google/api/apiKeyRotation.spec.js @@ -0,0 +1,111 @@ +var expect = require('chai').expect; +var plugin = require('./apiKeyRotation'); + + +const apiKeys = [ + { + "name": "projects/my-project/locations/global/keys/my-key-1", + "displayName": "API Key 1", + "createTime": '2022-04-07T17:23:05.126949Z', + }, + { + "name": "projects/my-project/locations/global/keys/my-key-2", + "displayName": "API key 2", + "createTime": '2021-04-07T17:23:05.126949Z', + + } +]; + +const createCache = (list, err) => { + return { + apiKeys: { + list: { + 'global': { + err: err, + data: list + } + }, + }, + projects: { + get: { + 'global': { + data: [ { name: 'testproj' } ] + } + } + } + } +}; + +describe('restrictedAPIKeys', function () { + describe('run', function () { + + it('should give unknown result if unable to query api keys', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('Unable to query API Keys for project'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if no api keys found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No API Keys found'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if google cloud api key is not outdated', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('which is equal to or less than'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + [apiKeys[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give failing result if google cloud api key is outdated', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('which is greater than'); + expect(results[0].region).to.equal('global') + done(); + }; + + const cache = createCache( + [apiKeys[1]], + null); + + plugin.run(cache, {}, callback); + }); + + }) +}); + From 64066174ba1293913f2191d26a365c3d44766d41 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Fri, 8 Apr 2022 02:58:43 +0500 Subject: [PATCH 055/350] GCP API Key Application Restriction Plugin --- exports.js | 1 + .../api/apiKeyApplicationRestriction.js | 72 +++++++++++ .../api/apiKeyApplicationRestriction.spec.js | 113 ++++++++++++++++++ 3 files changed, 186 insertions(+) create mode 100644 plugins/google/api/apiKeyApplicationRestriction.js create mode 100644 plugins/google/api/apiKeyApplicationRestriction.spec.js diff --git a/exports.js b/exports.js index 687916559b..324e64fc63 100644 --- a/exports.js +++ b/exports.js @@ -931,6 +931,7 @@ module.exports = { 'restrictedAPIKeys' : require(__dirname + '/plugins/google/api/restrictedAPIKeys.js'), 'apiKeyRotation' : require(__dirname + '/plugins/google/api/apiKeyRotation.js'), + 'apiKeyApplicationRestriction' : require(__dirname + '/plugins/google/api/apiKeyApplicationRestriction.js'), 'privateEndpoint' : require(__dirname + '/plugins/google/kubernetes/privateEndpoint.js'), 'monitoringEnabled' : require(__dirname + '/plugins/google/kubernetes/monitoringEnabled.js'), diff --git a/plugins/google/api/apiKeyApplicationRestriction.js b/plugins/google/api/apiKeyApplicationRestriction.js new file mode 100644 index 0000000000..dbe5d051b0 --- /dev/null +++ b/plugins/google/api/apiKeyApplicationRestriction.js @@ -0,0 +1,72 @@ +var helpers = require('../../../helpers/google'); + +module.exports = { + title: 'API Key Application Restriction', + category: 'API', + domain: 'API', + description: 'Ensure there are no unrestricted API keys available within your GCP project.', + more_info: 'To reduce the risk of attacks, Google Cloud API keys should be restricted only to trusted hosts, HTTP referrers, and Android/iOS mobile applications..', + link: 'https://cloud.google.com/docs/authentication/api-keys#adding_application_restrictions', + recommended_action: 'Ensure that Application restrictions are set for all Google Cloud API Keys.', + apis: ['apiKeys:list', 'projects:get'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + + let projects = helpers.addSource(cache, source, + ['projects', 'get', 'global']); + + if (!projects || projects.err || !projects.data) { + helpers.addResult(results, 3, + 'Unable to query for projects: ' + helpers.addError(projects), 'global', null, null, projects.err); + return callback(null, results, source); + } + + let apiKeys = helpers.addSource(cache, source, + ['apiKeys', 'list', 'global']); + + if (!apiKeys) return callback(null, results, source); + + if (apiKeys.err || !apiKeys.data) { + helpers.addResult(results, 3, 'Unable to query API Keys for project', 'global', null, null, apiKeys.err); + return callback(null, results, source); + } + + if (!apiKeys.data.length) { + helpers.addResult(results, 0, 'No API Keys found', 'global'); + return callback(null, results, source); + } + + apiKeys.data.forEach(key => { + let isRestricted = false; + + if (key.restrictions) { + if (key.restrictions.browserKeyRestrictions && key.restrictions.browserKeyRestrictions.allowedReferrers + && key.restrictions.browserKeyRestrictions.allowedReferrers.length) { + isRestricted = true; + } + if (key.restrictions.serverKeyRestrictions && key.restrictions.serverKeyRestrictions.allowedIps + && key.restrictions.serverKeyRestrictions.allowedIps.length) { + let allowedIps = key.restrictions.serverKeyRestrictions.allowedIps; + if (!(allowedIps.includes('0.0.0.0') || allowedIps.includes('0.0.0.0/0') || allowedIps.includes('::0'))) { + isRestricted = true; + } + } + } + if (isRestricted) { + helpers.addResult(results, 0, + 'API Key usage is restricted to restricted to trusted hosts, HTTP referrers, or applications', 'global', key.name); + } else { + helpers.addResult(results, 2, + 'API Key usage is not restricted to restricted to trusted hosts, HTTP referrers, or applications', 'global', key.name); + } + }); + + return callback(null, results, source); + } +}; + + + + diff --git a/plugins/google/api/apiKeyApplicationRestriction.spec.js b/plugins/google/api/apiKeyApplicationRestriction.spec.js new file mode 100644 index 0000000000..c0ba64e8a3 --- /dev/null +++ b/plugins/google/api/apiKeyApplicationRestriction.spec.js @@ -0,0 +1,113 @@ +var expect = require('chai').expect; +var plugin = require('./apiKeyApplicationRestriction'); + + +const apiKeys = [ + { + "name": "projects/my-project/locations/global/keys/my-key-1", + "displayName": "API Key 1", + "restrictions": { + "browserKeyRestrictions": { + "allowedReferrers" : [ "www.google.com"] + } + }, + }, + { + "name": "projects/my-project/locations/global/keys/my-key-2", + "displayName": "API key 2", + } +]; + +const createCache = (list, err) => { + return { + apiKeys: { + list: { + 'global': { + err: err, + data: list + } + }, + }, + projects: { + get: { + 'global': { + data: [ { name: 'testproj' } ] + } + } + } + } +}; + +describe('apiKeyApplicationRestriction', function () { + describe('run', function () { + + it('should give unknown result if unable to query api keys', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('Unable to query API Keys for project'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if no api keys found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No API Keys found'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if google cloud api key is restricted', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('API Key usage is restricted'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + [apiKeys[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give failing result if google cloud api key is not restricted', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('API Key usage is not restricted'); + expect(results[0].region).to.equal('global') + done(); + }; + + const cache = createCache( + [apiKeys[1]], + null); + + plugin.run(cache, {}, callback); + }); + + }) +}); + From 375a16fe56e7cb0a081e8ec0c7d88907ac4b716e Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 10 Apr 2022 03:00:50 +0500 Subject: [PATCH 056/350] Added allowedCertificateKeyTypes plugin and spec --- exports.js | 1 + .../keyvaults/allowedCertificateKeyTypes.js | 70 ++++++++ .../allowedCertificateKeyTypes.spec.js | 160 ++++++++++++++++++ 3 files changed, 231 insertions(+) create mode 100644 plugins/azure/keyvaults/allowedCertificateKeyTypes.js create mode 100644 plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..06dfdf7124 100644 --- a/exports.js +++ b/exports.js @@ -755,6 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), + 'allowedCertificateKeyTypes' : require(__dirname + '/plugins/azure/keyvaults/allowedCertificateKeyTypes.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js new file mode 100644 index 0000000000..6c6b294e60 --- /dev/null +++ b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js @@ -0,0 +1,70 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Allowed Certificates Key Types', + category: 'Key Vaults', + domain: 'Identity and Access Management', + description: 'Ensures that Microsoft Azure Key Vault SSL certificates are using the allowed key types.', + more_info: 'Having the right key type set for your Azure Key Vault SSL certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', + recommended_action: 'Ensure that Key Vault SSL certificates are using the allowed key types.', + link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/certificate-access-control', + apis: ['vaults:list', 'vaults:getKeys'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.vaults, function(location, rcb) { + var vaults = helpers.addSource(cache, source, + ['vaults', 'list', location]); + + if (!vaults) return rcb(); + + if (vaults.err || !vaults.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); + return rcb(); + } + + if (!vaults.data.length) { + helpers.addResult(results, 0, 'No Key Vaults found', location); + return rcb(); + } + + vaults.data.forEach((vault) => { + var keys = helpers.addSource(cache, source, + ['vaults', 'getKeys', location, vault.id]); + + if (!keys || keys.err || !keys.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); + } else if (!keys.data.length) { + helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); + } else { + keys.data.forEach((key) => { + var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); + var keyId = `${vault.id}/keys/${keyName}`; + + if (key.attributes) { + let attributes = key.attributes; + if ((attributes.expires && attributes.expires !== null && attributes.expires !== '') || (attributes.exp && attributes.exp !== null && attributes.exp !== '')) { + helpers.addResult(results, 0, + 'Expiry date is set for the key', location, keyId); + } else { + helpers.addResult(results, 2, + 'Expiry date is not set for the key', location, keyId); + } + } else { + helpers.addResult(results, 2, + 'Expiry date is not set for the key', location, keyId); + } + }); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js new file mode 100644 index 0000000000..7d048cb2f5 --- /dev/null +++ b/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js @@ -0,0 +1,160 @@ +var expect = require('chai').expect; +var auth = require('./secretExpirationEnabled'); + +const listVaults = [ + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + }, + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + }, + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + } +]; + +const getKeys = [ + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "exp": null, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + }, + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "exp": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + }, + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": false, + "exp": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + } +]; + +const createCache = (err, list, get) => { + return { + vaults: { + list: { + 'eastus': { + err: err, + data: list + } + }, + getSecrets: { + 'eastus': get + } + } + } +}; + +describe('secretExpirationEnabled', function() { + describe('run', function() { + it('should give passing result if no secrets 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 Key Vaults found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [], {}), {}, callback); + }); + + it('should give failing result if expiration is not set on secrets', 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('Expiry date is not set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], getKeys[0]), {}, callback); + }); + + it('should give passing result if expiration is set on keys', 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('Expiry date is set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[1]], getKeys[1]), {}, callback); + }); + + it('should give passing result if key is disabled', 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('The secret is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[2]], getKeys[2]), {}, callback); + }) + }) +}); From 055bf61e99a83594e39b2b517fdb89d55ed9aa30 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 10 Apr 2022 13:22:59 +0500 Subject: [PATCH 057/350] Added checkEncryptionKeysExpiry plugin and spec --- exports.js | 1 + .../keyvaults/checkEncryptionKeysExpiry.js | 79 +++++++++++++ .../checkEncryptionKeysExpiry.spec.js | 105 ++++++++++++++++++ 3 files changed, 185 insertions(+) create mode 100644 plugins/azure/keyvaults/checkEncryptionKeysExpiry.js create mode 100644 plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..2ff7942db0 100644 --- a/exports.js +++ b/exports.js @@ -755,6 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), + 'checkEncryptionKeysExpiry' : require(__dirname + '/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js b/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js new file mode 100644 index 0000000000..9283849d73 --- /dev/null +++ b/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js @@ -0,0 +1,79 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Key Expiration Enabled', + category: 'Key Vaults', + domain: 'Identity and Access Management', + description: 'Ensure that all Keys in Azure Key Vault have an expiry time set.', + more_info: 'Setting an expiry time on all keys forces key rotation and removes unused and forgotten keys from being used.', + recommended_action: 'Ensure each Key Vault has an expiry time set that provides for sufficient rotation.', + link: 'https://docs.microsoft.com/en-us/azure/key-vault/about-keys-secrets-and-certificates', + apis: ['vaults:list', 'vaults:getKeys'], + settings: { + encryption_keys_expiry_period: { + name: 'Key Vault Keys Expiration Period', + description: 'The period of time in days for a key expiration.', + regex: '^(?:36[0-5]|3[0-5][0-9]|[12][0-9][0-9]|[1-9][0-9]|[1-9])$', + default: 30 + } + }, + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + var encryption_keys_expiry_period = parseInt(settings.encryption_keys_expiry_period || this.settings.encryption_keys_expiry_period.default); + + async.each(locations.vaults, function(location, rcb) { + var vaults = helpers.addSource(cache, source, + ['vaults', 'list', location]); + + if (!vaults) return rcb(); + + if (vaults.err || !vaults.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); + return rcb(); + } + + if (!vaults.data.length) { + helpers.addResult(results, 0, 'No Key Vaults found', location); + return rcb(); + } + + vaults.data.forEach(function(vault){ + var keys = helpers.addSource(cache, source, + ['vaults', 'getKeys', location, vault.id]); + + if (!keys || keys.err || !keys.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); + } else if (!keys.data.length) { + helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); + } else { + keys.data.forEach(function(key){ + var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); + var keyId = `${vault.id}/keys/${keyName}`; + + if (key.attributes) { + let expiryPeriodInDays = helpers.daysBetween(new Date(), key.attributes.expires); + if (expiryPeriodInDays < encryption_keys_expiry_period) { + helpers.addResult(results, 0, + 'Key Vault encryption keys expiration is within the set expiry period', location, keyId); + } else { + helpers.addResult(results, 2, + 'Key Vault encryption keys expiration greater then the set expiry period', location, keyId); + } + } else { + helpers.addResult(results, 2, + 'Key Vault encryption keys expiration is not enabled', location, keyId); + } + }); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js b/plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js new file mode 100644 index 0000000000..7d864d43eb --- /dev/null +++ b/plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js @@ -0,0 +1,105 @@ +var assert = require('assert'); +var expect = require('chai').expect; +var auth = require('./secretExpirationEnabled'); + +const listKeyVaults = [ + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + } +]; + +const getKeys = [ + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "exp": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + } +]; + +const createCache = (err, list, get) => { + return { + vaults: { + list: { + 'eastus': { + err: err, + data: list + } + }, + getSecrets: { + 'eastus': get + } + } + } +}; + +describe('secretExpirationEnabled', function() { + describe('run', function() { + it('should give passing result if no secrets 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 Key Vaults found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [], {}), {}, callback); + }); + + it('should give failing result if expiration is not set on secrets', 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('Expiry date is not set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, listKeyVaults, getKeys[0]), {}, callback); + }); + + it('should give passing result if expiration is set on keys', 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('Expiry date is set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, listKeyVaults, getKeys[0]), {}, callback); + }); + + it('should give passing result if key is disabled', 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('The secret is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, listKeyVaults, getKeys[0]), {}, callback); + }) + }) +}); From faaeeab6bf082e57935beee3d089794822baa3f9 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Mon, 11 Apr 2022 02:13:57 +0500 Subject: [PATCH 058/350] Added checkSecretsExpiry plugin and spec --- exports.js | 1 + plugins/azure/keyvaults/checkSecretsExpiry.js | 77 +++++++++ .../keyvaults/checkSecretsExpiry.spec.js | 149 ++++++++++++++++++ 3 files changed, 227 insertions(+) create mode 100644 plugins/azure/keyvaults/checkSecretsExpiry.js create mode 100644 plugins/azure/keyvaults/checkSecretsExpiry.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..e4bc762704 100644 --- a/exports.js +++ b/exports.js @@ -755,6 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), + 'checkSecretsExpiry' : require(__dirname + '/plugins/azure/keyvaults/checkSecretsExpiry.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/checkSecretsExpiry.js b/plugins/azure/keyvaults/checkSecretsExpiry.js new file mode 100644 index 0000000000..6ee5a07602 --- /dev/null +++ b/plugins/azure/keyvaults/checkSecretsExpiry.js @@ -0,0 +1,77 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Key Expiration Enabled', + category: 'Key Vaults', + domain: 'Identity and Access Management', + description: 'Ensure that all Keys in Azure Key Vault have an expiry time set.', + more_info: 'Setting an expiry time on all keys forces key rotation and removes unused and forgotten keys from being used.', + recommended_action: 'Ensure each Key Vault has an expiry time set that provides for sufficient rotation.', + link: 'https://docs.microsoft.com/en-us/azure/key-vault/about-keys-secrets-and-certificates', + apis: ['vaults:list', 'vaults:getSecrets'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.vaults, function(location, rcb) { + var vaults = helpers.addSource(cache, source, + ['vaults', 'list', location]); + + if (!vaults) return rcb(); + + if (vaults.err || !vaults.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); + return rcb(); + } + + if (!vaults.data.length) { + helpers.addResult(results, 0, 'No Key Vaults found', location); + return rcb(); + } + + vaults.data.forEach(function(vault) { + var secrets = helpers.addSource(cache, source, + ['vaults', 'getSecrets', location, vault.id]); + + if (!secrets || secrets.err || !secrets.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault secrets: ' + helpers.addError(secrets), location, vault.id); + } else if (!secrets.data.length) { + helpers.addResult(results, 0, 'No Key Vault secrets found', location, vault.id); + } else { + secrets.data.forEach(function(secret) { + var secretName = secret.id.substring(secret.id.lastIndexOf('/') + 1); + var secretId = `${vault.id}/secrets/${secretName}`; + + if (secret.attributes) { + let attributes = secret.attributes; + if (!attributes.enabled) { + helpers.addResult(results, 0, 'The secret is disabled', location, secretId); + } else if (attributes.expiry) { + if (new Date(Date.now()) < new Date(attributes.expiry)) { + helpers.addResult(results, 0, + 'Expiry date is set for the secret and is within the set expiry period', location, secretId); + } else { + helpers.addResult(results, 2, + 'Expiry date is set for the secret and is greater than the set expiry period', location, secretId); + } + } else { + helpers.addResult(results, 2, + 'Expiry date is not set for the secret', location, secretId); + } + } else { + helpers.addResult(results, 2, + 'Expiry date is not set for the secret', location, secretId); + } + }); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/keyvaults/checkSecretsExpiry.spec.js b/plugins/azure/keyvaults/checkSecretsExpiry.spec.js new file mode 100644 index 0000000000..eb4cd7d182 --- /dev/null +++ b/plugins/azure/keyvaults/checkSecretsExpiry.spec.js @@ -0,0 +1,149 @@ +var expect = require('chai').expect; +var auth = require('./checkSecretsExpiry'); + +const listKeyVaults = [ + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + }, + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + } +]; + +const getSecrets = [ + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "expiry": null, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + }, + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "expiry": '2022-12-10T21:08:47.684Z', + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + }, + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": false, + "expiry": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + } +]; + +const createCache = (err, list, get) => { + return { + vaults: { + list: { + 'eastus': { + err: err, + data: list + } + }, + getSecrets: { + 'eastus': get + } + } + } +}; + +describe('checkSecretsExpiry', function() { + describe('run', function() { + it('should give passing result if no secrets 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 Key Vaults found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [], {}), {}, callback); + }); + + it('should give failing result if expiration is not set on secrets', 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('Expiry date is not set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listKeyVaults[0]], getSecrets[0]), {}, callback); + }); + + it('should give passing result if expiration is set on keys', 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('Expiry date is set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listKeyVaults[0]], getSecrets[1]), {}, callback); + }); + + it('should give passing result if key is disabled', 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('The secret is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listKeyVaults[0]], getSecrets[2]), {}, callback); + }); + }) +}); From 1f513023b9f46a6f6bda1f29a29aece66b2c0354 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Mon, 11 Apr 2022 02:10:25 +0500 Subject: [PATCH 059/350] GCP MYSQL Latest Version Plugin --- exports.js | 1 + plugins/google/sql/mysqlLatestVersion.js | 74 +++++++++++ plugins/google/sql/mysqlLatestVersion.spec.js | 123 ++++++++++++++++++ 3 files changed, 198 insertions(+) create mode 100644 plugins/google/sql/mysqlLatestVersion.js create mode 100644 plugins/google/sql/mysqlLatestVersion.spec.js diff --git a/exports.js b/exports.js index 36d4be0d16..8a7d22d7ed 100644 --- a/exports.js +++ b/exports.js @@ -903,6 +903,7 @@ module.exports = { 'storageAutoIncreaseEnabled' : require(__dirname + '/plugins/google/sql/storageAutoIncreaseEnabled.js'), 'serverCertificateRotation' : require(__dirname + '/plugins/google/sql/serverCertificateRotation.js'), 'sqlCMKEncryption' : require(__dirname + '/plugins/google/sql/sqlCMKEncryption.js'), + 'mysqlLatestVersion' : require(__dirname + '/plugins/google/sql/mysqlLatestVersion.js'), 'bucketVersioning' : require(__dirname + '/plugins/google/storage/bucketVersioning.js'), 'bucketLogging' : require(__dirname + '/plugins/google/storage/bucketLogging.js'), diff --git a/plugins/google/sql/mysqlLatestVersion.js b/plugins/google/sql/mysqlLatestVersion.js new file mode 100644 index 0000000000..9ad01bc741 --- /dev/null +++ b/plugins/google/sql/mysqlLatestVersion.js @@ -0,0 +1,74 @@ +var async = require('async'); +var helpers = require('../../../helpers/google'); + +module.exports = { + title: 'MySQL Latest Version', + category: 'SQL', + domain: 'Databases', + description: 'Ensure that MySQL database servers are using the latest major version of MySQL database.', + more_info: 'To make use of the latest database features and benefit from enhanced performance and security, make sure that your MySQL database instances are using the latest major version of MySQL.', + link: 'https://cloud.google.com/sql/docs/mysql/db-versions', + recommended_action: 'Ensure that all your MySQL database instances are using the latest MYSQL database version.', + apis: ['instances:sql:list', 'projects:get'], + + 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) { + helpers.addResult(results, 3, + 'Unable to query for projects: ' + helpers.addError(projects), 'global', null, null, projects.err); + return callback(null, results, source); + } + + let project = projects.data[0].name; + + const latestMySQLVersion = 8.0; + + async.each(regions.instances.sql, function(region, rcb){ + let sqlInstances = helpers.addSource( + cache, source, ['instances', 'sql', 'list', region]); + + if (!sqlInstances) return rcb(); + + if (sqlInstances.err || !sqlInstances.data) { + helpers.addResult(results, 3, 'Unable to query SQL instances: ' + helpers.addError(sqlInstances), region); + return rcb(); + } + + if (!sqlInstances.data.length) { + helpers.addResult(results, 0, 'No SQL instances found', region); + return rcb(); + } + + sqlInstances.data.forEach(sqlInstance => { + if (sqlInstance.instanceType && sqlInstance.instanceType.toUpperCase() === 'READ_REPLICA_INSTANCE') return; + + let resource = helpers.createResourceName('instances', sqlInstance.name, project); + + if (sqlInstance.databaseVersion && !sqlInstance.databaseVersion.toLowerCase().includes('mysql')) { + helpers.addResult(results, 0, + 'SQL instance database type is not of MySQL type', region, resource); + return; + } + + if (sqlInstance.databaseVersion && parseFloat(sqlInstance.databaseVersion.split('MYSQL_')[1].replace('_', '.')) >= latestMySQLVersion) { + helpers.addResult(results, 0, + `SQL instance is using MySQL major version ${sqlInstance.databaseVersion} which is the latest version`, region, resource); + } else { + helpers.addResult(results, 2, + `SQL instance is using MySQL major version ${sqlInstance.databaseVersion} which is not the latest version`, region, resource); + } + }); + + rcb(); + }, function(){ + // Global checking goes here + callback(null, results, source); + }); + } +}; diff --git a/plugins/google/sql/mysqlLatestVersion.spec.js b/plugins/google/sql/mysqlLatestVersion.spec.js new file mode 100644 index 0000000000..5bd0e01aae --- /dev/null +++ b/plugins/google/sql/mysqlLatestVersion.spec.js @@ -0,0 +1,123 @@ +var assert = require('assert'); +var expect = require('chai').expect; +var plugin = require('./mysqlLatestVersion'); + +const createCache = (err, data) => { + return { + instances: { + sql: { + list: { + 'global': { + err: err, + data: data + } + } + } + }, + projects: { + get: { + 'global': { + data: [{ name: 'test-project' }] + } + } + } + } +}; + +describe('mysqlLatestVersion', function () { + describe('run', function () { + it('should give unknown result if a sql instance error is passed or no data is present', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('Unable to query SQL instances'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + ['error'], + null, + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if no sql instances are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No SQL instances found'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [], + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if sql instance database type is not of MySQL type', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('SQL instance database type is not of MySQL type'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [{ + name: "testing-instance", + databaseVersion: "POSTGRES_13", + }], + ); + + plugin.run(cache, {}, callback); + }); + it('should give passing result if sql instance has the latest MySQL major version', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('which is the latest'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [{ + instanceType: "CLOUD_SQL_INSTANCE", + name: "testing-instance", + databaseVersion: "MYSQL_8_2" + }], + ); + + plugin.run(cache, {}, callback); + }); + it('should give failing result if sql instance does not have the latest MySQL major version', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('which is not the latest version'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [{ + instanceType: "CLOUD_SQL_INSTANCE", + name: "testing-instance", + databaseVersion: "MYSQL_5_7", + }], + ); + + plugin.run(cache, {}, callback); + }); + }) +}) \ No newline at end of file From 476ce2c9ee028b7e3d883b0cf8bbab066441fb49 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Mon, 11 Apr 2022 02:21:51 +0500 Subject: [PATCH 060/350] Updated messages --- plugins/azure/keyvaults/checkSecretsExpiry.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/azure/keyvaults/checkSecretsExpiry.js b/plugins/azure/keyvaults/checkSecretsExpiry.js index 6ee5a07602..a2d36fea75 100644 --- a/plugins/azure/keyvaults/checkSecretsExpiry.js +++ b/plugins/azure/keyvaults/checkSecretsExpiry.js @@ -2,13 +2,13 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); module.exports = { - title: 'Key Expiration Enabled', + title: 'Secret Expiration Enabled', category: 'Key Vaults', domain: 'Identity and Access Management', - description: 'Ensure that all Keys in Azure Key Vault have an expiry time set.', - more_info: 'Setting an expiry time on all keys forces key rotation and removes unused and forgotten keys from being used.', + description: 'Ensures that all secrets in Azure Key Vault have an expiry time set.', + more_info: 'Setting an expiry time on all secrets forces secret rotation and removes unused and forgotten secrets from being used.', recommended_action: 'Ensure each Key Vault has an expiry time set that provides for sufficient rotation.', - link: 'https://docs.microsoft.com/en-us/azure/key-vault/about-keys-secrets-and-certificates', + link: 'https://docs.microsoft.com/en-us/azure/secret-vault/about-secrets-secrets-and-certificates', apis: ['vaults:list', 'vaults:getSecrets'], run: function(cache, settings, callback) { @@ -52,10 +52,10 @@ module.exports = { } else if (attributes.expiry) { if (new Date(Date.now()) < new Date(attributes.expiry)) { helpers.addResult(results, 0, - 'Expiry date is set for the secret and is within the set expiry period', location, secretId); + 'Expiry date is set for the secret and date is not yet reached', location, secretId); } else { helpers.addResult(results, 2, - 'Expiry date is set for the secret and is greater than the set expiry period', location, secretId); + 'Expiry date is set for the secret and date has been reached', location, secretId); } } else { helpers.addResult(results, 2, From 01225fbf53ab1f2253a267402f0c4f6fb0dedfb4 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Mon, 11 Apr 2022 02:37:31 +0500 Subject: [PATCH 061/350] GCP PostgreSQL Latest Version Plugin --- exports.js | 2 + plugins/google/sql/postgresqlLatestVersion.js | 75 +++++++++++ .../sql/postgresqlLatestVersion.spec.js | 123 ++++++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 plugins/google/sql/postgresqlLatestVersion.js create mode 100644 plugins/google/sql/postgresqlLatestVersion.spec.js diff --git a/exports.js b/exports.js index 36d4be0d16..014ef7dcb8 100644 --- a/exports.js +++ b/exports.js @@ -903,6 +903,8 @@ module.exports = { 'storageAutoIncreaseEnabled' : require(__dirname + '/plugins/google/sql/storageAutoIncreaseEnabled.js'), 'serverCertificateRotation' : require(__dirname + '/plugins/google/sql/serverCertificateRotation.js'), 'sqlCMKEncryption' : require(__dirname + '/plugins/google/sql/sqlCMKEncryption.js'), + 'postgresqlLatestVersion' : require(__dirname + '/plugins/google/sql/postgresqlLatestVersion.js'), + 'bucketVersioning' : require(__dirname + '/plugins/google/storage/bucketVersioning.js'), 'bucketLogging' : require(__dirname + '/plugins/google/storage/bucketLogging.js'), diff --git a/plugins/google/sql/postgresqlLatestVersion.js b/plugins/google/sql/postgresqlLatestVersion.js new file mode 100644 index 0000000000..6bc4e6f556 --- /dev/null +++ b/plugins/google/sql/postgresqlLatestVersion.js @@ -0,0 +1,75 @@ +var async = require('async'); +var helpers = require('../../../helpers/google'); + +module.exports = { + title: 'PostgreSQL Latest Version', + category: 'SQL', + domain: 'Databases', + description: 'Ensure that PostgreSQL database servers are using the latest major version of PostgreSQL database.', + more_info: 'To make use of the latest database features and benefit from enhanced performance and security, make sure that your PostgreSQL database instances are using the latest major version of PostgreSQL.', + link: 'https://cloud.google.com/sql/docs/postgres/db-versions', + recommended_action: 'Ensure that all your PostgreSQL database instances are using the latest PostgreSQL database version.', + apis: ['instances:sql:list', 'projects:get'], + + 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) { + helpers.addResult(results, 3, + 'Unable to query for projects: ' + helpers.addError(projects), 'global', null, null, projects.err); + return callback(null, results, source); + } + + let project = projects.data[0].name; + + const latestPostgreSQLVersion = 14; + + async.each(regions.instances.sql, function(region, rcb){ + let sqlInstances = helpers.addSource( + cache, source, ['instances', 'sql', 'list', region]); + + if (!sqlInstances) return rcb(); + + if (sqlInstances.err || !sqlInstances.data) { + helpers.addResult(results, 3, 'Unable to query SQL instances: ' + helpers.addError(sqlInstances), region); + return rcb(); + } + + if (!sqlInstances.data.length) { + helpers.addResult(results, 0, 'No SQL instances found', region); + return rcb(); + } + + sqlInstances.data.forEach(sqlInstance => { + if (sqlInstance.instanceType && sqlInstance.instanceType.toUpperCase() === 'READ_REPLICA_INSTANCE') return; + + let resource = helpers.createResourceName('instances', sqlInstance.name, project); + + if (sqlInstance.databaseVersion && !sqlInstance.databaseVersion.toUpperCase().startsWith('POSTGRES')) { + helpers.addResult(results, 0, + 'SQL instance database type is not of POSTGRES type', region, resource); + return; + } + + if (sqlInstance.databaseVersion && parseInt(sqlInstance.databaseVersion.toUpperCase().split('POSTGRES_')[1]) >= latestPostgreSQLVersion) { + helpers.addResult(results, 0, + `SQL instance is using Postgres major version ${sqlInstance.databaseVersion} which is the latest version`, region, resource); + } else { + helpers.addResult(results, 2, + `SQL instance is using Postgres major version ${sqlInstance.databaseVersion} which is not the latest version`, region, resource); + } + }); + + rcb(); + }, function(){ + // Global checking goes here + callback(null, results, source); + }); + } +}; + diff --git a/plugins/google/sql/postgresqlLatestVersion.spec.js b/plugins/google/sql/postgresqlLatestVersion.spec.js new file mode 100644 index 0000000000..06c8a247ac --- /dev/null +++ b/plugins/google/sql/postgresqlLatestVersion.spec.js @@ -0,0 +1,123 @@ +var assert = require('assert'); +var expect = require('chai').expect; +var plugin = require('./postgresqlLatestVersion'); + +const createCache = (err, data) => { + return { + instances: { + sql: { + list: { + 'global': { + err: err, + data: data + } + } + } + }, + projects: { + get: { + 'global': { + data: [{ name: 'test-project' }] + } + } + } + } +}; + +describe('postgresqlLatestVersion', function () { + describe('run', function () { + it('should give unknown result if a sql instance error is passed or no data is present', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('Unable to query SQL instances'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + ['error'], + null, + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if no sql instances are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No SQL instances found'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [], + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if sql instance database type is not of POSTGRES type', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('SQL instance database type is not of POSTGRES type'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [{ + name: "testing-instance", + databaseVersion: "MYSQL_5_7", + }], + ); + + plugin.run(cache, {}, callback); + }); + it('should give passing result if sql instance has the latest postgreSQL major version', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('which is the latest'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [{ + instanceType: "CLOUD_SQL_INSTANCE", + name: "testing-instance", + databaseVersion: "POSTGRES_14" + }], + ); + + plugin.run(cache, {}, callback); + }); + it('should give failing result if sql instance does not have the latest PostgreSQL major version', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('which is not the latest version'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [{ + instanceType: "CLOUD_SQL_INSTANCE", + name: "testing-instance", + databaseVersion: "POSTGRES_11", + }], + ); + + plugin.run(cache, {}, callback); + }); + }) +}) From 424bb15520447e326d7c5a0cde6b83c270b02317 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Tue, 12 Apr 2022 13:51:57 +0500 Subject: [PATCH 062/350] Refactored plugin and tests --- .../keyvaults/checkEncryptionKeysExpiry.js | 22 +-- .../checkEncryptionKeysExpiry.spec.js | 139 ++++++++++++------ 2 files changed, 100 insertions(+), 61 deletions(-) diff --git a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js b/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js index 9283849d73..326b1a2ed4 100644 --- a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js +++ b/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js @@ -10,20 +10,11 @@ module.exports = { recommended_action: 'Ensure each Key Vault has an expiry time set that provides for sufficient rotation.', link: 'https://docs.microsoft.com/en-us/azure/key-vault/about-keys-secrets-and-certificates', apis: ['vaults:list', 'vaults:getKeys'], - settings: { - encryption_keys_expiry_period: { - name: 'Key Vault Keys Expiration Period', - description: 'The period of time in days for a key expiration.', - regex: '^(?:36[0-5]|3[0-5][0-9]|[12][0-9][0-9]|[1-9][0-9]|[1-9])$', - default: 30 - } - }, run: function(cache, settings, callback) { var results = []; var source = {}; var locations = helpers.locations(settings.govcloud); - var encryption_keys_expiry_period = parseInt(settings.encryption_keys_expiry_period || this.settings.encryption_keys_expiry_period.default); async.each(locations.vaults, function(location, rcb) { var vaults = helpers.addSource(cache, source, @@ -50,22 +41,21 @@ module.exports = { } else if (!keys.data.length) { helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); } else { - keys.data.forEach(function(key){ + keys.data.forEach(function(key) { var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); var keyId = `${vault.id}/keys/${keyName}`; - if (key.attributes) { - let expiryPeriodInDays = helpers.daysBetween(new Date(), key.attributes.expires); - if (expiryPeriodInDays < encryption_keys_expiry_period) { + if (key.attributes && key.attributes.expires) { + if (new Date(Date.now()) < new Date(key.attributes.expires)) { helpers.addResult(results, 0, - 'Key Vault encryption keys expiration is within the set expiry period', location, keyId); + 'Key expiry date is not yet reached', location, keyId); } else { helpers.addResult(results, 2, - 'Key Vault encryption keys expiration greater then the set expiry period', location, keyId); + 'Key has reached its expiry date', location, keyId); } } else { helpers.addResult(results, 2, - 'Key Vault encryption keys expiration is not enabled', location, keyId); + 'Key expiration is not enabled', location, keyId); } }); } diff --git a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js b/plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js index 7d864d43eb..a174d19bd8 100644 --- a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js +++ b/plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js @@ -1,42 +1,86 @@ -var assert = require('assert'); var expect = require('chai').expect; -var auth = require('./secretExpirationEnabled'); +var auth = require('./checkEncryptionKeysExpiry'); const listKeyVaults = [ { - "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", - "name": "testvault", - "type": "Microsoft.KeyVault/vaults", - "location": "eastus", - "tags": {}, - "sku": { - "family": "A", - "name": "Standard" + id: '/subscriptions/dce7d7as-ebf6-437f-a3b0-28fc0d22111e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/nauman-test', + name: 'nauman-test', + type: 'Microsoft.KeyVault/vaults', + location: 'eastus', + tags: { owner: 'kubernetes' }, + sku: { family: 'A', name: 'Standard' }, + tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', + accessPolicies: [ + { + tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', + objectId: 'b4062000-c33b-448b-817e-fa0f17bef4b9', + permissions: { + keys: ['Get', 'List'], + secrets: ['Get', 'List'], + certificates: ['Get', 'List'] + } + } + ], + enableSoftDelete: true, + softDeleteRetentionInDays: 7, + enableRbacAuthorization: false, + vaultUri: 'https://nauman-test.vault.azure.net/', + provisioningState: 'Succeeded' + } + ]; + + const getKeys = [ + { + "attributes": { + "created": "2022-04-10T17:57:43+00:00", + "enabled": true, + "expires": null, + "notBefore": null, + "recoveryLevel": "CustomizedRecoverable+Purgeable", + "updated": "2022-04-10T17:57:43+00:00" + }, + "kid": "https://nauman-test.vault.azure.net/keys/nauman-test", + "managed": null, + "name": "nauman-test", + "tags": { + "hello": "world" } - } -]; - -const getKeys = [ + }, { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": true, - "exp": 1635448252, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] + "attributes": { + "created": "2022-04-10T17:57:43+00:00", + "enabled": true, + "expires": "2022-08-31T17:52:06+00:00", + "notBefore": null, + "recoveryLevel": "CustomizedRecoverable+Purgeable", + "updated": "2022-04-10T17:57:43+00:00" + }, + "kid": "https://nauman-test.vault.azure.net/keys/nauman-test", + "managed": null, + "name": "nauman-test", + "tags": { + "hello": "world" + } + }, + { + "attributes": { + "created": "2022-04-10T17:57:43+00:00", + "enabled": true, + "expires": "2022-04-01T17:52:06+00:00", + "notBefore": null, + "recoveryLevel": "CustomizedRecoverable+Purgeable", + "updated": "2022-04-10T17:57:43+00:00" + }, + "kid": "https://nauman-test.vault.azure.net/keys/nauman-test", + "managed": null, + "name": "nauman-test", + "tags": { + "hello": "world" } } ]; -const createCache = (err, list, get) => { +const createCache = (err, list, keys) => { return { vaults: { list: { @@ -45,16 +89,21 @@ const createCache = (err, list, get) => { data: list } }, - getSecrets: { - 'eastus': get + getKeys: { + 'eastus': { + '/subscriptions/dce7d7as-ebf6-437f-a3b0-28fc0d22111e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/nauman-test': { + err: err, + data: keys + } + } } } } }; -describe('secretExpirationEnabled', function() { +describe('checkEncryptionKeysExpiry', function() { describe('run', function() { - it('should give passing result if no secrets found', function(done) { + it('should give passing result if no keys found', function(done) { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); @@ -66,40 +115,40 @@ describe('secretExpirationEnabled', function() { auth.run(createCache(null, [], {}), {}, callback); }); - it('should give failing result if expiration is not set on secrets', function(done) { + it('should give failing result if expiration is not set on keys', 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('Expiry date is not set for the secret'); + expect(results[0].message).to.include('Key expiration is not enabled'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, listKeyVaults, getKeys[0]), {}, callback); + auth.run(createCache(null, [listKeyVaults[0]], [getKeys[0]]), {}, callback); }); - it('should give passing result if expiration is set on keys', function(done) { + it('should give passing result if expiry date is not yet reached', 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('Expiry date is set for the secret'); + expect(results[0].message).to.include('Key expiry date is not yet reached'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, listKeyVaults, getKeys[0]), {}, callback); + auth.run(createCache(null, listKeyVaults, [getKeys[1]]), {}, callback); }); - it('should give passing result if key is disabled', function(done) { + it('should give failing results if the key has reached its expiry date', 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('The secret is disabled'); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Key has reached its expiry date'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, listKeyVaults, getKeys[0]), {}, callback); - }) - }) + auth.run(createCache(null, listKeyVaults, [getKeys[2]]), {}, callback); + }); + }); }); From f41973afec5fdabc29ca754d8a2e74704c9c84bd Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 14 Apr 2022 15:10:25 +0500 Subject: [PATCH 063/350] Updated Versions For Lambda And Kubernetes Plugins --- helpers/aws/regions.js | 25 +++++++++++---------- plugins/aws/eks/eksKubernetesVersion.js | 2 +- plugins/aws/eks/eksLatestPlatformVersion.js | 9 ++++---- plugins/aws/lambda/lambdaOldRuntimes.js | 7 +++--- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index 52d8f9f211..0e891c35b9 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -53,7 +53,7 @@ module.exports = { configservice: [...regions, ...newRegions], dax: [...regions, ...newRegions], devopsguru: ['us-east-1', 'us-east-2', 'eu-west-1', 'us-west-2', 'ap-northeast-1', 'eu-central-1', - 'ap-southeast-1', 'ap-southeast-2'], + 'ap-southeast-1', 'ap-southeast-2', 'eu-north-1'], dynamodb: [...regions, ...newRegions], docdb: ['us-east-1', 'us-east-2', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', @@ -101,7 +101,7 @@ module.exports = { transfer: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'eu-south-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'ap-east-1', - 'sa-east-1', 'me-south-1', 'af-south-1'], + 'sa-east-1', 'me-south-1', 'af-south-1', 'ap-northeast-3'], lambda: [...regions, ...newRegions], mwaa: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'ap-south-1', 'eu-north-1', 'eu-central-1', 'ap-southeast-2', 'ap-southeast-1', 'ap-northeast-2', 'ap-northeast-1', 'ca-central-1', 'sa-east-1'], @@ -137,7 +137,7 @@ module.exports = { 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1'], kafka: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'eu-south-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', - 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1'], + 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1', 'af-south-1'], kendra: ['us-east-1', 'us-east-2', 'us-west-2', 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'eu-west-1'], proton: ['us-east-1', 'us-east-2', 'us-west-2', 'ap-northeast-1', 'eu-west-1'], customerprofiles: ['us-east-1', 'us-west-2', 'eu-west-2', 'ca-central-1', 'eu-central-1', @@ -148,8 +148,7 @@ module.exports = { finspace: ['us-east-1', 'us-east-2', 'us-west-2', 'ca-central-1','eu-west-1'], codepipeline: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ap-east-1', 'ap-south-1', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'eu-south-1', 'ap-northeast-1', - 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'ap-east-1', - 'sa-east-1'], + 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'sa-east-1'], codeartifact: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'eu-south-1', 'ap-northeast-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1'], @@ -162,14 +161,16 @@ module.exports = { 'eu-west-3', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'af-south-1' ], translate: [ - 'us-east-1', 'us-east-2', 'us-west-2', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'ap-northeast-2' + 'us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'ap-northeast-2', + 'ap-east-1', 'ap-south-1', 'ap-northeast-1', 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1','eu-west-3', + 'eu-north-1' ], databrew: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'eu-south-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'af-south-1' ], managedblockchain: ['us-east-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-northeast-1', 'eu-west-1', 'eu-west-2'], - connect: ['us-east-1', 'us-west-2', 'eu-west-2', 'ca-central-1', 'eu-central-1', + connect: ['us-east-1', 'us-west-2', 'eu-west-2', 'ca-central-1', 'eu-central-1', 'af-south-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'ap-northeast-2'], apprunner: ['us-east-1', 'us-west-2', 'us-west-2', 'eu-west-1','ap-northeast-1'], healthlake: ['us-east-1', 'us-east-2', 'eu-west-2'], @@ -178,10 +179,10 @@ module.exports = { 'ap-northeast-1', 'eu-central-1', 'eu-west-1'], location: [ 'us-east-1', 'us-east-2', 'us-west-2', 'eu-central-1', 'eu-west-1', 'eu-north-1', - 'ap-northeast-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1' + 'ap-northeast-1', 'ap-southeast-1', 'ap-southeast-2' ], - lookoutvision: ['us-east-1', 'us-east-2', 'ap-northeast-1', 'ap-northeast-2', 'eu-central-1', 'eu-west-1'], - lookoutmetrics: ['us-east-1', 'us-east-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'eu-central-1', + lookoutvision: ['us-east-1', 'us-east-2', 'us-west-2', 'ap-northeast-1', 'ap-northeast-2', 'eu-central-1', 'eu-west-1'], + lookoutmetrics: ['us-east-1', 'us-east-2', 'us-west-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'eu-central-1', 'eu-west-1', 'eu-north-1'], forecastservice: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-central-1', 'eu-west-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1'], @@ -190,8 +191,8 @@ module.exports = { fsx: regions, wisdom: ['us-east-1', 'us-west-2', 'eu-west-2', 'eu-central-1', 'ap-northeast-1', 'ap-southeast-2'], voiceid: ['us-east-1', 'us-west-2', 'eu-west-2', 'eu-central-1', 'ap-southeast-1', 'ap-northeast-1', 'ap-southeast-2'], - appmesh: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', - 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', + appmesh: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'af-south-1', 'ca-central-1', 'eu-central-1', + 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', 'eu-south-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1'], frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'] }; diff --git a/plugins/aws/eks/eksKubernetesVersion.js b/plugins/aws/eks/eksKubernetesVersion.js index d3aadadf19..6f8050ed55 100644 --- a/plugins/aws/eks/eksKubernetesVersion.js +++ b/plugins/aws/eks/eksKubernetesVersion.js @@ -29,7 +29,7 @@ module.exports = { '1.15': '2021-05-03', '1.16': '2021-09-27', '1.17': '2021-11-02', - '1.18': '2022-12-02' + '1.18': '2022-03-31' }; var outdatedVersions = { diff --git a/plugins/aws/eks/eksLatestPlatformVersion.js b/plugins/aws/eks/eksLatestPlatformVersion.js index 704279de9e..db0ddc16e7 100644 --- a/plugins/aws/eks/eksLatestPlatformVersion.js +++ b/plugins/aws/eks/eksLatestPlatformVersion.js @@ -22,10 +22,11 @@ module.exports = { var accountId = helpers.addSource(cache, source, ['sts', 'getCallerIdentity', acctRegion, 'data']); var latestVersions = { - '1.21' : 4, - '1.20' : 3, - '1.19': 7, - '1.18': 9, + '1.22' : 1, + '1.21' : 6, + '1.20' : 5, + '1.19': 9, + '1.18': 11, }; var deprecatedVersions = { diff --git a/plugins/aws/lambda/lambdaOldRuntimes.js b/plugins/aws/lambda/lambdaOldRuntimes.js index 83265d68cb..dd6352d877 100644 --- a/plugins/aws/lambda/lambdaOldRuntimes.js +++ b/plugins/aws/lambda/lambdaOldRuntimes.js @@ -18,8 +18,8 @@ module.exports = { var deprecatedRuntimes = [ { 'id':'nodejs', 'name': 'Node.js 0.10', 'endOfLifeDate': '2016-10-31' }, - { 'id':'nodejs4.3', 'name': 'Node.js 4.3', 'endOfLifeDate': '2018-04-30' }, - { 'id':'nodejs4.3-edge', 'name': 'Node.js 4.3', 'endOfLifeDate': '2018-04-30' }, + { 'id':'nodejs4.3', 'name': 'Node.js 4.3', 'endOfLifeDate': '2020-04-06' }, + { 'id':'nodejs4.3-edge', 'name': 'Node.js 4.3', 'endOfLifeDate': '2019-04-30' }, { 'id':'nodejs6.10', 'name': 'Node.js 6.10', 'endOfLifeDate': '2019-08-12' }, { 'id':'nodejs8.10', 'name': 'Node.js 8.10', 'endOfLifeDate': '2020-03-06' }, { 'id':'nodejs10.x', 'name': 'Node.js 10.x', 'endOfLifeDate': '2022-02-14' }, @@ -27,8 +27,7 @@ module.exports = { { 'id':'dotnetcore2.0', 'name': '.Net Core 2.0', 'endOfLifeDate': '2018-10-01' }, { 'id':'dotnetcore1.0', 'name': '.Net Core 1.0', 'endOfLifeDate': '2019-06-27' }, { 'id':'python2.7', 'name': 'Python 2.7', 'endOfLifeDate': '2022-02-14' }, - { 'id':'python3.5', 'name': 'Python 3.5', 'endOfLifeDate': '2020-09-13' }, - { 'id':'ruby2.5', 'name': 'Ruby 2.5', 'endOfLifeDate': '2022-02-14' }, + { 'id':'ruby2.5', 'name': 'Ruby 2.5', 'endOfLifeDate': '2022-03-31' }, ]; async.each(regions.lambda, function(region, rcb){ From 49d94c4cea219c79b026d8d988885d8642afd91d Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 14 Apr 2022 15:18:45 +0500 Subject: [PATCH 064/350] added some changes --- plugins/aws/eks/eksLatestPlatformVersion.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/eks/eksLatestPlatformVersion.spec.js b/plugins/aws/eks/eksLatestPlatformVersion.spec.js index 6cf76b4557..58efa5f09e 100644 --- a/plugins/aws/eks/eksLatestPlatformVersion.spec.js +++ b/plugins/aws/eks/eksLatestPlatformVersion.spec.js @@ -85,7 +85,7 @@ describe('eksLatestPlatformVersion', function () { "name": "das", "arn": "arn:aws:eks:us-east-1:012345678911:cluster/das", "version": "1.21", - "platformVersion": "eks.4", + "platformVersion": "eks.6", } } ); From c8148e0262f5c233818ad019afb70b53fe5805e1 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Fri, 15 Apr 2022 21:14:42 +0500 Subject: [PATCH 065/350] Added Remediations To Open Ports --- .../aws/ec2/openOracleAutoDataWarehouse.js | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/plugins/aws/ec2/openOracleAutoDataWarehouse.js b/plugins/aws/ec2/openOracleAutoDataWarehouse.js index c662efaff0..a4f3f8a3b4 100644 --- a/plugins/aws/ec2/openOracleAutoDataWarehouse.js +++ b/plugins/aws/ec2/openOracleAutoDataWarehouse.js @@ -20,6 +20,32 @@ module.exports = { default: 'false', } }, + remediation_description: 'The impacted security group rule will be deleted if no input is provided. Otherwise, any input will replace the open CIDR rule.', + remediation_min_version: '202006020730', + apis_remediate: ['EC2:describeSecurityGroups'], + remediation_inputs: { + openOracleAutoDataWarehouseReplacementIpAddress: { + name: '(Optional) Replacement IPv4 CIDR', + description: 'Comma separated list of IPv4 CIDR block used to replace the open IP rule', + regex: '^(([0-9]{1,3}\\.){3}[0-9]{1,3}(\\/([0-9]|[1-2][0-9]|3[0-2])),)*([0-9]{1,3}\\.){3}[0-9]{1,3}(\\/([0-9]|[1-2][0-9]|3[0-2]))$', + required: false + }, + openOracleAutoDataWarehouseReplacementIpv6Address: { + name: '(Optional) Replacement IPv6 CIDR', + description: 'Comma separated list of IPv6 CIDR block used to replace the open IP rule', + regex: '^s*(((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])),)*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))$', + required: false + } + }, + actions: { + remediate: ['EC2:authorizeSecurityGroupIngress','EC2:revokeSecurityGroupIngress'], + rollback: ['EC2:authorizeSecurityGroupIngress'] + }, + permissions: { + remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], + rollback:['ec2:AuthorizeSecurityGroupIngress'] + }, + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], run: function(cache, settings, callback) { var config = { @@ -61,5 +87,24 @@ module.exports = { }, function(){ callback(null, results, source); }); + }, + remediate: function(config, cache, settings, resource, callback) { + var remediation_file = settings.remediation_file; + var putCall = this.actions.remediate; + var pluginName = 'openOracleAutoDataWarehouse'; + var protocol = 'tcp'; + var port = 1522; + + helpers.remediateOpenPorts(putCall, pluginName, protocol, port, config, cache, settings, resource, remediation_file, function(error, action) { + if (error && (error.length || Object.keys(error).length)) { + remediation_file['post_remediate']['actions'][pluginName]['error'] = error; + settings.remediation_file = remediation_file; + return callback(error, null); + } else { + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + settings.remediation_file = remediation_file; + return callback(null, action); + } + }); } }; \ No newline at end of file From c309fe84e128757a3b5b505d5ea219053daf0c9f Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 17 Apr 2022 16:34:08 +0500 Subject: [PATCH 066/350] SAAS-4238: Added rsaCertificateKeySize plugin and spec --- exports.js | 1 + .../keyvaults/allowedCertificateKeyTypes.js | 70 ++++++++ .../allowedCertificateKeyTypes.spec.js | 160 ++++++++++++++++++ 3 files changed, 231 insertions(+) create mode 100644 plugins/azure/keyvaults/allowedCertificateKeyTypes.js create mode 100644 plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..06dfdf7124 100644 --- a/exports.js +++ b/exports.js @@ -755,6 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), + 'allowedCertificateKeyTypes' : require(__dirname + '/plugins/azure/keyvaults/allowedCertificateKeyTypes.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js new file mode 100644 index 0000000000..6c6b294e60 --- /dev/null +++ b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js @@ -0,0 +1,70 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Allowed Certificates Key Types', + category: 'Key Vaults', + domain: 'Identity and Access Management', + description: 'Ensures that Microsoft Azure Key Vault SSL certificates are using the allowed key types.', + more_info: 'Having the right key type set for your Azure Key Vault SSL certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', + recommended_action: 'Ensure that Key Vault SSL certificates are using the allowed key types.', + link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/certificate-access-control', + apis: ['vaults:list', 'vaults:getKeys'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.vaults, function(location, rcb) { + var vaults = helpers.addSource(cache, source, + ['vaults', 'list', location]); + + if (!vaults) return rcb(); + + if (vaults.err || !vaults.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); + return rcb(); + } + + if (!vaults.data.length) { + helpers.addResult(results, 0, 'No Key Vaults found', location); + return rcb(); + } + + vaults.data.forEach((vault) => { + var keys = helpers.addSource(cache, source, + ['vaults', 'getKeys', location, vault.id]); + + if (!keys || keys.err || !keys.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); + } else if (!keys.data.length) { + helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); + } else { + keys.data.forEach((key) => { + var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); + var keyId = `${vault.id}/keys/${keyName}`; + + if (key.attributes) { + let attributes = key.attributes; + if ((attributes.expires && attributes.expires !== null && attributes.expires !== '') || (attributes.exp && attributes.exp !== null && attributes.exp !== '')) { + helpers.addResult(results, 0, + 'Expiry date is set for the key', location, keyId); + } else { + helpers.addResult(results, 2, + 'Expiry date is not set for the key', location, keyId); + } + } else { + helpers.addResult(results, 2, + 'Expiry date is not set for the key', location, keyId); + } + }); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js new file mode 100644 index 0000000000..7d048cb2f5 --- /dev/null +++ b/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js @@ -0,0 +1,160 @@ +var expect = require('chai').expect; +var auth = require('./secretExpirationEnabled'); + +const listVaults = [ + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + }, + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + }, + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + } +]; + +const getKeys = [ + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "exp": null, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + }, + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "exp": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + }, + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": false, + "exp": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + } +]; + +const createCache = (err, list, get) => { + return { + vaults: { + list: { + 'eastus': { + err: err, + data: list + } + }, + getSecrets: { + 'eastus': get + } + } + } +}; + +describe('secretExpirationEnabled', function() { + describe('run', function() { + it('should give passing result if no secrets 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 Key Vaults found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [], {}), {}, callback); + }); + + it('should give failing result if expiration is not set on secrets', 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('Expiry date is not set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], getKeys[0]), {}, callback); + }); + + it('should give passing result if expiration is set on keys', 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('Expiry date is set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[1]], getKeys[1]), {}, callback); + }); + + it('should give passing result if key is disabled', 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('The secret is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[2]], getKeys[2]), {}, callback); + }) + }) +}); From 07d61b9b1161bb0644d38d00ac2c90f861991476 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 17 Apr 2022 16:39:42 +0500 Subject: [PATCH 067/350] SAAS-4239: Added accessAndManagePermissions plugin and spec --- exports.js | 1 + .../keyvaults/allowedCertificateKeyTypes.js | 70 ++++++++ .../allowedCertificateKeyTypes.spec.js | 160 ++++++++++++++++++ 3 files changed, 231 insertions(+) create mode 100644 plugins/azure/keyvaults/allowedCertificateKeyTypes.js create mode 100644 plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..06dfdf7124 100644 --- a/exports.js +++ b/exports.js @@ -755,6 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), + 'allowedCertificateKeyTypes' : require(__dirname + '/plugins/azure/keyvaults/allowedCertificateKeyTypes.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js new file mode 100644 index 0000000000..6c6b294e60 --- /dev/null +++ b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js @@ -0,0 +1,70 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Allowed Certificates Key Types', + category: 'Key Vaults', + domain: 'Identity and Access Management', + description: 'Ensures that Microsoft Azure Key Vault SSL certificates are using the allowed key types.', + more_info: 'Having the right key type set for your Azure Key Vault SSL certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', + recommended_action: 'Ensure that Key Vault SSL certificates are using the allowed key types.', + link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/certificate-access-control', + apis: ['vaults:list', 'vaults:getKeys'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.vaults, function(location, rcb) { + var vaults = helpers.addSource(cache, source, + ['vaults', 'list', location]); + + if (!vaults) return rcb(); + + if (vaults.err || !vaults.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); + return rcb(); + } + + if (!vaults.data.length) { + helpers.addResult(results, 0, 'No Key Vaults found', location); + return rcb(); + } + + vaults.data.forEach((vault) => { + var keys = helpers.addSource(cache, source, + ['vaults', 'getKeys', location, vault.id]); + + if (!keys || keys.err || !keys.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); + } else if (!keys.data.length) { + helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); + } else { + keys.data.forEach((key) => { + var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); + var keyId = `${vault.id}/keys/${keyName}`; + + if (key.attributes) { + let attributes = key.attributes; + if ((attributes.expires && attributes.expires !== null && attributes.expires !== '') || (attributes.exp && attributes.exp !== null && attributes.exp !== '')) { + helpers.addResult(results, 0, + 'Expiry date is set for the key', location, keyId); + } else { + helpers.addResult(results, 2, + 'Expiry date is not set for the key', location, keyId); + } + } else { + helpers.addResult(results, 2, + 'Expiry date is not set for the key', location, keyId); + } + }); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js new file mode 100644 index 0000000000..7d048cb2f5 --- /dev/null +++ b/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js @@ -0,0 +1,160 @@ +var expect = require('chai').expect; +var auth = require('./secretExpirationEnabled'); + +const listVaults = [ + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + }, + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + }, + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + } +]; + +const getKeys = [ + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "exp": null, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + }, + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "exp": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + }, + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": false, + "exp": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + } +]; + +const createCache = (err, list, get) => { + return { + vaults: { + list: { + 'eastus': { + err: err, + data: list + } + }, + getSecrets: { + 'eastus': get + } + } + } +}; + +describe('secretExpirationEnabled', function() { + describe('run', function() { + it('should give passing result if no secrets 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 Key Vaults found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [], {}), {}, callback); + }); + + it('should give failing result if expiration is not set on secrets', 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('Expiry date is not set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], getKeys[0]), {}, callback); + }); + + it('should give passing result if expiration is set on keys', 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('Expiry date is set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[1]], getKeys[1]), {}, callback); + }); + + it('should give passing result if key is disabled', 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('The secret is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[2]], getKeys[2]), {}, callback); + }) + }) +}); From 0e00afd449f2a23344c1cfd98a9a84cdb2905867 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 17 Apr 2022 16:42:23 +0500 Subject: [PATCH 068/350] SAAS-4240: Added sslCertificatesAutoRenewalPeriod plugin and spec --- exports.js | 1 + .../keyvaults/allowedCertificateKeyTypes.js | 70 ++++++++ .../allowedCertificateKeyTypes.spec.js | 160 ++++++++++++++++++ 3 files changed, 231 insertions(+) create mode 100644 plugins/azure/keyvaults/allowedCertificateKeyTypes.js create mode 100644 plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..06dfdf7124 100644 --- a/exports.js +++ b/exports.js @@ -755,6 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), + 'allowedCertificateKeyTypes' : require(__dirname + '/plugins/azure/keyvaults/allowedCertificateKeyTypes.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js new file mode 100644 index 0000000000..6c6b294e60 --- /dev/null +++ b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js @@ -0,0 +1,70 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Allowed Certificates Key Types', + category: 'Key Vaults', + domain: 'Identity and Access Management', + description: 'Ensures that Microsoft Azure Key Vault SSL certificates are using the allowed key types.', + more_info: 'Having the right key type set for your Azure Key Vault SSL certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', + recommended_action: 'Ensure that Key Vault SSL certificates are using the allowed key types.', + link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/certificate-access-control', + apis: ['vaults:list', 'vaults:getKeys'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.vaults, function(location, rcb) { + var vaults = helpers.addSource(cache, source, + ['vaults', 'list', location]); + + if (!vaults) return rcb(); + + if (vaults.err || !vaults.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); + return rcb(); + } + + if (!vaults.data.length) { + helpers.addResult(results, 0, 'No Key Vaults found', location); + return rcb(); + } + + vaults.data.forEach((vault) => { + var keys = helpers.addSource(cache, source, + ['vaults', 'getKeys', location, vault.id]); + + if (!keys || keys.err || !keys.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); + } else if (!keys.data.length) { + helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); + } else { + keys.data.forEach((key) => { + var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); + var keyId = `${vault.id}/keys/${keyName}`; + + if (key.attributes) { + let attributes = key.attributes; + if ((attributes.expires && attributes.expires !== null && attributes.expires !== '') || (attributes.exp && attributes.exp !== null && attributes.exp !== '')) { + helpers.addResult(results, 0, + 'Expiry date is set for the key', location, keyId); + } else { + helpers.addResult(results, 2, + 'Expiry date is not set for the key', location, keyId); + } + } else { + helpers.addResult(results, 2, + 'Expiry date is not set for the key', location, keyId); + } + }); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js new file mode 100644 index 0000000000..7d048cb2f5 --- /dev/null +++ b/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js @@ -0,0 +1,160 @@ +var expect = require('chai').expect; +var auth = require('./secretExpirationEnabled'); + +const listVaults = [ + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + }, + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + }, + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + } +]; + +const getKeys = [ + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "exp": null, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + }, + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "exp": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + }, + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": false, + "exp": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + } +]; + +const createCache = (err, list, get) => { + return { + vaults: { + list: { + 'eastus': { + err: err, + data: list + } + }, + getSecrets: { + 'eastus': get + } + } + } +}; + +describe('secretExpirationEnabled', function() { + describe('run', function() { + it('should give passing result if no secrets 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 Key Vaults found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [], {}), {}, callback); + }); + + it('should give failing result if expiration is not set on secrets', 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('Expiry date is not set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], getKeys[0]), {}, callback); + }); + + it('should give passing result if expiration is set on keys', 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('Expiry date is set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[1]], getKeys[1]), {}, callback); + }); + + it('should give passing result if key is disabled', 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('The secret is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[2]], getKeys[2]), {}, callback); + }) + }) +}); From 990c2ecd68aa96caf750e065491cabfe783e50f8 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 17 Apr 2022 16:47:56 +0500 Subject: [PATCH 069/350] SAAS-4241: Added cmkCreationForDatabaseTier plugin and spec --- exports.js | 1 + .../keyvaults/checkEncryptionKeysExpiry.js | 69 ++++++++ .../checkEncryptionKeysExpiry.spec.js | 154 ++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 plugins/azure/keyvaults/checkEncryptionKeysExpiry.js create mode 100644 plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..2ff7942db0 100644 --- a/exports.js +++ b/exports.js @@ -755,6 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), + 'checkEncryptionKeysExpiry' : require(__dirname + '/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js b/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js new file mode 100644 index 0000000000..326b1a2ed4 --- /dev/null +++ b/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js @@ -0,0 +1,69 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Key Expiration Enabled', + category: 'Key Vaults', + domain: 'Identity and Access Management', + description: 'Ensure that all Keys in Azure Key Vault have an expiry time set.', + more_info: 'Setting an expiry time on all keys forces key rotation and removes unused and forgotten keys from being used.', + recommended_action: 'Ensure each Key Vault has an expiry time set that provides for sufficient rotation.', + link: 'https://docs.microsoft.com/en-us/azure/key-vault/about-keys-secrets-and-certificates', + apis: ['vaults:list', 'vaults:getKeys'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.vaults, function(location, rcb) { + var vaults = helpers.addSource(cache, source, + ['vaults', 'list', location]); + + if (!vaults) return rcb(); + + if (vaults.err || !vaults.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); + return rcb(); + } + + if (!vaults.data.length) { + helpers.addResult(results, 0, 'No Key Vaults found', location); + return rcb(); + } + + vaults.data.forEach(function(vault){ + var keys = helpers.addSource(cache, source, + ['vaults', 'getKeys', location, vault.id]); + + if (!keys || keys.err || !keys.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); + } else if (!keys.data.length) { + helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); + } else { + keys.data.forEach(function(key) { + var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); + var keyId = `${vault.id}/keys/${keyName}`; + + if (key.attributes && key.attributes.expires) { + if (new Date(Date.now()) < new Date(key.attributes.expires)) { + helpers.addResult(results, 0, + 'Key expiry date is not yet reached', location, keyId); + } else { + helpers.addResult(results, 2, + 'Key has reached its expiry date', location, keyId); + } + } else { + helpers.addResult(results, 2, + 'Key expiration is not enabled', location, keyId); + } + }); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js b/plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js new file mode 100644 index 0000000000..a174d19bd8 --- /dev/null +++ b/plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js @@ -0,0 +1,154 @@ +var expect = require('chai').expect; +var auth = require('./checkEncryptionKeysExpiry'); + +const listKeyVaults = [ + { + id: '/subscriptions/dce7d7as-ebf6-437f-a3b0-28fc0d22111e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/nauman-test', + name: 'nauman-test', + type: 'Microsoft.KeyVault/vaults', + location: 'eastus', + tags: { owner: 'kubernetes' }, + sku: { family: 'A', name: 'Standard' }, + tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', + accessPolicies: [ + { + tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', + objectId: 'b4062000-c33b-448b-817e-fa0f17bef4b9', + permissions: { + keys: ['Get', 'List'], + secrets: ['Get', 'List'], + certificates: ['Get', 'List'] + } + } + ], + enableSoftDelete: true, + softDeleteRetentionInDays: 7, + enableRbacAuthorization: false, + vaultUri: 'https://nauman-test.vault.azure.net/', + provisioningState: 'Succeeded' + } + ]; + + const getKeys = [ + { + "attributes": { + "created": "2022-04-10T17:57:43+00:00", + "enabled": true, + "expires": null, + "notBefore": null, + "recoveryLevel": "CustomizedRecoverable+Purgeable", + "updated": "2022-04-10T17:57:43+00:00" + }, + "kid": "https://nauman-test.vault.azure.net/keys/nauman-test", + "managed": null, + "name": "nauman-test", + "tags": { + "hello": "world" + } + }, + { + "attributes": { + "created": "2022-04-10T17:57:43+00:00", + "enabled": true, + "expires": "2022-08-31T17:52:06+00:00", + "notBefore": null, + "recoveryLevel": "CustomizedRecoverable+Purgeable", + "updated": "2022-04-10T17:57:43+00:00" + }, + "kid": "https://nauman-test.vault.azure.net/keys/nauman-test", + "managed": null, + "name": "nauman-test", + "tags": { + "hello": "world" + } + }, + { + "attributes": { + "created": "2022-04-10T17:57:43+00:00", + "enabled": true, + "expires": "2022-04-01T17:52:06+00:00", + "notBefore": null, + "recoveryLevel": "CustomizedRecoverable+Purgeable", + "updated": "2022-04-10T17:57:43+00:00" + }, + "kid": "https://nauman-test.vault.azure.net/keys/nauman-test", + "managed": null, + "name": "nauman-test", + "tags": { + "hello": "world" + } + } +]; + +const createCache = (err, list, keys) => { + return { + vaults: { + list: { + 'eastus': { + err: err, + data: list + } + }, + getKeys: { + 'eastus': { + '/subscriptions/dce7d7as-ebf6-437f-a3b0-28fc0d22111e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/nauman-test': { + err: err, + data: keys + } + } + } + } + } +}; + +describe('checkEncryptionKeysExpiry', function() { + describe('run', function() { + it('should give passing result if no keys 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 Key Vaults found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [], {}), {}, callback); + }); + + it('should give failing result if expiration is not set on keys', 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('Key expiration is not enabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listKeyVaults[0]], [getKeys[0]]), {}, callback); + }); + + it('should give passing result if expiry date is not yet reached', 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('Key expiry date is not yet reached'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, listKeyVaults, [getKeys[1]]), {}, callback); + }); + + it('should give failing results if the key has reached its expiry date', 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('Key has reached its expiry date'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, listKeyVaults, [getKeys[2]]), {}, callback); + }); + }); +}); From 947075802fe27651553b9a8a602d861d34bae65d Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sun, 17 Apr 2022 23:53:01 +0500 Subject: [PATCH 070/350] Oracle - Specs fro Open Ports Plugins --- .../networking/openAllPortsProtocols.spec.js | 214 ++++++++++++ plugins/oracle/networking/openCIFS.spec.js | 309 +++++++++++++++++ plugins/oracle/networking/openDNS.spec.js | 308 +++++++++++++++++ plugins/oracle/networking/openDocker.spec.js | 315 ++++++++++++++++++ plugins/oracle/networking/openFTP.spec.js | 315 ++++++++++++++++++ .../networking/openHadoopNameNode.spec.js | 315 ++++++++++++++++++ .../openHadoopNameNodeWebUI.spec.js | 315 ++++++++++++++++++ plugins/oracle/networking/openKibana.spec.js | 308 +++++++++++++++++ plugins/oracle/networking/openMySQL.spec.js | 315 ++++++++++++++++++ plugins/oracle/networking/openNetBIOS.spec.js | 315 ++++++++++++++++++ plugins/oracle/networking/openOracle.spec.js | 308 +++++++++++++++++ .../openOracleAutoDataWarehouse.spec.js | 308 +++++++++++++++++ .../oracle/networking/openPostgreSQL.spec.js | 308 +++++++++++++++++ plugins/oracle/networking/openRDP.spec.js | 308 +++++++++++++++++ plugins/oracle/networking/openRPC.spec.js | 308 +++++++++++++++++ plugins/oracle/networking/openSMBoTCP.spec.js | 308 +++++++++++++++++ plugins/oracle/networking/openSMTP.spec.js | 308 +++++++++++++++++ .../oracle/networking/openSQLServer.spec.js | 308 +++++++++++++++++ plugins/oracle/networking/openSSH.spec.js | 294 ++++++++++++++++ plugins/oracle/networking/openSalt.spec.js | 315 ++++++++++++++++++ plugins/oracle/networking/openTelnet.spec.js | 294 ++++++++++++++++ .../oracle/networking/openVNCClient.spec.js | 294 ++++++++++++++++ .../oracle/networking/openVNCServer.spec.js | 294 ++++++++++++++++ 23 files changed, 6984 insertions(+) create mode 100644 plugins/oracle/networking/openAllPortsProtocols.spec.js create mode 100644 plugins/oracle/networking/openCIFS.spec.js create mode 100644 plugins/oracle/networking/openDNS.spec.js create mode 100644 plugins/oracle/networking/openDocker.spec.js create mode 100644 plugins/oracle/networking/openFTP.spec.js create mode 100644 plugins/oracle/networking/openHadoopNameNode.spec.js create mode 100644 plugins/oracle/networking/openHadoopNameNodeWebUI.spec.js create mode 100644 plugins/oracle/networking/openKibana.spec.js create mode 100644 plugins/oracle/networking/openMySQL.spec.js create mode 100644 plugins/oracle/networking/openNetBIOS.spec.js create mode 100644 plugins/oracle/networking/openOracle.spec.js create mode 100644 plugins/oracle/networking/openOracleAutoDataWarehouse.spec.js create mode 100644 plugins/oracle/networking/openPostgreSQL.spec.js create mode 100644 plugins/oracle/networking/openRDP.spec.js create mode 100644 plugins/oracle/networking/openRPC.spec.js create mode 100644 plugins/oracle/networking/openSMBoTCP.spec.js create mode 100644 plugins/oracle/networking/openSMTP.spec.js create mode 100644 plugins/oracle/networking/openSQLServer.spec.js create mode 100644 plugins/oracle/networking/openSSH.spec.js create mode 100644 plugins/oracle/networking/openSalt.spec.js create mode 100644 plugins/oracle/networking/openTelnet.spec.js create mode 100644 plugins/oracle/networking/openVNCClient.spec.js create mode 100644 plugins/oracle/networking/openVNCServer.spec.js diff --git a/plugins/oracle/networking/openAllPortsProtocols.spec.js b/plugins/oracle/networking/openAllPortsProtocols.spec.js new file mode 100644 index 0000000000..52f1146ecd --- /dev/null +++ b/plugins/oracle/networking/openAllPortsProtocols.spec.js @@ -0,0 +1,214 @@ +var expect = require('chai').expect; +const plugin = require('./openAllPortsProtocols'); + +const securityLists = [ + + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "all", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK" + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "egressSecurityRules": [ + { + "destination": "0.0.0.0/0", + "destinationType": "CIDR_BLOCK", + "isStateless": false, + "protocol": "all" + } + ], + "freeformTags": {}, + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + }, + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } +]; + +const vcnData = [ + { + + "compartmentId": "compartment1", + "displayName": "vcn1", + "freeformTags": {}, + "id": "vcn1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z" + } +] +const createCache = (listsData, listsErr, vcnData, vcnErr) => { + return { + vcn: { + list: { + "us-ashburn-1": { + data: vcnData, + err: vcnErr + } + } + }, + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openAllPortsProtocols', function () { + describe('run', function () { + it('should give unknown if unable to query for VCNs', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for VCNs') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + vcnData, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + vcnData, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No public open ports found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + vcnData, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has all ports open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + vcnData, + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openCIFS.spec.js b/plugins/oracle/networking/openCIFS.spec.js new file mode 100644 index 0000000000..7f7fe30e09 --- /dev/null +++ b/plugins/oracle/networking/openCIFS.spec.js @@ -0,0 +1,309 @@ +var expect = require('chai').expect; +const plugin = require('./openCIFS'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "udpOptions": { + "destinationPortRange": { + "max": 445, + "min": 445 + }, + "sourcePortRange": { + "max": 445, + "min": 445 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "udpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "udpOptions": { + "destinationPortRange": { + "max": 445, + "min": 445 + }, + "sourcePortRange": { + "max": 445, + "min": 445 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "displayName": "firstgroup", + "freeformTags": {}, + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openCIFS', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has CIFS port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has CIFS: UDP port 445 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has CIFS port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has CIFS: UDP port 445 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openDNS.spec.js b/plugins/oracle/networking/openDNS.spec.js new file mode 100644 index 0000000000..478fd97a66 --- /dev/null +++ b/plugins/oracle/networking/openDNS.spec.js @@ -0,0 +1,308 @@ +var expect = require('chai').expect; +const plugin = require('./openDNS'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "udpOptions": { + "destinationPortRange": { + "max": 53, + "min": 53 + }, + "sourcePortRange": { + "max": 53, + "min": 53 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 53, + "min": 53 + }, + "sourcePortRange": { + "max": 53, + "min": 53 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "displayName": "firstgroup", + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openDNS', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has DNS port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has DNS: UDP port 53 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has DNS port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has DNS: TCP port 53 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openDocker.spec.js b/plugins/oracle/networking/openDocker.spec.js new file mode 100644 index 0000000000..51eb3995d0 --- /dev/null +++ b/plugins/oracle/networking/openDocker.spec.js @@ -0,0 +1,315 @@ +var expect = require('chai').expect; +const plugin = require('./openDocker'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 2376, + "min": 2375 + }, + "sourcePortRange": { + "max": 2376, + "min": 2375 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 2376, + "min":2375 + }, + "sourcePortRange": { + "max": 2376, + "min": 2375 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "definedTags": { + "Oracle-Tags": { + "CreatedBy": "muhammad.akhtar.ext@aquasec.com", + "CreatedOn": "2022-01-09T13:03:47.837Z" + } + }, + "displayName": "firstgroup", + "freeformTags": {}, + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openDocker', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has Docker port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has Docker: TCP port 2375,2376 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has Docker port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has Docker: TCP port 2375,2376 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openFTP.spec.js b/plugins/oracle/networking/openFTP.spec.js new file mode 100644 index 0000000000..a5849a525b --- /dev/null +++ b/plugins/oracle/networking/openFTP.spec.js @@ -0,0 +1,315 @@ +var expect = require('chai').expect; +const plugin = require('./openFTP'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 21, + "min": 20 + }, + "sourcePortRange": { + "max": 21, + "min": 20 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 21, + "min":20 + }, + "sourcePortRange": { + "max": 21, + "min": 20 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "definedTags": { + "Oracle-Tags": { + "CreatedBy": "muhammad.akhtar.ext@aquasec.com", + "CreatedOn": "2022-01-09T13:03:47.837Z" + } + }, + "displayName": "firstgroup", + "freeformTags": {}, + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openFTP', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has FTP port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has FTP: TCP port 20,21 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has FTP port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has FTP: TCP port 20,21 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openHadoopNameNode.spec.js b/plugins/oracle/networking/openHadoopNameNode.spec.js new file mode 100644 index 0000000000..0df7605346 --- /dev/null +++ b/plugins/oracle/networking/openHadoopNameNode.spec.js @@ -0,0 +1,315 @@ +var expect = require('chai').expect; +const plugin = require('./openHadoopNameNode'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 8020, + "min": 8020 + }, + "sourcePortRange": { + "max": 8020, + "min": 8020 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "802022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "802022-01-09T13:02:8020.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "802022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "802022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 8020, + "min":8020 + }, + "sourcePortRange": { + "max": 8020, + "min": 8020 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "definedTags": { + "Oracle-Tags": { + "CreatedBy": "muhammad.akhtar.ext@aquasec.com", + "CreatedOn": "802022-01-09T13:03:47.837Z" + } + }, + "displayName": "firstgroup", + "freeformTags": {}, + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "802022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openHadoopNameNode', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has NameNodeMetadata port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has NameNodeMetadata: TCP port 8020 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has NameNodeMetadata port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has NameNodeMetadata: TCP port 8020 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openHadoopNameNodeWebUI.spec.js b/plugins/oracle/networking/openHadoopNameNodeWebUI.spec.js new file mode 100644 index 0000000000..ad14e6faa1 --- /dev/null +++ b/plugins/oracle/networking/openHadoopNameNodeWebUI.spec.js @@ -0,0 +1,315 @@ +var expect = require('chai').expect; +const plugin = require('./openHadoopNameNodeWebUI'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 50470, + "min": 50070 + }, + "sourcePortRange": { + "max": 50470, + "min": 50070 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "802022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "802022-01-09T13:02:8020.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "802022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "802022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 50470, + "min": 50070 + }, + "sourcePortRange": { + "max": 50470, + "min": 50070 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "definedTags": { + "Oracle-Tags": { + "CreatedBy": "muhammad.akhtar.ext@aquasec.com", + "CreatedOn": "802022-01-09T13:03:47.837Z" + } + }, + "displayName": "firstgroup", + "freeformTags": {}, + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "802022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openHadoopNameNodeWebUI', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has NameNodeWebUI port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has NameNodeWebUI: TCP port 50070,50470 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has NameNodeWebUI port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has NameNodeWebUI: TCP port 50070,50470 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openKibana.spec.js b/plugins/oracle/networking/openKibana.spec.js new file mode 100644 index 0000000000..2b2ffaedbe --- /dev/null +++ b/plugins/oracle/networking/openKibana.spec.js @@ -0,0 +1,308 @@ +var expect = require('chai').expect; +const plugin = require('./openKibana'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 5601, + "min": 5601 + }, + "sourcePortRange": { + "max": 5601, + "min": 5601 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 5601, + "min": 5601 + }, + "sourcePortRange": { + "max": 5601, + "min": 5601 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "displayName": "firstgroup", + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openKibana', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has Kibana port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has Kibana: TCP port 5601 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has Kibana port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has Kibana: TCP port 5601 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openMySQL.spec.js b/plugins/oracle/networking/openMySQL.spec.js new file mode 100644 index 0000000000..0955b7b02c --- /dev/null +++ b/plugins/oracle/networking/openMySQL.spec.js @@ -0,0 +1,315 @@ +var expect = require('chai').expect; +const plugin = require('./openMySQL'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 4333, + "min": 3306 + }, + "sourcePortRange": { + "max": 4333, + "min": 3306 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "330622-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "330622-01-09T13:02:3306.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "330622-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "330622-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 4333, + "min":3306 + }, + "sourcePortRange": { + "max": 4333, + "min": 3306 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "definedTags": { + "Oracle-Tags": { + "CreatedBy": "muhammad.akhtar.ext@aquasec.com", + "CreatedOn": "330622-01-09T13:03:47.837Z" + } + }, + "displayName": "firstgroup", + "freeformTags": {}, + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "330622-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openMySQL', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has MySQL port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has MySQL: TCP port 4333,3306 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has MySQL port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has MySQL: TCP port 4333,3306 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openNetBIOS.spec.js b/plugins/oracle/networking/openNetBIOS.spec.js new file mode 100644 index 0000000000..cc06b64b79 --- /dev/null +++ b/plugins/oracle/networking/openNetBIOS.spec.js @@ -0,0 +1,315 @@ +var expect = require('chai').expect; +const plugin = require('./openNetBIOS'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "udpOptions": { + "destinationPortRange": { + "max": 138, + "min": 137 + }, + "sourcePortRange": { + "max": 138, + "min": 137 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "udpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "udpOptions": { + "destinationPortRange": { + "max": 138, + "min":137 + }, + "sourcePortRange": { + "max": 138, + "min": 137 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "definedTags": { + "Oracle-Tags": { + "CreatedBy": "muhammad.akhtar.ext@aquasec.com", + "CreatedOn": "2022-01-09T13:03:47.837Z" + } + }, + "displayName": "firstgroup", + "freeformTags": {}, + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openNetBIOS', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has NetBIOS port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has NetBIOS: UDP port 137,138 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has NetBIOS port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has NetBIOS: UDP port 137,138 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openOracle.spec.js b/plugins/oracle/networking/openOracle.spec.js new file mode 100644 index 0000000000..6457485912 --- /dev/null +++ b/plugins/oracle/networking/openOracle.spec.js @@ -0,0 +1,308 @@ +var expect = require('chai').expect; +const plugin = require('./openOracle'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 1521, + "min": 1521 + }, + "sourcePortRange": { + "max": 1521, + "min": 1521 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 1521, + "min": 1521 + }, + "sourcePortRange": { + "max": 1521, + "min": 1521 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "displayName": "firstgroup", + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openOracle', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has Oracle port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has Oracle: TCP port 1521 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has Oracle port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has Oracle: TCP port 1521 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openOracleAutoDataWarehouse.spec.js b/plugins/oracle/networking/openOracleAutoDataWarehouse.spec.js new file mode 100644 index 0000000000..6e36f33e08 --- /dev/null +++ b/plugins/oracle/networking/openOracleAutoDataWarehouse.spec.js @@ -0,0 +1,308 @@ +var expect = require('chai').expect; +const plugin = require('./openOracleAutoDataWarehouse'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 1522, + "min": 1522 + }, + "sourcePortRange": { + "max": 1522, + "min": 1522 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 1522, + "min": 1522 + }, + "sourcePortRange": { + "max": 1522, + "min": 1522 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "displayName": "firstgroup", + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openOracleAutoDataWarehouse', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has Autonomous Data Warehouse port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has Autonomous Data Warehouse: TCP port 1522 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has Autonomous Data Warehouse port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has Autonomous Data Warehouse: TCP port 1522 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openPostgreSQL.spec.js b/plugins/oracle/networking/openPostgreSQL.spec.js new file mode 100644 index 0000000000..797e9fd3d0 --- /dev/null +++ b/plugins/oracle/networking/openPostgreSQL.spec.js @@ -0,0 +1,308 @@ +var expect = require('chai').expect; +const plugin = require('./openPostgreSQL'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 5432, + "min": 5432 + }, + "sourcePortRange": { + "max": 5432, + "min": 5432 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 5432, + "min": 5432 + }, + "sourcePortRange": { + "max": 5432, + "min": 5432 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "displayName": "firstgroup", + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openPostgreSQL', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has PostgresSQL port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has PostgresSQL: TCP port 5432 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has PostgresSQL port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has PostgresSQL: TCP port 5432 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openRDP.spec.js b/plugins/oracle/networking/openRDP.spec.js new file mode 100644 index 0000000000..2baefa07d5 --- /dev/null +++ b/plugins/oracle/networking/openRDP.spec.js @@ -0,0 +1,308 @@ +var expect = require('chai').expect; +const plugin = require('./openRDP'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 3389, + "min": 3389 + }, + "sourcePortRange": { + "max": 3389, + "min": 3389 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 3389, + "min": 3389 + }, + "sourcePortRange": { + "max": 3389, + "min": 3389 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "displayName": "firstgroup", + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openRDP', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has RDP port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has RDP: TCP port 3389 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has RDP port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has RDP: TCP port 3389 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openRPC.spec.js b/plugins/oracle/networking/openRPC.spec.js new file mode 100644 index 0000000000..62ecf0379c --- /dev/null +++ b/plugins/oracle/networking/openRPC.spec.js @@ -0,0 +1,308 @@ +var expect = require('chai').expect; +const plugin = require('./openRPC'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 135, + "min": 135 + }, + "sourcePortRange": { + "max": 135, + "min": 135 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 135, + "min": 135 + }, + "sourcePortRange": { + "max": 135, + "min": 135 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "displayName": "firstgroup", + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openRPC', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has RPC port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has RPC: TCP port 135 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has RPC port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has RPC: TCP port 135 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openSMBoTCP.spec.js b/plugins/oracle/networking/openSMBoTCP.spec.js new file mode 100644 index 0000000000..e43ac94fbe --- /dev/null +++ b/plugins/oracle/networking/openSMBoTCP.spec.js @@ -0,0 +1,308 @@ +var expect = require('chai').expect; +const plugin = require('./openSMBoTCP'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 445, + "min": 445 + }, + "sourcePortRange": { + "max": 445, + "min": 445 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 445, + "min": 445 + }, + "sourcePortRange": { + "max": 445, + "min": 445 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "displayName": "firstgroup", + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openSMBoTCP', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has SMBoTCP port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has SMBoTCP: TCP port 445 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has SMBoTCP port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has SMBoTCP: TCP port 445 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openSMTP.spec.js b/plugins/oracle/networking/openSMTP.spec.js new file mode 100644 index 0000000000..472e5f222c --- /dev/null +++ b/plugins/oracle/networking/openSMTP.spec.js @@ -0,0 +1,308 @@ +var expect = require('chai').expect; +const plugin = require('./openSMTP'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 25, + "min": 25 + }, + "sourcePortRange": { + "max": 25, + "min": 25 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 25, + "min": 25 + }, + "sourcePortRange": { + "max": 25, + "min": 25 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "displayName": "firstgroup", + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openSMTP', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has SMTP port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has SMTP: TCP port 25 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has SMTP port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has SMTP: TCP port 25 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openSQLServer.spec.js b/plugins/oracle/networking/openSQLServer.spec.js new file mode 100644 index 0000000000..d11fb2ffb7 --- /dev/null +++ b/plugins/oracle/networking/openSQLServer.spec.js @@ -0,0 +1,308 @@ +var expect = require('chai').expect; +const plugin = require('./openSQLServer'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "udpOptions": { + "destinationPortRange": { + "max": 1434, + "min": 1434 + }, + "sourcePortRange": { + "max": 1434, + "min": 1434 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 1433, + "min": 1433 + }, + "sourcePortRange": { + "max": 1433, + "min": 1433 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "displayName": "firstgroup", + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openSQLServer', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has SQL Server port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has SQL Server: UDP port 1434 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has SQL Server port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has SQL Server: TCP port 1433 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openSSH.spec.js b/plugins/oracle/networking/openSSH.spec.js new file mode 100644 index 0000000000..4aec4064a4 --- /dev/null +++ b/plugins/oracle/networking/openSSH.spec.js @@ -0,0 +1,294 @@ +var expect = require('chai').expect; +const plugin = require('./openSSH'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + }, + "sourcePortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.422Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + }, + "sourcePortRange": { + "max": 22, + "min": 22 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "displayName": "firstgroup", + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openSSH', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has SSH port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has SSH: TCP port 22 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has SSH port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has SSH: TCP port 22 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openSalt.spec.js b/plugins/oracle/networking/openSalt.spec.js new file mode 100644 index 0000000000..f21d7db0c8 --- /dev/null +++ b/plugins/oracle/networking/openSalt.spec.js @@ -0,0 +1,315 @@ +var expect = require('chai').expect; +const plugin = require('./openSalt'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 4506, + "min": 4505 + }, + "sourcePortRange": { + "max": 4506, + "min": 4505 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 22, + "min": 22 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.425Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 4506, + "min":4505 + }, + "sourcePortRange": { + "max": 4506, + "min": 4505 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "definedTags": { + "Oracle-Tags": { + "CreatedBy": "muhammad.akhtar.ext@aquasec.com", + "CreatedOn": "2022-01-09T13:03:47.837Z" + } + }, + "displayName": "firstgroup", + "freeformTags": {}, + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openSalt', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has Salt port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has Salt: TCP port 4505,4506 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has Salt port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has Salt: TCP port 4505,4506 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openTelnet.spec.js b/plugins/oracle/networking/openTelnet.spec.js new file mode 100644 index 0000000000..bb99d4886d --- /dev/null +++ b/plugins/oracle/networking/openTelnet.spec.js @@ -0,0 +1,294 @@ +var expect = require('chai').expect; +const plugin = require('./openTelnet'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 23, + "min": 23 + }, + "sourcePortRange": { + "max": 23, + "min": 23 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.422Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 23, + "min": 23 + }, + "sourcePortRange": { + "max": 23, + "min": 23 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "displayName": "firstgroup", + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openTelnet', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has Telnet port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has Telnet: TCP port 23 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has Telnet port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has Telnet: TCP port 23 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openVNCClient.spec.js b/plugins/oracle/networking/openVNCClient.spec.js new file mode 100644 index 0000000000..dcc679bfd4 --- /dev/null +++ b/plugins/oracle/networking/openVNCClient.spec.js @@ -0,0 +1,294 @@ +var expect = require('chai').expect; +const plugin = require('./openVNCClient'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 5500, + "min": 5500 + }, + "sourcePortRange": { + "max": 5500, + "min": 5500 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.422Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 5500, + "min": 5500 + }, + "sourcePortRange": { + "max": 5500, + "min": 5500 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "displayName": "firstgroup", + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openVNCClient', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has VNC Client port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has VNC Client: TCP port 5500 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has VNC Client port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has VNC Client: TCP port 5500 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); diff --git a/plugins/oracle/networking/openVNCServer.spec.js b/plugins/oracle/networking/openVNCServer.spec.js new file mode 100644 index 0000000000..e0f7e1266d --- /dev/null +++ b/plugins/oracle/networking/openVNCServer.spec.js @@ -0,0 +1,294 @@ +var expect = require('chai').expect; +const plugin = require('./openVNCServer'); + +const securityLists = [ + { + "compartmentId": "compartment-1", + "displayName": "list1", + "egressSecurityRules": [], + "freeformTags": {}, + "id": "list1", + "ingressSecurityRules": [ + { + "isStateless": false, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "tcpOptions": { + "destinationPortRange": { + "max": 5900, + "min": 5900 + }, + "sourcePortRange": { + "max": 5900, + "min": 5900 + } + } + } + ], + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-04-17T01:16:32.366Z", + "vcnId": "vcn1" + }, + { + "compartmentId": "compartment-1", + "displayName": "list2", + "id": "list2", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:02:20.422Z", + "vcnId": "vcn1" + } + ]; + +const securityRules = [ + { + "direction": "INGRESS", + "id": "1", + "isStateless": false, + "isValid": true, + "protocol": "all", + "source": "10.1.0.0/16", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-01-09T13:03:48.937Z", + "networkSecurityGroups": "group1" + }, + { + "direction": "INGRESS", + "id": "2", + "isStateless": false, + "isValid": true, + "protocol": "17", + "source": "0.0.0.0/0", + "sourceType": "CIDR_BLOCK", + "timeCreated": "2022-04-17T12:16:46.679Z", + "tcpOptions": { + "destinationPortRange": { + "max": 5900, + "min": 5900 + }, + "sourcePortRange": { + "max": 5900, + "min": 5900 + } + }, + "networkSecurityGroups": "group1" + } + ] +const networkSecurityGroups = [ + { + "compartmentId": "compartment-1", + "displayName": "firstgroup", + "id": "group1", + "lifecycleState": "AVAILABLE", + "timeCreated": "2022-01-09T13:03:47.999Z", + "vcnId": "vcn1" + } + ] +const createCache = (listsData, listsErr, groupsData, groupsErr, rulesData, rulesErr,) => { + return { + + securityList: { + list: { + "us-ashburn-1": { + data: listsData, + err: listsErr + } + } + }, + securityRule: { + list: { + "us-ashburn-1": { + data: rulesData, + err: rulesErr + } + } + }, + networkSecurityGroup: { + list: { + "us-ashburn-1": { + data: groupsData, + err: groupsErr + } + } + }, + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + }; +}; + + + +describe('openVNCServer', function () { + describe('run', function () { + it('should give unknown if unable to query for security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give unknown if unable to query for security rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + securityLists[1], + null, + networkSecurityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no security lists or ruls are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security rules or lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + networkSecurityGroups, + null, + [], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in security lists', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No open ports found in Security Lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should PASS if no open ports found in network security groups', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(0) + expect(results[1].message).to.include('No open ports found in Network Security Groups') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should FAIL if security list has VNC Server port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('has VNC Server: TCP port 5900 open to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[0]], + null, + networkSecurityGroups, + null, + [securityRules[0]], + null + ); + + plugin.run(cache, {}, callback); + }); + it('should FAIL if network security group has VNC Server port open to public', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[1].status).to.equal(2) + expect(results[1].message).to.include('has VNC Server: TCP port 5900 open to') + expect(results[1].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [securityLists[1]], + null, + networkSecurityGroups, + null, + [securityRules[1]], + null + ); + + plugin.run(cache, {}, callback); + }); + }); +}); From 7816127215be71d50899b722905a42a1dccc2beb Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Mon, 18 Apr 2022 01:41:33 +0500 Subject: [PATCH 071/350] GCP API Key Application Restriction Plugin --- plugins/google/api/apiKeyApplicationRestriction.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/google/api/apiKeyApplicationRestriction.js b/plugins/google/api/apiKeyApplicationRestriction.js index dbe5d051b0..dcb96528ec 100644 --- a/plugins/google/api/apiKeyApplicationRestriction.js +++ b/plugins/google/api/apiKeyApplicationRestriction.js @@ -44,7 +44,9 @@ module.exports = { if (key.restrictions) { if (key.restrictions.browserKeyRestrictions && key.restrictions.browserKeyRestrictions.allowedReferrers && key.restrictions.browserKeyRestrictions.allowedReferrers.length) { - isRestricted = true; + isRestricted = key.restrictions.browserKeyRestrictions.allowedReferrers.every(referrer => + referrer.match(/^(\*\.)?([\w-]+\.)+[\w-]+$/) + ); } if (key.restrictions.serverKeyRestrictions && key.restrictions.serverKeyRestrictions.allowedIps && key.restrictions.serverKeyRestrictions.allowedIps.length) { @@ -56,10 +58,10 @@ module.exports = { } if (isRestricted) { helpers.addResult(results, 0, - 'API Key usage is restricted to restricted to trusted hosts, HTTP referrers, or applications', 'global', key.name); + 'API Key usage is restricted to trusted hosts, HTTP referrers, or applications', 'global', key.name); } else { helpers.addResult(results, 2, - 'API Key usage is not restricted to restricted to trusted hosts, HTTP referrers, or applications', 'global', key.name); + 'API Key usage is not restricted to trusted hosts, HTTP referrers, or applications', 'global', key.name); } }); From ac6e74fd28b501f2cde2b828da8639635a49d921 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Mon, 18 Apr 2022 03:10:45 +0500 Subject: [PATCH 072/350] Oracle Identity Users Password Last Used Plugin --- exports.js | 1 + .../oracle/identity/usersPasswordLastUsed.js | 94 +++++++ .../identity/usersPasswordLastUsed.spec.js | 261 ++++++++++++++++++ 3 files changed, 356 insertions(+) create mode 100644 plugins/oracle/identity/usersPasswordLastUsed.js create mode 100644 plugins/oracle/identity/usersPasswordLastUsed.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..99882f3a57 100644 --- a/exports.js +++ b/exports.js @@ -797,6 +797,7 @@ module.exports = { 'userAuthTokenRotated' : require(__dirname + '/plugins/oracle/identity/userAuthTokenRotated.js'), 'userCustomerSecretKeysRotated' : require(__dirname + '/plugins/oracle/identity/userCustomerSecretKeysRotated.js'), 'userAPIKeysRotated' : require(__dirname + '/plugins/oracle/identity/userAPIKeysRotated.js'), + 'usersPasswordLastUsed' : require(__dirname + '/plugins/oracle/identity/usersPasswordLastUsed.js'), 'openSSH' : require(__dirname + '/plugins/oracle/networking/openSSH.js'), 'openOracleAutoDataWarehouse' : require(__dirname + '/plugins/oracle/networking/openOracleAutoDataWarehouse.js'), diff --git a/plugins/oracle/identity/usersPasswordLastUsed.js b/plugins/oracle/identity/usersPasswordLastUsed.js new file mode 100644 index 0000000000..7b3de65f03 --- /dev/null +++ b/plugins/oracle/identity/usersPasswordLastUsed.js @@ -0,0 +1,94 @@ +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Users Password Last Used', + category: 'Identity', + domain: 'Identity and Access Management', + description: 'Detect users that have not logged in for a period of time and should be deactivated.', + more_info: 'Having multiple user accounts that have been inactive for a period of time can increase the risk of security attacks and breaches.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/managingusers.htm', + recommended_action: 'Delete old user accounts that allow password-based logins and have not been used recently.', + apis: ['user:list'], + compliance: { + pci: 'PCI requires that all user credentials are rotated every 90 days. If the user password has not been used in the last 90 days, the user should be deactivated.', + cis1: '1.3 Ensure credentials unused for 90 days or greater are disabled' + }, + settings: { + identity_users_password_last_used_fail: { + name: 'Users Password Last Used Fail', + description: 'Return a failing result when users with password logins exceed this number of days without being used', + regex: '^[1-9]{1}[0-9]{0,3}$', + default: 180 + }, + identity_users_password_last_used_warn: { + name: 'Users Password Last Used Warn', + description: 'Return a warning result when users with password logins exceed this number of days without being used', + regex: '^[1-9]{1}[0-9]{0,3}$', + default: 90 + } + }, + + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var config = { + identity_users_password_last_used_fail: settings.identity_users_password_last_used_fail || this.settings.identity_users_password_last_used_fail.default, + identity_users_password_last_used_warn: settings.identity_users_password_last_used_warn || this.settings.identity_users_password_last_used_warn.default + }; + + var region = helpers.objectFirstKey(cache['regionSubscription']['list']); + + var users = helpers.addSource(cache, source, + ['user', 'list', region]); + + if (!users) return callback(null, results, source); + + if (users.err || !users.data) { + helpers.addResult(results, 3, + 'Unable to query for user MFA status: ' + helpers.addError(users)); + return callback(null, results, source); + } + + if (users.data.length < 2) { + helpers.addResult(results, 0, 'No user accounts found'); + return callback(null, results, source); + } + + + var found = false; + + users.data.forEach(user => { + var returnCode, returnMsg, daysAgo; + + if (user.lastSuccessfulLoginTime) { + daysAgo = helpers.daysBetween(new Date(), new Date(user.lastSuccessfulLoginTime)); + returnMsg = `User's last successful login was ${daysAgo} days ago`; + } else if (user.timeCreated) { + daysAgo = helpers.daysBetween(new Date(), new Date(user.timeCreated)); + returnMsg = `User was created ${daysAgo} days ago but never logged in`; + } + + if (!isNaN(daysAgo)) { + + if (daysAgo > config.identity_users_password_last_used_fail) { + returnCode = 2; + } else if (daysAgo > config.identity_users_password_last_used_warn) { + returnCode = 1; + } else { + returnCode = 0; + } + + helpers.addResult(results, returnCode, returnMsg, 'global', user.name); + + found = true; + } + }); + + if (!found) { + helpers.addResult(results, 0, 'No users with password logins found'); + } + + callback(null, results, source); + } +}; diff --git a/plugins/oracle/identity/usersPasswordLastUsed.spec.js b/plugins/oracle/identity/usersPasswordLastUsed.spec.js new file mode 100644 index 0000000000..2915743445 --- /dev/null +++ b/plugins/oracle/identity/usersPasswordLastUsed.spec.js @@ -0,0 +1,261 @@ +var expect = require('chai').expect; +var plugin = require('./usersPasswordLastUsed'); + +var warnDate = new Date(); +warnDate.setMonth(warnDate.getMonth() - 4); +var passDate = new Date(); +passDate.setMonth(passDate.getMonth() - 2); +var failDate = new Date(); +failDate.setMonth(failDate.getMonth() - 7); + +const user = [ + { + "description": "login user", + "email": "user3@gmail.com", + "emailVerified": false, + "isMfaActivated": true, + "id": "111", + "timeCreated": failDate, + "lastSuccessfulLoginTime": failDate, + }, + { + "description": "login user", + "email": "user3@gmail.com", + "emailVerified": false, + "isMfaActivated": true, + "id": "111", + "timeCreated": failDate, + }, + { + "defined-tags": {}, + "description": "login user", + "email": "user1@gmail.com", + "isMfaActivated": false, + "id": "111", + "timeCreated": warnDate, + "lastSuccessfulLoginTime": warnDate, + + }, + { + "defined-tags": {}, + "description": "login user", + "email": "user1@gmail.com", + "isMfaActivated": false, + "id": "111", + "timeCreated": warnDate, + + }, + { + "email": "user2@gmail.com", + "emailVerified": true, + "name": "user2", + "description": "user2", + "timeCreated": passDate, + "lastSuccessfulLoginTime": passDate, + }, + { + "email": "user2@gmail.com", + "emailVerified": true, + "name": "user2", + "description": "user2", + "timeCreated": passDate, + }, + { + "description": "login user", + "email": "user3@gmail.com", + "emailVerified": false, + "isMfaActivated": true, + "id": "111", + } +]; + +const createCache = (err, data) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + user: { + list: { + 'us-ashburn-1': { + err: err, + data: data + } + } + } + } +}; + +describe('usersPasswordLastUsed', function () { + describe('run', function () { + it('should give unknown result if unable to query for users', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for user') + expect(results[0].region).to.equal('global') + done() + }; + + const cache = createCache( + {err: 'error'}, + undefined + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if no user accounts found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No user accounts found') + expect(results[0].region).to.equal('global') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if no users with password logins found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No users with password logins found') + expect(results[0].region).to.equal('global') + done() + }; + + const cache = createCache( + null, + [user[6], user[6]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should PASS if the user password was last used within the pass limit', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('global') + done() + }; + + const cache = createCache( + null, + [user[4], user[5]] + ); + + plugin.run(cache, { identity_users_password_last_used_fail: 180, identity_users_password_last_used_warn: 90 }, callback); + }) + + it('should PASS if the user was created within the pass limit but never used', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('global') + done() + }; + + const cache = createCache( + null, + [user[5], user[4]] + ); + + plugin.run(cache, { identity_users_password_last_used_fail: 180, identity_users_password_last_used_warn: 90 }, callback); + }) + + it('should WARN if the user password was last used within the warn limit', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(1) + expect(results[0].region).to.equal('global') + done() + }; + + const cache = createCache( + null, + [user[2], user[3]] + ); + + plugin.run(cache, { identity_users_password_last_used_fail: 180, identity_users_password_last_used_warn: 90 }, callback); + }) + + it('should WARN if the user was created within the warn limit but never used', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(1) + expect(results[0].region).to.equal('global') + done() + }; + + const cache = createCache( + null, + [user[3], user[2]] + ); + + plugin.run(cache, { identity_users_password_last_used_fail: 180, identity_users_password_last_used_warn: 90 }, callback); + }) + + it('should FAIL if the user password was last used within the fail limit', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].region).to.equal('global') + done() + }; + + const cache = createCache( + null, + [user[0], user[1]] + ); + + plugin.run(cache, { identity_users_password_last_used_fail: 180, identity_users_password_last_used_warn: 90 }, callback); + }) + + it('should FAIL if the user was created within the fail limit but never used', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].region).to.equal('global') + done() + }; + + const cache = createCache( + null, + [user[1], user[0]] + ); + + plugin.run(cache, { identity_users_password_last_used_fail: 180, identity_users_password_last_used_warn: 90 }, callback); + }) + + }); +}); \ No newline at end of file From d08d68597b6012bf1e665bf6a855c9e143bd41fb Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 10 Apr 2022 03:00:50 +0500 Subject: [PATCH 073/350] Added allowedCertificateKeyTypes plugin and spec --- exports.js | 1 + .../keyvaults/allowedCertificateKeyTypes.js | 70 ++++++++ .../allowedCertificateKeyTypes.spec.js | 160 ++++++++++++++++++ 3 files changed, 231 insertions(+) create mode 100644 plugins/azure/keyvaults/allowedCertificateKeyTypes.js create mode 100644 plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..06dfdf7124 100644 --- a/exports.js +++ b/exports.js @@ -755,6 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), + 'allowedCertificateKeyTypes' : require(__dirname + '/plugins/azure/keyvaults/allowedCertificateKeyTypes.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js new file mode 100644 index 0000000000..6c6b294e60 --- /dev/null +++ b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js @@ -0,0 +1,70 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Allowed Certificates Key Types', + category: 'Key Vaults', + domain: 'Identity and Access Management', + description: 'Ensures that Microsoft Azure Key Vault SSL certificates are using the allowed key types.', + more_info: 'Having the right key type set for your Azure Key Vault SSL certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', + recommended_action: 'Ensure that Key Vault SSL certificates are using the allowed key types.', + link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/certificate-access-control', + apis: ['vaults:list', 'vaults:getKeys'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.vaults, function(location, rcb) { + var vaults = helpers.addSource(cache, source, + ['vaults', 'list', location]); + + if (!vaults) return rcb(); + + if (vaults.err || !vaults.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); + return rcb(); + } + + if (!vaults.data.length) { + helpers.addResult(results, 0, 'No Key Vaults found', location); + return rcb(); + } + + vaults.data.forEach((vault) => { + var keys = helpers.addSource(cache, source, + ['vaults', 'getKeys', location, vault.id]); + + if (!keys || keys.err || !keys.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); + } else if (!keys.data.length) { + helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); + } else { + keys.data.forEach((key) => { + var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); + var keyId = `${vault.id}/keys/${keyName}`; + + if (key.attributes) { + let attributes = key.attributes; + if ((attributes.expires && attributes.expires !== null && attributes.expires !== '') || (attributes.exp && attributes.exp !== null && attributes.exp !== '')) { + helpers.addResult(results, 0, + 'Expiry date is set for the key', location, keyId); + } else { + helpers.addResult(results, 2, + 'Expiry date is not set for the key', location, keyId); + } + } else { + helpers.addResult(results, 2, + 'Expiry date is not set for the key', location, keyId); + } + }); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js new file mode 100644 index 0000000000..7d048cb2f5 --- /dev/null +++ b/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js @@ -0,0 +1,160 @@ +var expect = require('chai').expect; +var auth = require('./secretExpirationEnabled'); + +const listVaults = [ + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + }, + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + }, + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + } +]; + +const getKeys = [ + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "exp": null, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + }, + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "exp": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + }, + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": false, + "exp": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + } +]; + +const createCache = (err, list, get) => { + return { + vaults: { + list: { + 'eastus': { + err: err, + data: list + } + }, + getSecrets: { + 'eastus': get + } + } + } +}; + +describe('secretExpirationEnabled', function() { + describe('run', function() { + it('should give passing result if no secrets 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 Key Vaults found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [], {}), {}, callback); + }); + + it('should give failing result if expiration is not set on secrets', 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('Expiry date is not set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], getKeys[0]), {}, callback); + }); + + it('should give passing result if expiration is set on keys', 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('Expiry date is set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[1]], getKeys[1]), {}, callback); + }); + + it('should give passing result if key is disabled', 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('The secret is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[2]], getKeys[2]), {}, callback); + }) + }) +}); From 28e771d667bdd3486f12ab0585feee3378419b02 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Mon, 18 Apr 2022 23:40:37 +0500 Subject: [PATCH 074/350] Refactored plugin and tests --- collectors/azure/collector.js | 33 ++- .../keyvaults/allowedCertificateKeyTypes.js | 53 +++-- .../allowedCertificateKeyTypes.spec.js | 207 +++++++++++------- 3 files changed, 179 insertions(+), 114 deletions(-) diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index c7fc096367..1c8c872ea0 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -409,7 +409,14 @@ var postcalls = { properties: ['vaultUri'], url: '{vaultUri}secrets?api-version=7.0', vault: true + }, + getCertificates: { + reliesOnPath: 'vaults.list', + properties: ['vaultUri'], + url: '{vaultUri}certificates?api-version=7.3', + vault: true } + }, databases: { listByServer: { @@ -484,6 +491,14 @@ var tertiarycalls = { properties: ['id'], url: 'https://management.azure.com/{id}/backupShortTermRetentionPolicies?api-version=2017-10-01-preview' } + }, + getCertificatePolicy: { + get: { + reliesOnPath: 'vaults.getCertificates', + properties: ['id'], + url: '{id}/policy?api-version=7.3', + vault: true + } } }; @@ -529,9 +544,9 @@ var collect = function(AzureConfig, settings, callback) { if (settings.gather) { return callback(null, calls, postcalls, tertiarycalls, specialcalls); } - + var helpers = require(__dirname + '/../../helpers/azure/auth.js'); - + // Login using the Azure config helpers.login(AzureConfig, function(loginErr, loginData) { if (loginErr) return callback(loginErr); @@ -556,7 +571,7 @@ var collect = function(AzureConfig, settings, callback) { subCallCb(); }); } - + async.eachOfLimit(calls, 10, function(callObj, service, callCb) { if (!collection[service]) collection[service] = {}; // Loop through sub-calls @@ -565,7 +580,7 @@ var collect = function(AzureConfig, settings, callback) { if (settings && settings.api_calls && settings.api_calls.indexOf([service, one].join(':')) === -1) return subCallCb(); - + if (!collection[service][one]) collection[service][one] = {}; processTopCall(collection[service][one], service, subCallObj, subCallCb); }, function() { @@ -633,7 +648,7 @@ var collect = function(AzureConfig, settings, callback) { subCallCb(); } } - + async.eachOfLimit(postcalls, 10, function(callObj, service, callCb) { if (!collection[service]) collection[service] = {}; // Loop through sub-calls @@ -641,7 +656,7 @@ var collect = function(AzureConfig, settings, callback) { if (settings && settings.api_calls && settings.api_calls.indexOf([service, one].join(':')) === -1) return subCallCb(); - + if (!collection[service][one]) collection[service][one] = {}; processTopCall(collection[service][one], service, subCallObj, subCallCb); }, function() { @@ -698,7 +713,7 @@ var collect = function(AzureConfig, settings, callback) { resourceDataCb(); }); } - + if (Array.isArray(resourceObj)) { async.eachLimit(resourceObj, 10, function(resourceData, resourceDataCb) { processResource(resourceData, resourceDataCb); @@ -734,7 +749,7 @@ var collect = function(AzureConfig, settings, callback) { if (settings && settings.api_calls && settings.api_calls.indexOf([service, one].join(':')) === -1) return subCallCb(); - + if (!collection[service][one]) collection[service][one] = {}; if (subCallObj.url) { processTopCall(collection[service][one], service, subCallObj, subCallCb); @@ -744,7 +759,7 @@ var collect = function(AzureConfig, settings, callback) { if (settings && settings.api_calls && settings.api_calls.indexOf([service, one, two].join(':')) === -1) return subCallCb(); - + if (!collection[service][one][two]) collection[service][one][two] = {}; processTopCall(collection[service][one][two], service, innerCallObj, innerCb); }, function() { diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js index 6c6b294e60..93d5d39649 100644 --- a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js +++ b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js @@ -9,12 +9,22 @@ module.exports = { more_info: 'Having the right key type set for your Azure Key Vault SSL certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', recommended_action: 'Ensure that Key Vault SSL certificates are using the allowed key types.', link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/certificate-access-control', - apis: ['vaults:list', 'vaults:getKeys'], + apis: ['vaults:list', 'vaults:getCertificates', 'getCertificatePolicy:get'], + settings: { + allowed_certificate_key_types: { + name: 'Key Vault Certificate Key Types', + description: 'Key types supported for certificates in Azure Key Vault', + regex: '^(RSA|EC)$' + } + }, run: function(cache, settings, callback) { var results = []; var source = {}; var locations = helpers.locations(settings.govcloud); + var config = { + allowed_certificate_key_types: settings.allowed_certificate_key_types || this.settings.allowed_certificate_key_types, + }; async.each(locations.vaults, function(location, rcb) { var vaults = helpers.addSource(cache, source, @@ -33,30 +43,33 @@ module.exports = { } vaults.data.forEach((vault) => { - var keys = helpers.addSource(cache, source, - ['vaults', 'getKeys', location, vault.id]); + var certificates = helpers.addSource(cache, source, + ['vaults', 'getCertificates', location, vault.id]); - if (!keys || keys.err || !keys.data) { - helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); - } else if (!keys.data.length) { - helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); + if (!certificates || certificates.err || !certificates.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault certificates: ' + helpers.addError(certificates), location, vault.id); + } else if (!certificates.data.length) { + helpers.addResult(results, 0, 'No Key Vault Certificates found', location, vault.id); } else { - keys.data.forEach((key) => { - var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); - var keyId = `${vault.id}/keys/${keyName}`; + certificates.data.forEach((certificate) => { + var certificatePolicy = helpers.addSource(cache, source, + ['getCertificatePolicy', 'get', location, certificate.id]); - if (key.attributes) { - let attributes = key.attributes; - if ((attributes.expires && attributes.expires !== null && attributes.expires !== '') || (attributes.exp && attributes.exp !== null && attributes.exp !== '')) { - helpers.addResult(results, 0, - 'Expiry date is set for the key', location, keyId); + if (!certificatePolicy || certificatePolicy.err || !certificatePolicy.data) { + helpers.addResult(results, 3, 'Unable to query for Certificate Policy: ' + helpers.addError(certificatePolicy), location, certificate.id); + } else { + const certificateKeys = certificatePolicy.data.key_props; + if (certificateKeys && certificateKeys.kty) { + const allowedCertTypesRegex = new RegExp(config.allowed_certificate_key_types.regex); + + if (allowedCertTypesRegex.test(certificateKeys.kty)) { + helpers.addResult(results, 0, 'Certificate key type is set to Allowed Key Types: ' + certificateKeys.kty, location, certificate.id); + } else { + helpers.addResult(results, 2, 'Certificate key type is not set to Allowed Key Types: ' + certificateKeys.kty, location, certificate.id); + } } else { - helpers.addResult(results, 2, - 'Expiry date is not set for the key', location, keyId); + helpers.addResult(results, 3, 'Unable to list key type for Key Vault Certificate: ' + helpers.addError(certificatePolicy), location, certificate.id); } - } else { - helpers.addResult(results, 2, - 'Expiry date is not set for the key', location, keyId); } }); } diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js index 7d048cb2f5..0d54d7b70a 100644 --- a/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js +++ b/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js @@ -1,5 +1,5 @@ var expect = require('chai').expect; -var auth = require('./secretExpirationEnabled'); +var auth = require('./allowedCertificateKeyTypes'); const listVaults = [ { @@ -12,86 +12,70 @@ const listVaults = [ "family": "A", "name": "Standard" } - }, - { - "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", - "name": "testvault", - "type": "Microsoft.KeyVault/vaults", - "location": "eastus", - "tags": {}, - "sku": { - "family": "A", - "name": "Standard" - } - }, + } +]; + +const certificates = [ { - "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", - "name": "testvault", - "type": "Microsoft.KeyVault/vaults", - "location": "eastus", - "tags": {}, - "sku": { - "family": "A", - "name": "Standard" - } + id: 'https://testvault.vault.azure.net/certificates/test-cert', + x5t: 'wi16heNOLNuStvVprwu6rzs0_is', + attributes: [Object], + tags: {}, + subject: '' } ]; -const getKeys = [ +const certificatePolicy = [ { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": true, - "exp": null, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] - } + id: 'https://testvault.vault.azure.net/certificates/test-cert/policy', + key_props: { exportable: true, kty: 'RSA', key_size: 2048, reuse_key: false }, + secret_props: { contentType: 'application/x-pkcs12' }, + x509_props: { + subject: 'CN=test.com', + sans: [Object], + ekus: [Array], + key_usage: [Array], + validity_months: 12, + basic_constraints: [Object] + }, + lifetime_actions: [ [Object] ], + issuer: { name: 'Self' }, + attributes: { enabled: true, created: 1649758944, updated: 1649758944 } }, { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": true, - "exp": 1635448252, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] - } + id: 'https://testvault.vault.azure.net/certificates/test-cert/policy', + secret_props: { contentType: 'application/x-pkcs12' }, + x509_props: { + subject: 'CN=test.com', + sans: [Object], + ekus: [Array], + key_usage: [Array], + validity_months: 12, + basic_constraints: [Object] + }, + lifetime_actions: [ [Object] ], + issuer: { name: 'Self' }, + attributes: { enabled: true, created: 1649758944, updated: 1649758944 } }, { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": false, - "exp": 1635448252, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] - } + id: 'https://testvault.vault.azure.net/certificates/test-cert/policy', + secret_props: { contentType: 'application/x-pkcs12' }, + key_props: { exportable: true, kty: 'ECC', key_size: 2048, reuse_key: false }, + x509_props: { + subject: 'CN=test.com', + sans: [Object], + ekus: [Array], + key_usage: [Array], + validity_months: 12, + basic_constraints: [Object] + }, + lifetime_actions: [ [Object] ], + issuer: { name: 'Self' }, + attributes: { enabled: true, created: 1649758944, updated: 1649758944 } } ]; -const createCache = (err, list, get) => { +const createCache = (err, list, certs, getCertificatePolicy) => { return { vaults: { list: { @@ -100,16 +84,21 @@ const createCache = (err, list, get) => { data: list } }, - getSecrets: { - 'eastus': get + getCertificates: { + 'eastus': certs + } + }, + getCertificatePolicy: { + get: { + 'eastus': getCertificatePolicy } } } }; -describe('secretExpirationEnabled', function() { +describe('allowedCertificateKeyTypes', function() { describe('run', function() { - it('should give passing result if no secrets found', function(done) { + it('should give passing result if no key vaults found', function(done) { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); @@ -118,43 +107,91 @@ describe('secretExpirationEnabled', function() { done() }; - auth.run(createCache(null, [], {}), {}, callback); + auth.run(createCache(null, [], {}, {}), {}, callback); }); - it('should give failing result if expiration is not set on secrets', function(done) { + it('should give unkown result if Unable to query for Key Vaults', 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('Expiry date is not set for the secret'); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('Unable to query for Key Vaults'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listVaults[0]], getKeys[0]), {}, callback); + auth.run(createCache(null, null, {}, {}), {}, callback); }); - it('should give passing result if expiration is set on keys', function(done) { + it('should give passing result if no key vault certificates 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('Expiry date is set for the secret'); + expect(results[0].message).to.include('No Key Vault Certificates found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [] } }, {}), {}, callback); + }); + + it('should give unkown result if unable to query for Key Vault Certificates', 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 Key Vault certificates'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listVaults[1]], getKeys[1]), {}, callback); + auth.run(createCache(null, [listVaults[0]], null, {}), {}, callback); }); - it('should give passing result if key is disabled', function(done) { + it('should give unknown results if unable to query for certificate policy', 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 Certificate Policy'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [certificates] } }, {}), {}, callback); + }); + + it('should give unknown results if Unable to list key type for Key Vault Certificate', 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 list key type for Key Vault Certificate'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [certificates] } }, { data: [certificatePolicy[1]] } ), {}, callback); + }); + + it('should give passing result if certificate has allowed key type', 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('The secret is disabled'); + expect(results[0].message).to.include('Certificate key type is set to Allowed Key Types: RSA'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [certificates] } }, { data: { ...certificatePolicy[0] } } ), {}, callback); + }); + + it('should give failing result if certificate does not have allowed key type', 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('Certificate key type is not set to Allowed Key Types: ECC'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listVaults[2]], getKeys[2]), {}, callback); - }) + auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [certificates] } }, { data: { ...certificatePolicy[2] } } ), {}, callback); + }); }) }); From ed9402cc8e292a0dfed8f691c28a74af5f6e45e7 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Wed, 6 Apr 2022 03:24:05 +0500 Subject: [PATCH 075/350] Added cmkCreationForAppTier plugin and spec --- exports.js | 1 + .../azure/keyvaults/cmkCreationForAppTier.js | 70 ++++++++ .../keyvaults/cmkCreationForAppTier.spec.js | 160 ++++++++++++++++++ 3 files changed, 231 insertions(+) create mode 100644 plugins/azure/keyvaults/cmkCreationForAppTier.js create mode 100644 plugins/azure/keyvaults/cmkCreationForAppTier.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..aaafa2c844 100644 --- a/exports.js +++ b/exports.js @@ -755,6 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), + 'cmkCreationForAppTier' : require(__dirname + '/plugins/azure/keyvaults/cmkCreationForAppTier.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/cmkCreationForAppTier.js b/plugins/azure/keyvaults/cmkCreationForAppTier.js new file mode 100644 index 0000000000..883cd73382 --- /dev/null +++ b/plugins/azure/keyvaults/cmkCreationForAppTier.js @@ -0,0 +1,70 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'CMK Creation for App Tier Enabled', + category: 'Key Vaults', + domain: 'Identity and Access Management', + description: 'Ensure that a Customer-Managed Key (CMK) is created and configured for your Microsoft Azure application tier.', + more_info: 'Setting a CMK for app tier, you gain full control over who can use this key to access the application data, implementing the principle of least privilege on the encryption key ownership and usage.', + recommended_action: 'Ensure each Key Vault has an expiry time set that provides for sufficient rotation.', + link: 'https://docs.microsoft.com/en-us/azure/azure-app-configuration/concept-customer-managed-keys', + apis: ['vaults:list', 'vaults:getKeys'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.vaults, function(location, rcb) { + var vaults = helpers.addSource(cache, source, + ['vaults', 'list', location]); + + if (!vaults) return rcb(); + + if (vaults.err || !vaults.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); + return rcb(); + } + + if (!vaults.data.length) { + helpers.addResult(results, 0, 'No Key Vaults found', location); + return rcb(); + } + + vaults.data.forEach((vault) => { + var keys = helpers.addSource(cache, source, + ['vaults', 'getKeys', location, vault.id]); + + if (!keys || keys.err || !keys.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); + } else if (!keys.data.length) { + helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); + } else { + keys.data.forEach((key) => { + var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); + var keyId = `${vault.id}/keys/${keyName}`; + + if (key.attributes) { + let attributes = key.attributes; + if ((attributes.expires && attributes.expires !== null && attributes.expires !== '') || (attributes.exp && attributes.exp !== null && attributes.exp !== '')) { + helpers.addResult(results, 0, + 'Expiry date is set for the key', location, keyId); + } else { + helpers.addResult(results, 2, + 'Expiry date is not set for the key', location, keyId); + } + } else { + helpers.addResult(results, 2, + 'Expiry date is not set for the key', location, keyId); + } + }); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js b/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js new file mode 100644 index 0000000000..7d048cb2f5 --- /dev/null +++ b/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js @@ -0,0 +1,160 @@ +var expect = require('chai').expect; +var auth = require('./secretExpirationEnabled'); + +const listVaults = [ + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + }, + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + }, + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + } +]; + +const getKeys = [ + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "exp": null, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + }, + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "exp": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + }, + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": false, + "exp": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + } +]; + +const createCache = (err, list, get) => { + return { + vaults: { + list: { + 'eastus': { + err: err, + data: list + } + }, + getSecrets: { + 'eastus': get + } + } + } +}; + +describe('secretExpirationEnabled', function() { + describe('run', function() { + it('should give passing result if no secrets 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 Key Vaults found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [], {}), {}, callback); + }); + + it('should give failing result if expiration is not set on secrets', 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('Expiry date is not set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], getKeys[0]), {}, callback); + }); + + it('should give passing result if expiration is set on keys', 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('Expiry date is set for the secret'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[1]], getKeys[1]), {}, callback); + }); + + it('should give passing result if key is disabled', 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('The secret is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[2]], getKeys[2]), {}, callback); + }) + }) +}); From d003f6e9f5254f48c91f92e87a5e18829dd88b62 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 10 Apr 2022 03:04:07 +0500 Subject: [PATCH 076/350] Updated recommended_action --- plugins/azure/keyvaults/cmkCreationForAppTier.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/keyvaults/cmkCreationForAppTier.js b/plugins/azure/keyvaults/cmkCreationForAppTier.js index 883cd73382..09d53f8cdf 100644 --- a/plugins/azure/keyvaults/cmkCreationForAppTier.js +++ b/plugins/azure/keyvaults/cmkCreationForAppTier.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Identity and Access Management', description: 'Ensure that a Customer-Managed Key (CMK) is created and configured for your Microsoft Azure application tier.', more_info: 'Setting a CMK for app tier, you gain full control over who can use this key to access the application data, implementing the principle of least privilege on the encryption key ownership and usage.', - recommended_action: 'Ensure each Key Vault has an expiry time set that provides for sufficient rotation.', + recommended_action: 'Ensure each Key Vault has a CMK created and configured.', link: 'https://docs.microsoft.com/en-us/azure/azure-app-configuration/concept-customer-managed-keys', apis: ['vaults:list', 'vaults:getKeys'], From 0e60b716b04f352ab260ed556ce874cededd68ed Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Tue, 19 Apr 2022 00:36:00 +0500 Subject: [PATCH 077/350] Changed settings allowedCert Types --- plugins/azure/keyvaults/allowedCertificateKeyTypes.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js index 93d5d39649..fd69d27843 100644 --- a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js +++ b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js @@ -14,7 +14,8 @@ module.exports = { allowed_certificate_key_types: { name: 'Key Vault Certificate Key Types', description: 'Key types supported for certificates in Azure Key Vault', - regex: '^(RSA|EC)$' + regex: '^(RSA|EC)$', + default: 'RSA' } }, From cb1f12203125b9f9813a1389a9dda5b41ea7d7a2 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Wed, 20 Apr 2022 21:12:13 +0500 Subject: [PATCH 078/350] Added EC2 Instances Optimized Plugin --- exports.js | 988 +++++++++--------- helpers/aws/api.js | 6 + helpers/aws/regions.js | 3 +- .../computeoptimizer/ec2InstancesOptimized.js | 65 ++ .../ec2InstancesOptimized.spec.js | 117 +++ 5 files changed, 685 insertions(+), 494 deletions(-) create mode 100644 plugins/aws/computeoptimizer/ec2InstancesOptimized.js create mode 100644 plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..29fb5cd71f 100644 --- a/exports.js +++ b/exports.js @@ -2,543 +2,545 @@ module.exports = { aws : { - 'accessAnalyzerEnabled' : require(__dirname + '/plugins/aws/accessanalyzer/accessAnalyzerEnabled.js'), - 'accessAnalyzerActiveFindings' : require(__dirname + '/plugins/aws/accessanalyzer/accessAnalyzerActiveFindings.js'), + // 'accessAnalyzerEnabled' : require(__dirname + '/plugins/aws/accessanalyzer/accessAnalyzerEnabled.js'), + // 'accessAnalyzerActiveFindings' : require(__dirname + '/plugins/aws/accessanalyzer/accessAnalyzerActiveFindings.js'), - 'acmValidation' : require(__dirname + '/plugins/aws/acm/acmValidation.js'), - 'acmCertificateExpiry' : require(__dirname + '/plugins/aws/acm/acmCertificateExpiry.js'), - 'acmSingleDomainNameCertificate': require(__dirname + '/plugins/aws/acm/acmSingleDomainNameCertificate.js'), + // 'acmValidation' : require(__dirname + '/plugins/aws/acm/acmValidation.js'), + // 'acmCertificateExpiry' : require(__dirname + '/plugins/aws/acm/acmCertificateExpiry.js'), + // 'acmSingleDomainNameCertificate': require(__dirname + '/plugins/aws/acm/acmSingleDomainNameCertificate.js'), - 'appmeshVGAccessLogging' : require(__dirname + '/plugins/aws/appmesh/appmeshVGAccessLogging.js'), + // 'appmeshVGAccessLogging' : require(__dirname + '/plugins/aws/appmesh/appmeshVGAccessLogging.js'), - 'apigatewayCertificateRotation' : require(__dirname + '/plugins/aws/apigateway/apigatewayCertificateRotation.js'), - 'apigatewayCloudwatchLogs' : require(__dirname + '/plugins/aws/apigateway/apigatewayCloudwatchLogs.js'), - 'apigatewayPrivateEndpoints' : require(__dirname + '/plugins/aws/apigateway/apigatewayPrivateEndpoints.js'), - 'apigatewayContentEncoding' : require(__dirname + '/plugins/aws/apigateway/apigatewayContentEncoding.js'), - 'apigatewayTracingEnabled' : require(__dirname + '/plugins/aws/apigateway/apigatewayTracingEnabled.js'), - 'apigatewayWafEnabled' : require(__dirname + '/plugins/aws/apigateway/apigatewayWafEnabled.js'), - 'detailedCloudWatchMetrics' : require(__dirname + '/plugins/aws/apigateway/detailedCloudWatchMetrics.js'), - 'apigatewayClientCertificate' : require(__dirname + '/plugins/aws/apigateway/apigatewayClientCertificate.js'), - 'apigatewayResponseCaching' : require(__dirname + '/plugins/aws/apigateway/apigatewayResponseCaching.js'), - 'apiStageLevelCacheEncryption' : require(__dirname + '/plugins/aws/apigateway/apiStageLevelCacheEncryption.js'), - - 'restrictExternalTraffic' : require(__dirname + '/plugins/aws/appmesh/restrictExternalTraffic.js'), - 'appmeshTLSRequired' : require(__dirname + '/plugins/aws/appmesh/appmeshTLSRequired.js'), - - 'asgMultiAz' : require(__dirname + '/plugins/aws/autoscaling/asgMultiAz.js'), - 'asgActiveNotifications' : require(__dirname + '/plugins/aws/autoscaling/asgActiveNotifications.js'), - 'asgCooldownPeriod' : require(__dirname + '/plugins/aws/autoscaling/asgCooldownPeriod.js'), - 'emptyASG' : require(__dirname + '/plugins/aws/autoscaling/emptyASG.js'), - 'sameAzElb' : require(__dirname + '/plugins/aws/autoscaling/sameAzElb.js'), - 'asgMissingELB' : require(__dirname + '/plugins/aws/autoscaling/asgMissingELB.js'), - 'webTierAsgAssociatedElb' : require(__dirname + '/plugins/aws/autoscaling/webTierAsgAssociatedElb.js'), - 'elbHealthCheckActive' : require(__dirname + '/plugins/aws/autoscaling/elbHealthCheckActive.js'), - 'asgSuspendedProcesses' : require(__dirname + '/plugins/aws/autoscaling/asgSuspendedProcesses.js'), - 'appTierAsgApprovedAmi' : require(__dirname + '/plugins/aws/autoscaling/appTierAsgApprovedAmi.js'), - 'webTierAsgApprovedAmi' : require(__dirname + '/plugins/aws/autoscaling/webTierAsgApprovedAmi.js'), - 'appTierAsgCloudwatchLogs' : require(__dirname + '/plugins/aws/autoscaling/appTierAsgCloudwatchLogs.js'), - 'webTierAsgCloudwatchLogs' : require(__dirname + '/plugins/aws/autoscaling/webTierAsgCloudwatchLogs.js'), - 'asgMissingSecurityGroups' : require(__dirname + '/plugins/aws/autoscaling/asgMissingSecurityGroups.js'), - 'webTierIamRole' : require(__dirname + '/plugins/aws/autoscaling/webTierIamRole.js'), - 'appTierIamRole' : require(__dirname + '/plugins/aws/autoscaling/appTierIamRole.js'), - 'asgUnusedLaunchConfiguration' : require(__dirname + '/plugins/aws/autoscaling/asgUnusedLaunchConfiguration.js'), - - 'workgroupEncrypted' : require(__dirname + '/plugins/aws/athena/workgroupEncrypted.js'), - 'workgroupEnforceConfiguration' : require(__dirname + '/plugins/aws/athena/workgroupEnforceConfiguration.js'), - - 'publicS3Origin' : require(__dirname + '/plugins/aws/cloudfront/publicS3Origin.js'), - 'secureOrigin' : require(__dirname + '/plugins/aws/cloudfront/secureOrigin.js'), - 'insecureProtocols' : require(__dirname + '/plugins/aws/cloudfront/insecureProtocols.js'), - 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), - 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), - 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), - 'cloudfrontFieldLevelEncryption': require(__dirname + '/plugins/aws/cloudfront/cloudfrontFieldLevelEncryption.js'), - 'cloudfrontInUse' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontInUse.js'), - 'enableOriginFailOver' : require(__dirname + '/plugins/aws/cloudfront/enableOriginFailOver.js'), - 'cloudfrontGeoRestriction' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontGeoRestriction.js'), - 'compressObjectsAutomatically' : require(__dirname + '/plugins/aws/cloudfront/compressObjectsAutomatically.js'), - - 'volumeEncryption' : require(__dirname + '/plugins/aws/comprehend/volumeEncryption.js'), - 'outputResultEncryption' : require(__dirname + '/plugins/aws/comprehend/outputResultEncryption.js'), - - 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), - 'stackFailedStatus' : require(__dirname + '/plugins/aws/cloudformation/stackFailedStatus.js'), - 'driftDetection' : require(__dirname + '/plugins/aws/cloudformation/driftDetection.js'), - 'stackTerminationProtection' : require(__dirname + '/plugins/aws/cloudformation/stackTerminationProtection.js'), - 'stackNotifications' : require(__dirname + '/plugins/aws/cloudformation/stackNotifications.js'), - 'cloudformationAdminPriviliges' : require(__dirname + '/plugins/aws/cloudformation/cloudformationAdminPriviliges.js'), - 'cloudformationInUse' : require(__dirname + '/plugins/aws/cloudformation/cloudformationInUse.js'), - - 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), - 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), - 'cloudtrailDataEvents' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailDataEvents.js'), - 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), - 'cloudtrailEncryption' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEncryption.js'), - 'cloudtrailFileValidation' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailFileValidation.js'), - 'cloudtrailObjectLock' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailObjectLock.js'), - 'cloudtrailToCloudwatch' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailToCloudwatch.js'), - 'cloudtrailBucketPrivate' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js'), - 'cloudtrailDeliveryFailing' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailDeliveryFailing.js'), - 'cloudtrailManagementEvents' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailManagementEvents.js'), - 'cloudtrailS3Bucket' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailS3Bucket.js'), - 'globalLoggingDuplicated' : require(__dirname + '/plugins/aws/cloudtrail/globalLoggingDuplicated.js'), - 'cloudtrailNotificationsEnabled': require(__dirname + '/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js'), - - 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), - 'configComplaintRules' : require(__dirname + '/plugins/aws/configservice/configComplaintRules.js'), - 'configDeliveryFailing' : require(__dirname + '/plugins/aws/configservice/configDeliveryFailing.js'), - 'configServiceMissingBucket' : require(__dirname + '/plugins/aws/configservice/configServiceMissingBucket.js'), - - 'devOpsGuruNotificationEnabled' : require(__dirname + '/plugins/aws/devopsguru/devOpsGuruNotificationEnabled.js'), + // 'apigatewayCertificateRotation' : require(__dirname + '/plugins/aws/apigateway/apigatewayCertificateRotation.js'), + // 'apigatewayCloudwatchLogs' : require(__dirname + '/plugins/aws/apigateway/apigatewayCloudwatchLogs.js'), + // 'apigatewayPrivateEndpoints' : require(__dirname + '/plugins/aws/apigateway/apigatewayPrivateEndpoints.js'), + // 'apigatewayContentEncoding' : require(__dirname + '/plugins/aws/apigateway/apigatewayContentEncoding.js'), + // 'apigatewayTracingEnabled' : require(__dirname + '/plugins/aws/apigateway/apigatewayTracingEnabled.js'), + // 'apigatewayWafEnabled' : require(__dirname + '/plugins/aws/apigateway/apigatewayWafEnabled.js'), + // 'detailedCloudWatchMetrics' : require(__dirname + '/plugins/aws/apigateway/detailedCloudWatchMetrics.js'), + // 'apigatewayClientCertificate' : require(__dirname + '/plugins/aws/apigateway/apigatewayClientCertificate.js'), + // 'apigatewayResponseCaching' : require(__dirname + '/plugins/aws/apigateway/apigatewayResponseCaching.js'), + // 'apiStageLevelCacheEncryption' : require(__dirname + '/plugins/aws/apigateway/apiStageLevelCacheEncryption.js'), + + // 'restrictExternalTraffic' : require(__dirname + '/plugins/aws/appmesh/restrictExternalTraffic.js'), + // 'appmeshTLSRequired' : require(__dirname + '/plugins/aws/appmesh/appmeshTLSRequired.js'), + + // 'asgMultiAz' : require(__dirname + '/plugins/aws/autoscaling/asgMultiAz.js'), + // 'asgActiveNotifications' : require(__dirname + '/plugins/aws/autoscaling/asgActiveNotifications.js'), + // 'asgCooldownPeriod' : require(__dirname + '/plugins/aws/autoscaling/asgCooldownPeriod.js'), + // 'emptyASG' : require(__dirname + '/plugins/aws/autoscaling/emptyASG.js'), + // 'sameAzElb' : require(__dirname + '/plugins/aws/autoscaling/sameAzElb.js'), + // 'asgMissingELB' : require(__dirname + '/plugins/aws/autoscaling/asgMissingELB.js'), + // 'webTierAsgAssociatedElb' : require(__dirname + '/plugins/aws/autoscaling/webTierAsgAssociatedElb.js'), + // 'elbHealthCheckActive' : require(__dirname + '/plugins/aws/autoscaling/elbHealthCheckActive.js'), + // 'asgSuspendedProcesses' : require(__dirname + '/plugins/aws/autoscaling/asgSuspendedProcesses.js'), + // 'appTierAsgApprovedAmi' : require(__dirname + '/plugins/aws/autoscaling/appTierAsgApprovedAmi.js'), + // 'webTierAsgApprovedAmi' : require(__dirname + '/plugins/aws/autoscaling/webTierAsgApprovedAmi.js'), + // 'appTierAsgCloudwatchLogs' : require(__dirname + '/plugins/aws/autoscaling/appTierAsgCloudwatchLogs.js'), + // 'webTierAsgCloudwatchLogs' : require(__dirname + '/plugins/aws/autoscaling/webTierAsgCloudwatchLogs.js'), + // 'asgMissingSecurityGroups' : require(__dirname + '/plugins/aws/autoscaling/asgMissingSecurityGroups.js'), + // 'webTierIamRole' : require(__dirname + '/plugins/aws/autoscaling/webTierIamRole.js'), + // 'appTierIamRole' : require(__dirname + '/plugins/aws/autoscaling/appTierIamRole.js'), + // 'asgUnusedLaunchConfiguration' : require(__dirname + '/plugins/aws/autoscaling/asgUnusedLaunchConfiguration.js'), + + // 'workgroupEncrypted' : require(__dirname + '/plugins/aws/athena/workgroupEncrypted.js'), + // 'workgroupEnforceConfiguration' : require(__dirname + '/plugins/aws/athena/workgroupEnforceConfiguration.js'), + + // 'publicS3Origin' : require(__dirname + '/plugins/aws/cloudfront/publicS3Origin.js'), + // 'secureOrigin' : require(__dirname + '/plugins/aws/cloudfront/secureOrigin.js'), + // 'insecureProtocols' : require(__dirname + '/plugins/aws/cloudfront/insecureProtocols.js'), + // 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), + // 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), + // 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), + // 'cloudfrontFieldLevelEncryption': require(__dirname + '/plugins/aws/cloudfront/cloudfrontFieldLevelEncryption.js'), + // 'cloudfrontInUse' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontInUse.js'), + // 'enableOriginFailOver' : require(__dirname + '/plugins/aws/cloudfront/enableOriginFailOver.js'), + // 'cloudfrontGeoRestriction' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontGeoRestriction.js'), + // 'compressObjectsAutomatically' : require(__dirname + '/plugins/aws/cloudfront/compressObjectsAutomatically.js'), + + // 'volumeEncryption' : require(__dirname + '/plugins/aws/comprehend/volumeEncryption.js'), + // 'outputResultEncryption' : require(__dirname + '/plugins/aws/comprehend/outputResultEncryption.js'), + + // 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), + // 'stackFailedStatus' : require(__dirname + '/plugins/aws/cloudformation/stackFailedStatus.js'), + // 'driftDetection' : require(__dirname + '/plugins/aws/cloudformation/driftDetection.js'), + // 'stackTerminationProtection' : require(__dirname + '/plugins/aws/cloudformation/stackTerminationProtection.js'), + // 'stackNotifications' : require(__dirname + '/plugins/aws/cloudformation/stackNotifications.js'), + // 'cloudformationAdminPriviliges' : require(__dirname + '/plugins/aws/cloudformation/cloudformationAdminPriviliges.js'), + // 'cloudformationInUse' : require(__dirname + '/plugins/aws/cloudformation/cloudformationInUse.js'), + + // 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), + // 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), + // 'cloudtrailDataEvents' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailDataEvents.js'), + // 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), + // 'cloudtrailEncryption' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEncryption.js'), + // 'cloudtrailFileValidation' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailFileValidation.js'), + // 'cloudtrailObjectLock' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailObjectLock.js'), + // 'cloudtrailToCloudwatch' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailToCloudwatch.js'), + // 'cloudtrailBucketPrivate' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js'), + // 'cloudtrailDeliveryFailing' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailDeliveryFailing.js'), + // 'cloudtrailManagementEvents' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailManagementEvents.js'), + // 'cloudtrailS3Bucket' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailS3Bucket.js'), + // 'globalLoggingDuplicated' : require(__dirname + '/plugins/aws/cloudtrail/globalLoggingDuplicated.js'), + // 'cloudtrailNotificationsEnabled': require(__dirname + '/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js'), + + // 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), + // 'configComplaintRules' : require(__dirname + '/plugins/aws/configservice/configComplaintRules.js'), + // 'configDeliveryFailing' : require(__dirname + '/plugins/aws/configservice/configDeliveryFailing.js'), + // 'configServiceMissingBucket' : require(__dirname + '/plugins/aws/configservice/configServiceMissingBucket.js'), + + 'ec2InstancesOptimized' : require(__dirname + '/plugins/aws/computeoptimizer/ec2InstancesOptimized.js'), + + // 'devOpsGuruNotificationEnabled' : require(__dirname + '/plugins/aws/devopsguru/devOpsGuruNotificationEnabled.js'), - 'dmsEncryptionEnabled' : require(__dirname + '/plugins/aws/dms/dmsEncryptionEnabled.js'), - 'dmsPubliclyAccessibleInstances': require(__dirname + '/plugins/aws/dms/dmsPubliclyAccessibleInstances.js'), - 'dmsMultiAZFeatureEnabled' : require(__dirname + '/plugins/aws/dms/dmsMultiAZFeatureEnabled.js'), - 'autoMinorVersionUpgrade' : require(__dirname + '/plugins/aws/dms/autoMinorVersionUpgrade.js'), - - 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), - 'daxClusterEncryption' : require(__dirname + '/plugins/aws/dynamodb/daxClusterEncryption.js'), - 'dynamoContinuousBackups' : require(__dirname + '/plugins/aws/dynamodb/dynamoContinuousBackups.js'), - 'dynamoTableBackupExists' : require(__dirname + '/plugins/aws/dynamodb/dynamoTableBackupExists.js'), - - 'appTierInstanceIamRole' : require(__dirname + '/plugins/aws/ec2/appTierInstanceIamRole.js'), - 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), - 'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'), - 'securityGroupRfc1918' : require(__dirname + '/plugins/aws/ec2/securityGroupRfc1918.js'), - 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), - 'unassociatedElasticIp' : require(__dirname + '/plugins/aws/ec2/unassociatedElasticIp.js'), - 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), - 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), - 'instanceLimit' : require(__dirname + '/plugins/aws/ec2/instanceLimit.js'), - 'instanceVcpusLimit' : require(__dirname + '/plugins/aws/ec2/instanceVcpusLimit.js'), - 'instanceMaxCount' : require(__dirname + '/plugins/aws/ec2/instanceMaxCount.js'), - 'instanceKeyBasedLogin' : require(__dirname + '/plugins/aws/ec2/instanceKeyBasedLogin.js'), - 'openAllPortsProtocols' : require(__dirname + '/plugins/aws/ec2/openAllPortsProtocols.js'), - 'openCIFS' : require(__dirname + '/plugins/aws/ec2/openCIFS.js'), - 'openCustomPorts' : require(__dirname + '/plugins/aws/ec2/openCustomPorts.js'), - 'openDNS' : require(__dirname + '/plugins/aws/ec2/openDNS.js'), - 'openDocker' : require(__dirname + '/plugins/aws/ec2/openDocker.js'), - 'openFTP' : require(__dirname + '/plugins/aws/ec2/openFTP.js'), - 'openHadoopNameNode' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNode.js'), - 'openHadoopNameNodeWebUI' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNodeWebUI.js'), - 'openOracleAutoDataWarehouse' : require(__dirname + '/plugins/aws/ec2/openOracleAutoDataWarehouse.js'), - 'openKibana' : require(__dirname + '/plugins/aws/ec2/openKibana.js'), - 'openMySQL' : require(__dirname + '/plugins/aws/ec2/openMySQL.js'), - 'openOracle' : require(__dirname + '/plugins/aws/ec2/openOracle.js'), - 'openNetBIOS' : require(__dirname + '/plugins/aws/ec2/openNetBIOS.js'), - 'openPostgreSQL' : require(__dirname + '/plugins/aws/ec2/openPostgreSQL.js'), - 'openRDP' : require(__dirname + '/plugins/aws/ec2/openRDP.js'), - 'openRPC' : require(__dirname + '/plugins/aws/ec2/openRPC.js'), - 'openSalt' : require(__dirname + '/plugins/aws/ec2/openSalt.js'), - 'openSMBoTCP' : require(__dirname + '/plugins/aws/ec2/openSMBoTCP.js'), - 'openSMTP' : require(__dirname + '/plugins/aws/ec2/openSMTP.js'), - 'openSQLServer' : require(__dirname + '/plugins/aws/ec2/openSQLServer.js'), - 'openSSH' : require(__dirname + '/plugins/aws/ec2/openSSH.js'), - 'openTelnet' : require(__dirname + '/plugins/aws/ec2/openTelnet.js'), - 'openVNCClient' : require(__dirname + '/plugins/aws/ec2/openVNCClient.js'), - 'openVNCServer' : require(__dirname + '/plugins/aws/ec2/openVNCServer.js'), - 'openElasticsearch' : require(__dirname + '/plugins/aws/ec2/openElasticsearch.js'), - 'vpcElasticIpLimit' : require(__dirname + '/plugins/aws/ec2/vpcElasticIpLimit.js'), - 'classicInstances' : require(__dirname + '/plugins/aws/ec2/classicInstances.js'), - 'flowLogsEnabled' : require(__dirname + '/plugins/aws/ec2/flowLogsEnabled.js'), - 'vpcMultipleSubnets' : require(__dirname + '/plugins/aws/ec2/multipleSubnets.js'), - 'overlappingSecurityGroups' : require(__dirname + '/plugins/aws/ec2/overlappingSecurityGroups.js'), - 'publicAmi' : require(__dirname + '/plugins/aws/ec2/publicAmi.js'), - 'encryptedAmi' : require(__dirname + '/plugins/aws/ec2/encryptedAmi.js'), - 'instanceIamRole' : require(__dirname + '/plugins/aws/ec2/instanceIamRole.js'), - 'ebsBackupEnabled' : require(__dirname + '/plugins/aws/ec2/ebsBackupEnabled.js'), - 'ebsEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsEncryptionEnabled.js'), - 'ebsSnapshotLifecycle' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotLifecycle.js'), - 'ebsOldSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsOldSnapshots.js'), - 'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'), - 'ebsSnapshotPublic' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPublic.js'), - 'unusedSecurityGroups' : require(__dirname + '/plugins/aws/ec2/unusedSecurityGroups.js'), - - 'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'), - 'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'), - 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), - 'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'), - 'vpcEndpointAcceptance' : require(__dirname + '/plugins/aws/ec2/vpcEndpointAcceptance'), - 'vpcEndpointExposed' : require(__dirname + '/plugins/aws/ec2/vpcEndpointExposed.js'), - 'vpcEndpointCrossAccount' : require(__dirname + '/plugins/aws/ec2/vpcEndpointCrossAccount.js'), - 'vpcPeeringConnections' : require(__dirname + '/plugins/aws/ec2/vpcPeeringConnections.js'), - 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), - 'ebsDefaultEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsDefaultEncryptionEnabled.js'), - 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), - 'unusedEni' : require(__dirname + '/plugins/aws/ec2/unusedEni.js'), - 'unusedAmi' : require(__dirname + '/plugins/aws/ec2/unusedAmi.js'), - 'unusedVpcInternetGateways' : require(__dirname + '/plugins/aws/ec2/unusedVpcInternetGateways.js'), - 'managedNatGateway' : require(__dirname + '/plugins/aws/ec2/managedNatGateway.js'), - 'allowedCustomPorts' : require(__dirname + '/plugins/aws/ec2/allowedCustomPorts.js'), - 'ebsUnusedVolumes' : require(__dirname + '/plugins/aws/ec2/ebsUnusedVolumes.js'), - 'publicIpAddress' : require(__dirname + '/plugins/aws/ec2/publicIpAddress.js'), - 'unusedVirtualPrivateGateway' : require(__dirname + '/plugins/aws/ec2/unusedVirtualPrivateGateway.js'), - 'vpcSubnetInstancesPresent' : require(__dirname + '/plugins/aws/ec2/vpcSubnetInstancesPresent.js'), - 'webTierInstanceIamRole' : require(__dirname + '/plugins/aws/ec2/webTierInstanceIamRole.js'), - 'vpnTunnelState' : require(__dirname + '/plugins/aws/ec2/vpnTunnelState.js'), - 'networkAclOutboundTraffic' : require(__dirname + '/plugins/aws/ec2/networkAclOutboundTraffic.js'), - 'outdatedAmiInUse' : require(__dirname + '/plugins/aws/ec2/outdatedAmiInUse.js'), - - 'efsCmkEncrypted' : require(__dirname + '/plugins/aws/efs/efsCmkEncrypted.js'), - 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), - - 'ecrRepositoryPolicy' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryPolicy.js'), - 'ecrRepositoryEncrypted' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryEncrypted.js'), - 'ecrRepositoryTagImmutability' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryTagImmutability.js'), - - 'managedPlatformUpdates' : require(__dirname + '/plugins/aws/elasticbeanstalk/managedPlatformUpdates.js'), - 'enhancedHealthReporting' : require(__dirname + '/plugins/aws/elasticbeanstalk/enhancedHealthReporting.js'), - 'environmentAccessLogs' : require(__dirname + '/plugins/aws/elasticbeanstalk/environmentAccessLogs.js'), - 'environmentPersistentLogs' : require(__dirname + '/plugins/aws/elasticbeanstalk/environmentPersistentLogs.js'), - - 'eksKubernetesVersion' : require(__dirname + '/plugins/aws/eks/eksKubernetesVersion.js'), - 'eksLoggingEnabled' : require(__dirname + '/plugins/aws/eks/eksLoggingEnabled.js'), - 'eksPrivateEndpoint' : require(__dirname + '/plugins/aws/eks/eksPrivateEndpoint.js'), - 'eksSecretsEncrypted' : require(__dirname + '/plugins/aws/eks/eksSecretsEncrypted.js'), - 'eksSecurityGroups' : require(__dirname + '/plugins/aws/eks/eksSecurityGroups.js'), - 'eksLatestPlatformVersion' : require(__dirname + '/plugins/aws/eks/eksLatestPlatformVersion.js'), + // 'dmsEncryptionEnabled' : require(__dirname + '/plugins/aws/dms/dmsEncryptionEnabled.js'), + // 'dmsPubliclyAccessibleInstances': require(__dirname + '/plugins/aws/dms/dmsPubliclyAccessibleInstances.js'), + // 'dmsMultiAZFeatureEnabled' : require(__dirname + '/plugins/aws/dms/dmsMultiAZFeatureEnabled.js'), + // 'autoMinorVersionUpgrade' : require(__dirname + '/plugins/aws/dms/autoMinorVersionUpgrade.js'), + + // 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), + // 'daxClusterEncryption' : require(__dirname + '/plugins/aws/dynamodb/daxClusterEncryption.js'), + // 'dynamoContinuousBackups' : require(__dirname + '/plugins/aws/dynamodb/dynamoContinuousBackups.js'), + // 'dynamoTableBackupExists' : require(__dirname + '/plugins/aws/dynamodb/dynamoTableBackupExists.js'), + + // 'appTierInstanceIamRole' : require(__dirname + '/plugins/aws/ec2/appTierInstanceIamRole.js'), + // 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), + // 'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'), + // 'securityGroupRfc1918' : require(__dirname + '/plugins/aws/ec2/securityGroupRfc1918.js'), + // 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), + // 'unassociatedElasticIp' : require(__dirname + '/plugins/aws/ec2/unassociatedElasticIp.js'), + // 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), + // 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), + // 'instanceLimit' : require(__dirname + '/plugins/aws/ec2/instanceLimit.js'), + // 'instanceVcpusLimit' : require(__dirname + '/plugins/aws/ec2/instanceVcpusLimit.js'), + // 'instanceMaxCount' : require(__dirname + '/plugins/aws/ec2/instanceMaxCount.js'), + // 'instanceKeyBasedLogin' : require(__dirname + '/plugins/aws/ec2/instanceKeyBasedLogin.js'), + // 'openAllPortsProtocols' : require(__dirname + '/plugins/aws/ec2/openAllPortsProtocols.js'), + // 'openCIFS' : require(__dirname + '/plugins/aws/ec2/openCIFS.js'), + // 'openCustomPorts' : require(__dirname + '/plugins/aws/ec2/openCustomPorts.js'), + // 'openDNS' : require(__dirname + '/plugins/aws/ec2/openDNS.js'), + // 'openDocker' : require(__dirname + '/plugins/aws/ec2/openDocker.js'), + // 'openFTP' : require(__dirname + '/plugins/aws/ec2/openFTP.js'), + // 'openHadoopNameNode' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNode.js'), + // 'openHadoopNameNodeWebUI' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNodeWebUI.js'), + // 'openOracleAutoDataWarehouse' : require(__dirname + '/plugins/aws/ec2/openOracleAutoDataWarehouse.js'), + // 'openKibana' : require(__dirname + '/plugins/aws/ec2/openKibana.js'), + // 'openMySQL' : require(__dirname + '/plugins/aws/ec2/openMySQL.js'), + // 'openOracle' : require(__dirname + '/plugins/aws/ec2/openOracle.js'), + // 'openNetBIOS' : require(__dirname + '/plugins/aws/ec2/openNetBIOS.js'), + // 'openPostgreSQL' : require(__dirname + '/plugins/aws/ec2/openPostgreSQL.js'), + // 'openRDP' : require(__dirname + '/plugins/aws/ec2/openRDP.js'), + // 'openRPC' : require(__dirname + '/plugins/aws/ec2/openRPC.js'), + // 'openSalt' : require(__dirname + '/plugins/aws/ec2/openSalt.js'), + // 'openSMBoTCP' : require(__dirname + '/plugins/aws/ec2/openSMBoTCP.js'), + // 'openSMTP' : require(__dirname + '/plugins/aws/ec2/openSMTP.js'), + // 'openSQLServer' : require(__dirname + '/plugins/aws/ec2/openSQLServer.js'), + // 'openSSH' : require(__dirname + '/plugins/aws/ec2/openSSH.js'), + // 'openTelnet' : require(__dirname + '/plugins/aws/ec2/openTelnet.js'), + // 'openVNCClient' : require(__dirname + '/plugins/aws/ec2/openVNCClient.js'), + // 'openVNCServer' : require(__dirname + '/plugins/aws/ec2/openVNCServer.js'), + // 'openElasticsearch' : require(__dirname + '/plugins/aws/ec2/openElasticsearch.js'), + // 'vpcElasticIpLimit' : require(__dirname + '/plugins/aws/ec2/vpcElasticIpLimit.js'), + // 'classicInstances' : require(__dirname + '/plugins/aws/ec2/classicInstances.js'), + // 'flowLogsEnabled' : require(__dirname + '/plugins/aws/ec2/flowLogsEnabled.js'), + // 'vpcMultipleSubnets' : require(__dirname + '/plugins/aws/ec2/multipleSubnets.js'), + // 'overlappingSecurityGroups' : require(__dirname + '/plugins/aws/ec2/overlappingSecurityGroups.js'), + // 'publicAmi' : require(__dirname + '/plugins/aws/ec2/publicAmi.js'), + // 'encryptedAmi' : require(__dirname + '/plugins/aws/ec2/encryptedAmi.js'), + // 'instanceIamRole' : require(__dirname + '/plugins/aws/ec2/instanceIamRole.js'), + // 'ebsBackupEnabled' : require(__dirname + '/plugins/aws/ec2/ebsBackupEnabled.js'), + // 'ebsEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsEncryptionEnabled.js'), + // 'ebsSnapshotLifecycle' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotLifecycle.js'), + // 'ebsOldSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsOldSnapshots.js'), + // 'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'), + // 'ebsSnapshotPublic' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPublic.js'), + // 'unusedSecurityGroups' : require(__dirname + '/plugins/aws/ec2/unusedSecurityGroups.js'), + + // 'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'), + // 'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'), + // 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), + // 'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'), + // 'vpcEndpointAcceptance' : require(__dirname + '/plugins/aws/ec2/vpcEndpointAcceptance'), + // 'vpcEndpointExposed' : require(__dirname + '/plugins/aws/ec2/vpcEndpointExposed.js'), + // 'vpcEndpointCrossAccount' : require(__dirname + '/plugins/aws/ec2/vpcEndpointCrossAccount.js'), + // 'vpcPeeringConnections' : require(__dirname + '/plugins/aws/ec2/vpcPeeringConnections.js'), + // 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), + // 'ebsDefaultEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsDefaultEncryptionEnabled.js'), + // 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), + // 'unusedEni' : require(__dirname + '/plugins/aws/ec2/unusedEni.js'), + // 'unusedAmi' : require(__dirname + '/plugins/aws/ec2/unusedAmi.js'), + // 'unusedVpcInternetGateways' : require(__dirname + '/plugins/aws/ec2/unusedVpcInternetGateways.js'), + // 'managedNatGateway' : require(__dirname + '/plugins/aws/ec2/managedNatGateway.js'), + // 'allowedCustomPorts' : require(__dirname + '/plugins/aws/ec2/allowedCustomPorts.js'), + // 'ebsUnusedVolumes' : require(__dirname + '/plugins/aws/ec2/ebsUnusedVolumes.js'), + // 'publicIpAddress' : require(__dirname + '/plugins/aws/ec2/publicIpAddress.js'), + // 'unusedVirtualPrivateGateway' : require(__dirname + '/plugins/aws/ec2/unusedVirtualPrivateGateway.js'), + // 'vpcSubnetInstancesPresent' : require(__dirname + '/plugins/aws/ec2/vpcSubnetInstancesPresent.js'), + // 'webTierInstanceIamRole' : require(__dirname + '/plugins/aws/ec2/webTierInstanceIamRole.js'), + // 'vpnTunnelState' : require(__dirname + '/plugins/aws/ec2/vpnTunnelState.js'), + // 'networkAclOutboundTraffic' : require(__dirname + '/plugins/aws/ec2/networkAclOutboundTraffic.js'), + // 'outdatedAmiInUse' : require(__dirname + '/plugins/aws/ec2/outdatedAmiInUse.js'), + + // 'efsCmkEncrypted' : require(__dirname + '/plugins/aws/efs/efsCmkEncrypted.js'), + // 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), + + // 'ecrRepositoryPolicy' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryPolicy.js'), + // 'ecrRepositoryEncrypted' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryEncrypted.js'), + // 'ecrRepositoryTagImmutability' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryTagImmutability.js'), + + // 'managedPlatformUpdates' : require(__dirname + '/plugins/aws/elasticbeanstalk/managedPlatformUpdates.js'), + // 'enhancedHealthReporting' : require(__dirname + '/plugins/aws/elasticbeanstalk/enhancedHealthReporting.js'), + // 'environmentAccessLogs' : require(__dirname + '/plugins/aws/elasticbeanstalk/environmentAccessLogs.js'), + // 'environmentPersistentLogs' : require(__dirname + '/plugins/aws/elasticbeanstalk/environmentPersistentLogs.js'), + + // 'eksKubernetesVersion' : require(__dirname + '/plugins/aws/eks/eksKubernetesVersion.js'), + // 'eksLoggingEnabled' : require(__dirname + '/plugins/aws/eks/eksLoggingEnabled.js'), + // 'eksPrivateEndpoint' : require(__dirname + '/plugins/aws/eks/eksPrivateEndpoint.js'), + // 'eksSecretsEncrypted' : require(__dirname + '/plugins/aws/eks/eksSecretsEncrypted.js'), + // 'eksSecurityGroups' : require(__dirname + '/plugins/aws/eks/eksSecurityGroups.js'), + // 'eksLatestPlatformVersion' : require(__dirname + '/plugins/aws/eks/eksLatestPlatformVersion.js'), - 'kendraIndexEncrypted' : require(__dirname + '/plugins/aws/kendra/kendraIndexEncrypted.js'), + // 'kendraIndexEncrypted' : require(__dirname + '/plugins/aws/kendra/kendraIndexEncrypted.js'), - 'environmentTemplateEncrypted' : require(__dirname + '/plugins/aws/proton/environmentTemplateEncrypted.js'), + // 'environmentTemplateEncrypted' : require(__dirname + '/plugins/aws/proton/environmentTemplateEncrypted.js'), - 'crosszoneLoadBalancing' : require(__dirname + '/plugins/aws/elb/crosszoneLoadBalancing.js'), - 'insecureCiphers' : require(__dirname + '/plugins/aws/elb/insecureCiphers.js'), - 'elbHttpsOnly' : require(__dirname + '/plugins/aws/elb/elbHttpsOnly.js'), - 'elbLoggingEnabled' : require(__dirname + '/plugins/aws/elb/elbLoggingEnabled.js'), - 'elbNoInstances' : require(__dirname + '/plugins/aws/elb/elbNoInstances.js'), - 'classicELBInUse' : require(__dirname + '/plugins/aws/elb/classicELBInUse.js'), - 'connectionDrainingEnabled' : require(__dirname + '/plugins/aws/elb/connectionDrainingEnabled.js'), - 'appTierElbSecurity' : require(__dirname + '/plugins/aws/elb/appTierElbSecurity.js'), - - 'elbv2DeletionProtection' : require(__dirname + '/plugins/aws/elbv2/elbv2DeletionProtection.js'), - 'elbv2LoggingEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2LoggingEnabled.js'), - 'elbv2HttpsOnly' : require(__dirname + '/plugins/aws/elbv2/elbv2HttpsOnly.js'), - 'elbv2NoInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2NoInstances.js'), - 'elbv2WafEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2WafEnabled.js'), - 'elbv2MinimumTargetInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2MinimumTargetInstances.js'), - 'elbv2NlbListenerSecurity' : require(__dirname + '/plugins/aws/elbv2/elbv2NlbListenerSecurity.js'), - 'elbv2DeregistrationDelay' : require(__dirname + '/plugins/aws/elbv2/elbv2DeregistrationDelay.js'), - 'elbv2SslTermination' : require(__dirname + '/plugins/aws/elbv2/elbv2SslTermination.js'), - - 'elasticacheDefaultPorts' : require(__dirname + '/plugins/aws/elasticache/elasticacheDefaultPorts.js'), - - 'emrClusterLogging' : require(__dirname + '/plugins/aws/emr/emrClusterLogging.js'), - 'emrClusterInVPC' : require(__dirname + '/plugins/aws/emr/emrClusterInVPC.js'), - 'emrEncryptionInTransit' : require(__dirname + '/plugins/aws/emr/emrEncryptionInTransit.js'), - 'emrEncryptionAtRest' : require(__dirname + '/plugins/aws/emr/emrEncryptionAtRest.js'), - 'emrDesiredInstanceType' : require(__dirname + '/plugins/aws/emr/emrDesiredInstanceType.js'), - 'emrInstanceCount' : require(__dirname + '/plugins/aws/emr/emrInstanceCount.js'), - - 'esAccessFromIps' : require(__dirname + '/plugins/aws/es/esAccessFromIps.js'), - 'esPublicEndpoint' : require(__dirname + '/plugins/aws/es/esPublicEndpoint.js'), - 'esRequireIAMAuth' : require(__dirname + '/plugins/aws/es/esRequireIAMAuth.js'), - 'esEncryptedDomain' : require(__dirname + '/plugins/aws/es/esEncryptedDomain.js'), - 'esExposedDomain' : require(__dirname + '/plugins/aws/es/esExposedDomain.js'), - 'esNodeToNodeEncryption' : require(__dirname + '/plugins/aws/es/esNodeToNodeEncryption.js'), - 'esLoggingEnabled' : require(__dirname + '/plugins/aws/es/esLoggingEnabled.js'), - 'esUpgradeAvailable' : require(__dirname + '/plugins/aws/es/esUpgradeAvailable.js'), - 'esHttpsOnly' : require(__dirname + '/plugins/aws/es/esHttpsOnly.js'), - 'esCrossAccountAccess' : require(__dirname + '/plugins/aws/es/esCrossAccountAccess.js'), - 'esClusterStatus' : require(__dirname + '/plugins/aws/es/esClusterStatus.js'), - 'esDedicatedMasterEnabled' : require(__dirname + '/plugins/aws/es/esDedicatedMasterEnabled.js'), - 'esDesiredInstanceTypes' : require(__dirname + '/plugins/aws/es/esDesiredInstanceTypes.js'), - 'esTlsVersion' : require(__dirname + '/plugins/aws/es/esTlsVersion.js'), - 'esDomainEncryptionEnabled' : require(__dirname + '/plugins/aws/es/esDomainEncryptionEnabled.js'), - 'vaultPublicAccess' : require(__dirname + '/plugins/aws/s3glacier/vaultPublicAccess.js'), - 'firehoseEncrypted' : require(__dirname + '/plugins/aws/firehose/firehoseEncrypted.js'), - 'deliveryStreamEncrypted' : require(__dirname + '/plugins/aws/firehose/deliveryStreamEncrypted.js'), - - 'eventBusCrossAccountAccess' : require(__dirname + '/plugins/aws/eventbridge/eventBusCrossAccountAccess.js'), - 'eventBusPublicAccess' : require(__dirname + '/plugins/aws/eventbridge/eventBusPublicAccess.js'), - 'eventsInUse' : require(__dirname + '/plugins/aws/eventbridge/eventsInUse.js'), - - 'glueCloudwatchLogsEncrypted' : require(__dirname + '/plugins/aws/glue/glueCloudwatchLogsEncrypted.js'), - 'glueS3EncryptionEnabled' : require(__dirname + '/plugins/aws/glue/glueS3EncryptionEnabled.js'), - 'dataCatalogCmkEncrypted' : require(__dirname + '/plugins/aws/glue/dataCatalogCmkEncrypted.js'), - 'bookmarkEncryptionEnabled' : require(__dirname + '/plugins/aws/glue/bookmarkEncryptionEnabled.js'), - 'dataCatalogEncryptionEnabled' : require(__dirname + '/plugins/aws/glue/dataCatalogEncryptionEnabled.js'), - - 'accessKeysExtra' : require(__dirname + '/plugins/aws/iam/accessKeysExtra.js'), - 'accessKeysLastUsed' : require(__dirname + '/plugins/aws/iam/accessKeysLastUsed.js'), - 'accessKeysRotated' : require(__dirname + '/plugins/aws/iam/accessKeysRotated.js'), - 'certificateExpiry' : require(__dirname + '/plugins/aws/iam/certificateExpiry.js'), - 'crossAccountMfaExtIdAccess' : require(__dirname + '/plugins/aws/iam/crossAccountMfaExtIdAccess.js'), - 'emptyGroups' : require(__dirname + '/plugins/aws/iam/emptyGroups.js'), - 'groupInlinePolicies' : require(__dirname + '/plugins/aws/iam/groupInlinePolicies.js'), - 'iamMasterManagerRoles' : require(__dirname + '/plugins/aws/iam/iamMasterManagerRoles.js'), - 'iamUserAdmins' : require(__dirname + '/plugins/aws/iam/iamUserAdmins.js'), - 'iamUserNameRegex' : require(__dirname + '/plugins/aws/iam/iamUserNameRegex.js'), - 'iamUserUnauthorizedToEdit' : require(__dirname + '/plugins/aws/iam/iamUserUnauthorizedToEdit'), - 'iamRolePolicies' : require(__dirname + '/plugins/aws/iam/iamRolePolicies.js'), - 'iamRoleLastUsed' : require(__dirname + '/plugins/aws/iam/iamRoleLastUsed.js'), - 'maxPasswordAge' : require(__dirname + '/plugins/aws/iam/maxPasswordAge.js'), - 'minPasswordLength' : require(__dirname + '/plugins/aws/iam/minPasswordLength.js'), - 'noUserIamPolicies' : require(__dirname + '/plugins/aws/iam/noUserIamPolicies.js'), - 'passwordExpiration' : require(__dirname + '/plugins/aws/iam/passwordExpiration.js'), - 'passwordRequiresLowercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresLowercase.js'), - 'passwordRequiresNumbers' : require(__dirname + '/plugins/aws/iam/passwordRequiresNumbers.js'), - 'passwordRequiresSymbols' : require(__dirname + '/plugins/aws/iam/passwordRequiresSymbols.js'), - 'passwordRequiresUppercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresUppercase.js'), - 'passwordReusePrevention' : require(__dirname + '/plugins/aws/iam/passwordReusePrevention.js'), - 'rootAccessKeys' : require(__dirname + '/plugins/aws/iam/rootAccessKeys.js'), - 'rootSigningCertificate' : require(__dirname + '/plugins/aws/iam/rootSigningCertificate.js'), - 'rootAccountInUse' : require(__dirname + '/plugins/aws/iam/rootAccountInUse.js'), - 'rootHardwareMfa' : require(__dirname + '/plugins/aws/iam/rootHardwareMfa.js'), - 'rootMfaEnabled' : require(__dirname + '/plugins/aws/iam/rootMfaEnabled.js'), - 'sshKeysRotated' : require(__dirname + '/plugins/aws/iam/sshKeysRotated.js'), - 'trustedCrossAccountRoles' : require(__dirname + '/plugins/aws/iam/trustedCrossAccountRoles.js'), - 'usersMfaEnabled' : require(__dirname + '/plugins/aws/iam/usersMfaEnabled.js'), - 'usersPasswordAndKeys' : require(__dirname + '/plugins/aws/iam/usersPasswordAndKeys.js'), - 'usersPasswordLastUsed' : require(__dirname + '/plugins/aws/iam/usersPasswordLastUsed.js'), - 'canaryKeysUsed' : require(__dirname + '/plugins/aws/iam/canaryKeysUsed.js'), - 'iamPoliciesPresent' : require(__dirname + '/plugins/aws/iam/iamPoliciesPresent.js'), - 'iamDbAuthenticationEnabled' : require(__dirname + '/plugins/aws/rds/iamDbAuthenticationEnabled.js'), - 'iamSupportPolicy' : require(__dirname + '/plugins/aws/iam/iamSupportPolicy.js'), - 'iamUserPresent' : require(__dirname + '/plugins/aws/iam/iamUserPresent.js'), - - 'iamUserInUse' : require(__dirname + '/plugins/aws/iam/iamUserInUse.js'), - 'kinesisEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisEncrypted.js'), - 'kinesisDataStreamsEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisDataStreamsEncrypted.js'), - 'videostreamDataEncrypted' : require(__dirname + '/plugins/aws/kinesisvideo/videostreamDataEncrypted.js'), - - 'kmsKeyRotation' : require(__dirname + '/plugins/aws/kms/kmsKeyRotation.js'), - 'kmsScheduledDeletion' : require(__dirname + '/plugins/aws/kms/kmsScheduledDeletion.js'), - 'kmsKeyPolicy' : require(__dirname + '/plugins/aws/kms/kmsKeyPolicy.js'), - 'kmsDefaultKeyUsage' : require(__dirname + '/plugins/aws/kms/kmsDefaultKeyUsage.js'), - 'kmsAppTierCmk' : require(__dirname + '/plugins/aws/kms/kmsAppTierCmk.js'), - 'kmsGrantLeastPrivilege' : require(__dirname + '/plugins/aws/kms/kmsGrantLeastPrivilege.js'), - 'kmsDuplicateGrants' : require(__dirname + '/plugins/aws/kms/kmsDuplicateGrants.js'), - - 'rdsAutomatedBackups' : require(__dirname + '/plugins/aws/rds/rdsAutomatedBackups.js'), - 'rdsEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsEncryptionEnabled.js'), - 'rdsCmkEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsCmkEncryptionEnabled.js'), - 'rdsLoggingEnabled' : require(__dirname + '/plugins/aws/rds/rdsLoggingEnabled.js'), - 'rdsPubliclyAccessible' : require(__dirname + '/plugins/aws/rds/rdsPubliclyAccessible.js'), - 'rdsRestorable' : require(__dirname + '/plugins/aws/rds/rdsRestorable.js'), - 'rdsMultiAz' : require(__dirname + '/plugins/aws/rds/rdsMultiAz.js'), - 'rdsSnapshotEncryption' : require(__dirname + '/plugins/aws/rds/rdsSnapshotEncryption.js'), - 'rdsMinorVersionUpgrade' : require(__dirname + '/plugins/aws/rds/rdsMinorVersionUpgrade.js'), - 'sqlServerTLSVersion' : require(__dirname + '/plugins/aws/rds/sqlServerTLSVersion'), - 'rdsTransportEncryption' : require(__dirname + '/plugins/aws/rds/rdsTransportEncryption'), - 'rdsDeletionProtectionEnabled' : require(__dirname + '/plugins/aws/rds/rdsDeletionProtectionEnabled.js'), - - 'redisClusterEncryptionInTransit': require(__dirname + '/plugins/aws/elasticache/redisClusterEncryptionInTransit.js'), - 'elasticacheClusterInVpc' : require(__dirname + '/plugins/aws/elasticache/elasticacheClusterInVpc.js'), - 'elasticacheInstanceGeneration' : require(__dirname + '/plugins/aws/elasticache/elasticacheInstanceGeneration.js'), - 'redisEngineVersions' : require(__dirname + '/plugins/aws/elasticache/redisEngineVersions.js'), - 'elasticacheNodesCount' : require(__dirname + '/plugins/aws/elasticache/elasticacheNodesCount.js'), - 'elasticacheRedisMultiAZ' : require(__dirname + '/plugins/aws/elasticache/elasticacheRedisMultiAZ.js'), - 'idleElastiCacheNode' : require(__dirname + '/plugins/aws/elasticache/idleElastiCacheNode.js'), - 'elasticaheDesiredNodeType' : require(__dirname + '/plugins/aws/elasticache/elasticaheDesiredNodeType.js'), - - 'domainAutoRenew' : require(__dirname + '/plugins/aws/route53/domainAutoRenew.js'), - 'domainExpiry' : require(__dirname + '/plugins/aws/route53/domainExpiry.js'), - 'domainTransferLock' : require(__dirname + '/plugins/aws/route53/domainTransferLock.js'), - 'danglingDnsRecords' : require(__dirname + '/plugins/aws/route53/danglingDnsRecords.js'), - 'privacyProtection' : require(__dirname + '/plugins/aws/route53/privacyProtection.js'), - 'senderPolicyFwInUse' : require(__dirname + '/plugins/aws/route53/senderPolicyFwInUse.js'), - 'senderPolicyFwRecordPresent' : require(__dirname + '/plugins/aws/route53/senderPolicyFwRecordPresent.js'), - - 'bucketEncryptionInTransit' : require(__dirname + '/plugins/aws/s3/bucketEncryptionInTransit.js'), - 'bucketAllUsersPolicy' : require(__dirname + '/plugins/aws/s3/bucketAllUsersPolicy.js'), - 'bucketAllUsersAcl' : require(__dirname + '/plugins/aws/s3/bucketAllUsersAcl.js'), - 'bucketPolicyCloudFrontOai' : require(__dirname + '/plugins/aws/s3/bucketPolicyCloudFrontOai.js'), - 'bucketVersioning' : require(__dirname + '/plugins/aws/s3/bucketVersioning.js'), - 'bucketLogging' : require(__dirname + '/plugins/aws/s3/bucketLogging.js'), - 's3Encryption' : require(__dirname + '/plugins/aws/s3/s3Encryption.js'), - 'bucketPublicAccessBlock' : require(__dirname + '/plugins/aws/s3/bucketPublicAccessBlock.js'), - 'bucketEncryption' : require(__dirname + '/plugins/aws/s3/bucketEncryption.js'), - 'bucketWebsiteEnabled' : require(__dirname + '/plugins/aws/s3/bucketWebsiteEnabled.js'), - 'bucketEnforceEncryption' : require(__dirname + '/plugins/aws/s3/bucketEnforceEncryption.js'), - 'bucketSecureTransportEnabled' : require(__dirname + '/plugins/aws/s3/bucketSecureTransportEnabled.js'), - 'bucketLifecycleConfiguration' : require(__dirname + '/plugins/aws/s3/bucketLifecycleConfiguration'), - 'bucketTransferAcceleration' : require(__dirname + '/plugins/aws/s3/bucketTransferAcceleration'), - 'bucketDnsCompliantName' : require(__dirname + '/plugins/aws/s3/bucketDnsCompliantName.js'), - 'versionedBucketsLC' : require(__dirname + '/plugins/aws/s3/versionedBucketsLC.js'), - - 'notebookDataEncrypted' : require(__dirname + '/plugins/aws/sagemaker/notebookDataEncrypted.js'), - 'notebookDirectInternetAccess' : require(__dirname + '/plugins/aws/sagemaker/notebookDirectInternetAccess.js'), - 'notebookInstanceInVpc' : require(__dirname + '/plugins/aws/sagemaker/notebookInstanceInVpc.js'), - - 'dkimEnabled' : require(__dirname + '/plugins/aws/ses/dkimEnabled.js'), - 'emailMessagesEncrypted' : require(__dirname + '/plugins/aws/ses/emailMessagesEncrypted.js'), - - 'topicEncrypted' : require(__dirname + '/plugins/aws/sns/topicEncrypted.js'), - 'topicPolicies' : require(__dirname + '/plugins/aws/sns/topicPolicies.js'), - 'topicCmkEncrypted' : require(__dirname + '/plugins/aws/sns/topicCmkEncrypted.js'), - 'snsCrossAccount' : require(__dirname + '/plugins/aws/sns/snsCrossAccount.js'), - 'snsValidSubscribers' : require(__dirname + '/plugins/aws/sns/snsValidSubscribers.js'), - - 'sqsCrossAccount' : require(__dirname + '/plugins/aws/sqs/sqsCrossAccount.js'), - 'sqsDeadLetterQueue' : require(__dirname + '/plugins/aws/sqs/sqsDeadLetterQueue.js'), - 'sqsEncrypted' : require(__dirname + '/plugins/aws/sqs/sqsEncrypted.js'), - 'sqsPublicAccess' : require(__dirname + '/plugins/aws/sqs/sqsPublicAccess.js'), - 'queueUnprocessedMessages' : require(__dirname + '/plugins/aws/sqs/queueUnprocessedMessages.js'), - 'sqsEncryptionEnabled' : require(__dirname + '/plugins/aws/sqs/sqsEncryptionEnabled.js'), - - 'ssmEncryptedParameters' : require(__dirname + '/plugins/aws/ssm/ssmEncryptedParameters.js'), - 'ssmActiveOnAllInstances' : require(__dirname + '/plugins/aws/ssm/ssmActiveOnAllInstances.js'), - 'ssmAgentLatestVersion' : require(__dirname + '/plugins/aws/ssm/ssmAgentLatestVersion.js'), - 'ssmAgentAutoUpdateEnabled' : require(__dirname + '/plugins/aws/ssm/ssmAgentAutoUpdateEnabled'), - 'ssmDocumentPublicAccess' : require(__dirname + '/plugins/aws/ssm/ssmDocumentPublicAccess'), - 'ssmManagedInstances' : require(__dirname + '/plugins/aws/ssm/ssmManagedInstances'), - 'ssmSessionDuration' : require(__dirname + '/plugins/aws/ssm/ssmSessionDuration'), - - 'ledgerEncrypted' : require(__dirname + '/plugins/aws/qldb/ledgerEncrypted'), - - 'lambdaAdminPrivileges' : require(__dirname + '/plugins/aws/lambda/lambdaAdminPrivileges.js'), - 'envVarsClientSideEncryption' : require(__dirname + '/plugins/aws/lambda/envVarsClientSideEncryption.js'), - 'lambdaOldRuntimes' : require(__dirname + '/plugins/aws/lambda/lambdaOldRuntimes.js'), - 'lambdaVpcConfig' : require(__dirname + '/plugins/aws/lambda/lambdaVpcConfig.js'), - 'lambdaPublicAccess' : require(__dirname + '/plugins/aws/lambda/lambdaPublicAccess.js'), - 'lambdaLogGroups' : require(__dirname + '/plugins/aws/lambda/lambdaLogGroups.js'), - 'lambdaTracingEnabled' : require(__dirname + '/plugins/aws/lambda/lambdaTracingEnabled.js'), - - 'webServerPublicAccess' : require(__dirname + '/plugins/aws/mwaa/webServerPublicAccess.js'), - 'environmentAdminPrivileges' : require(__dirname + '/plugins/aws/mwaa/environmentAdminPrivileges.js'), - 'environmentDataEncrypted' : require(__dirname + '/plugins/aws/mwaa/environmentDataEncrypted.js'), - - 'neptuneDBInstanceEncrypted' : require(__dirname + '/plugins/aws/neptune/neptuneDBInstanceEncrypted.js'), - - 'monitoringMetrics' : require(__dirname + '/plugins/aws/cloudwatchlogs/monitoringMetrics.js'), - - 'customerProfilesDomainEncrypted' : require(__dirname + '/plugins/aws/connect/customerProfilesDomainEncrypted.js'), - 'wisdomDomainEncrypted' : require(__dirname + '/plugins/aws/connect/wisdomDomainEncrypted.js'), - 'voiceIdDomainEncrypted' : require(__dirname + '/plugins/aws/connect/voiceIdDomainEncrypted.js'), - - 'logRetentionPeriod' : require(__dirname + '/plugins/aws/cloudwatchlogs/logRetentionPeriod.js'), - 'logGroupsEncrypted' : require(__dirname + '/plugins/aws/cloudwatchlogs/logGroupsEncrypted.js'), - - 'vpcFlowLogsMetricAlarm' : require(__dirname + '/plugins/aws/cloudwatch/vpcFlowLogsMetricAlarm.js'), - - 'timestreamDatabaseEncrypted' : require(__dirname + '/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js'), - - 'mqAutoMinorVersionUpgrade' : require(__dirname + '/plugins/aws/mq/mqAutoMinorVersionUpgrade.js'), - 'mqLogExports' : require(__dirname + '/plugins/aws/mq/mqLogExports.js'), - 'mqDeploymentMode' : require(__dirname + '/plugins/aws/mq/mqDeploymentMode.js'), - 'mqDesiredInstanceType' : require(__dirname + '/plugins/aws/mq/mqDesiredInstanceType.js'), - 'mqBrokerEncrypted' : require(__dirname + '/plugins/aws/mq/mqBrokerEncrypted.js'), + // 'crosszoneLoadBalancing' : require(__dirname + '/plugins/aws/elb/crosszoneLoadBalancing.js'), + // 'insecureCiphers' : require(__dirname + '/plugins/aws/elb/insecureCiphers.js'), + // 'elbHttpsOnly' : require(__dirname + '/plugins/aws/elb/elbHttpsOnly.js'), + // 'elbLoggingEnabled' : require(__dirname + '/plugins/aws/elb/elbLoggingEnabled.js'), + // 'elbNoInstances' : require(__dirname + '/plugins/aws/elb/elbNoInstances.js'), + // 'classicELBInUse' : require(__dirname + '/plugins/aws/elb/classicELBInUse.js'), + // 'connectionDrainingEnabled' : require(__dirname + '/plugins/aws/elb/connectionDrainingEnabled.js'), + // 'appTierElbSecurity' : require(__dirname + '/plugins/aws/elb/appTierElbSecurity.js'), + + // 'elbv2DeletionProtection' : require(__dirname + '/plugins/aws/elbv2/elbv2DeletionProtection.js'), + // 'elbv2LoggingEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2LoggingEnabled.js'), + // 'elbv2HttpsOnly' : require(__dirname + '/plugins/aws/elbv2/elbv2HttpsOnly.js'), + // 'elbv2NoInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2NoInstances.js'), + // 'elbv2WafEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2WafEnabled.js'), + // 'elbv2MinimumTargetInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2MinimumTargetInstances.js'), + // 'elbv2NlbListenerSecurity' : require(__dirname + '/plugins/aws/elbv2/elbv2NlbListenerSecurity.js'), + // 'elbv2DeregistrationDelay' : require(__dirname + '/plugins/aws/elbv2/elbv2DeregistrationDelay.js'), + // 'elbv2SslTermination' : require(__dirname + '/plugins/aws/elbv2/elbv2SslTermination.js'), + + // 'elasticacheDefaultPorts' : require(__dirname + '/plugins/aws/elasticache/elasticacheDefaultPorts.js'), + + // 'emrClusterLogging' : require(__dirname + '/plugins/aws/emr/emrClusterLogging.js'), + // 'emrClusterInVPC' : require(__dirname + '/plugins/aws/emr/emrClusterInVPC.js'), + // 'emrEncryptionInTransit' : require(__dirname + '/plugins/aws/emr/emrEncryptionInTransit.js'), + // 'emrEncryptionAtRest' : require(__dirname + '/plugins/aws/emr/emrEncryptionAtRest.js'), + // 'emrDesiredInstanceType' : require(__dirname + '/plugins/aws/emr/emrDesiredInstanceType.js'), + // 'emrInstanceCount' : require(__dirname + '/plugins/aws/emr/emrInstanceCount.js'), + + // 'esAccessFromIps' : require(__dirname + '/plugins/aws/es/esAccessFromIps.js'), + // 'esPublicEndpoint' : require(__dirname + '/plugins/aws/es/esPublicEndpoint.js'), + // 'esRequireIAMAuth' : require(__dirname + '/plugins/aws/es/esRequireIAMAuth.js'), + // 'esEncryptedDomain' : require(__dirname + '/plugins/aws/es/esEncryptedDomain.js'), + // 'esExposedDomain' : require(__dirname + '/plugins/aws/es/esExposedDomain.js'), + // 'esNodeToNodeEncryption' : require(__dirname + '/plugins/aws/es/esNodeToNodeEncryption.js'), + // 'esLoggingEnabled' : require(__dirname + '/plugins/aws/es/esLoggingEnabled.js'), + // 'esUpgradeAvailable' : require(__dirname + '/plugins/aws/es/esUpgradeAvailable.js'), + // 'esHttpsOnly' : require(__dirname + '/plugins/aws/es/esHttpsOnly.js'), + // 'esCrossAccountAccess' : require(__dirname + '/plugins/aws/es/esCrossAccountAccess.js'), + // 'esClusterStatus' : require(__dirname + '/plugins/aws/es/esClusterStatus.js'), + // 'esDedicatedMasterEnabled' : require(__dirname + '/plugins/aws/es/esDedicatedMasterEnabled.js'), + // 'esDesiredInstanceTypes' : require(__dirname + '/plugins/aws/es/esDesiredInstanceTypes.js'), + // 'esTlsVersion' : require(__dirname + '/plugins/aws/es/esTlsVersion.js'), + // 'esDomainEncryptionEnabled' : require(__dirname + '/plugins/aws/es/esDomainEncryptionEnabled.js'), + // 'vaultPublicAccess' : require(__dirname + '/plugins/aws/s3glacier/vaultPublicAccess.js'), + // 'firehoseEncrypted' : require(__dirname + '/plugins/aws/firehose/firehoseEncrypted.js'), + // 'deliveryStreamEncrypted' : require(__dirname + '/plugins/aws/firehose/deliveryStreamEncrypted.js'), + + // 'eventBusCrossAccountAccess' : require(__dirname + '/plugins/aws/eventbridge/eventBusCrossAccountAccess.js'), + // 'eventBusPublicAccess' : require(__dirname + '/plugins/aws/eventbridge/eventBusPublicAccess.js'), + // 'eventsInUse' : require(__dirname + '/plugins/aws/eventbridge/eventsInUse.js'), + + // 'glueCloudwatchLogsEncrypted' : require(__dirname + '/plugins/aws/glue/glueCloudwatchLogsEncrypted.js'), + // 'glueS3EncryptionEnabled' : require(__dirname + '/plugins/aws/glue/glueS3EncryptionEnabled.js'), + // 'dataCatalogCmkEncrypted' : require(__dirname + '/plugins/aws/glue/dataCatalogCmkEncrypted.js'), + // 'bookmarkEncryptionEnabled' : require(__dirname + '/plugins/aws/glue/bookmarkEncryptionEnabled.js'), + // 'dataCatalogEncryptionEnabled' : require(__dirname + '/plugins/aws/glue/dataCatalogEncryptionEnabled.js'), + + // 'accessKeysExtra' : require(__dirname + '/plugins/aws/iam/accessKeysExtra.js'), + // 'accessKeysLastUsed' : require(__dirname + '/plugins/aws/iam/accessKeysLastUsed.js'), + // 'accessKeysRotated' : require(__dirname + '/plugins/aws/iam/accessKeysRotated.js'), + // 'certificateExpiry' : require(__dirname + '/plugins/aws/iam/certificateExpiry.js'), + // 'crossAccountMfaExtIdAccess' : require(__dirname + '/plugins/aws/iam/crossAccountMfaExtIdAccess.js'), + // 'emptyGroups' : require(__dirname + '/plugins/aws/iam/emptyGroups.js'), + // 'groupInlinePolicies' : require(__dirname + '/plugins/aws/iam/groupInlinePolicies.js'), + // 'iamMasterManagerRoles' : require(__dirname + '/plugins/aws/iam/iamMasterManagerRoles.js'), + // 'iamUserAdmins' : require(__dirname + '/plugins/aws/iam/iamUserAdmins.js'), + // 'iamUserNameRegex' : require(__dirname + '/plugins/aws/iam/iamUserNameRegex.js'), + // 'iamUserUnauthorizedToEdit' : require(__dirname + '/plugins/aws/iam/iamUserUnauthorizedToEdit'), + // 'iamRolePolicies' : require(__dirname + '/plugins/aws/iam/iamRolePolicies.js'), + // 'iamRoleLastUsed' : require(__dirname + '/plugins/aws/iam/iamRoleLastUsed.js'), + // 'maxPasswordAge' : require(__dirname + '/plugins/aws/iam/maxPasswordAge.js'), + // 'minPasswordLength' : require(__dirname + '/plugins/aws/iam/minPasswordLength.js'), + // 'noUserIamPolicies' : require(__dirname + '/plugins/aws/iam/noUserIamPolicies.js'), + // 'passwordExpiration' : require(__dirname + '/plugins/aws/iam/passwordExpiration.js'), + // 'passwordRequiresLowercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresLowercase.js'), + // 'passwordRequiresNumbers' : require(__dirname + '/plugins/aws/iam/passwordRequiresNumbers.js'), + // 'passwordRequiresSymbols' : require(__dirname + '/plugins/aws/iam/passwordRequiresSymbols.js'), + // 'passwordRequiresUppercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresUppercase.js'), + // 'passwordReusePrevention' : require(__dirname + '/plugins/aws/iam/passwordReusePrevention.js'), + // 'rootAccessKeys' : require(__dirname + '/plugins/aws/iam/rootAccessKeys.js'), + // 'rootSigningCertificate' : require(__dirname + '/plugins/aws/iam/rootSigningCertificate.js'), + // 'rootAccountInUse' : require(__dirname + '/plugins/aws/iam/rootAccountInUse.js'), + // 'rootHardwareMfa' : require(__dirname + '/plugins/aws/iam/rootHardwareMfa.js'), + // 'rootMfaEnabled' : require(__dirname + '/plugins/aws/iam/rootMfaEnabled.js'), + // 'sshKeysRotated' : require(__dirname + '/plugins/aws/iam/sshKeysRotated.js'), + // 'trustedCrossAccountRoles' : require(__dirname + '/plugins/aws/iam/trustedCrossAccountRoles.js'), + // 'usersMfaEnabled' : require(__dirname + '/plugins/aws/iam/usersMfaEnabled.js'), + // 'usersPasswordAndKeys' : require(__dirname + '/plugins/aws/iam/usersPasswordAndKeys.js'), + // 'usersPasswordLastUsed' : require(__dirname + '/plugins/aws/iam/usersPasswordLastUsed.js'), + // 'canaryKeysUsed' : require(__dirname + '/plugins/aws/iam/canaryKeysUsed.js'), + // 'iamPoliciesPresent' : require(__dirname + '/plugins/aws/iam/iamPoliciesPresent.js'), + // 'iamDbAuthenticationEnabled' : require(__dirname + '/plugins/aws/rds/iamDbAuthenticationEnabled.js'), + // 'iamSupportPolicy' : require(__dirname + '/plugins/aws/iam/iamSupportPolicy.js'), + // 'iamUserPresent' : require(__dirname + '/plugins/aws/iam/iamUserPresent.js'), + + // 'iamUserInUse' : require(__dirname + '/plugins/aws/iam/iamUserInUse.js'), + // 'kinesisEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisEncrypted.js'), + // 'kinesisDataStreamsEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisDataStreamsEncrypted.js'), + // 'videostreamDataEncrypted' : require(__dirname + '/plugins/aws/kinesisvideo/videostreamDataEncrypted.js'), + + // 'kmsKeyRotation' : require(__dirname + '/plugins/aws/kms/kmsKeyRotation.js'), + // 'kmsScheduledDeletion' : require(__dirname + '/plugins/aws/kms/kmsScheduledDeletion.js'), + // 'kmsKeyPolicy' : require(__dirname + '/plugins/aws/kms/kmsKeyPolicy.js'), + // 'kmsDefaultKeyUsage' : require(__dirname + '/plugins/aws/kms/kmsDefaultKeyUsage.js'), + // 'kmsAppTierCmk' : require(__dirname + '/plugins/aws/kms/kmsAppTierCmk.js'), + // 'kmsGrantLeastPrivilege' : require(__dirname + '/plugins/aws/kms/kmsGrantLeastPrivilege.js'), + // 'kmsDuplicateGrants' : require(__dirname + '/plugins/aws/kms/kmsDuplicateGrants.js'), + + // 'rdsAutomatedBackups' : require(__dirname + '/plugins/aws/rds/rdsAutomatedBackups.js'), + // 'rdsEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsEncryptionEnabled.js'), + // 'rdsCmkEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsCmkEncryptionEnabled.js'), + // 'rdsLoggingEnabled' : require(__dirname + '/plugins/aws/rds/rdsLoggingEnabled.js'), + // 'rdsPubliclyAccessible' : require(__dirname + '/plugins/aws/rds/rdsPubliclyAccessible.js'), + // 'rdsRestorable' : require(__dirname + '/plugins/aws/rds/rdsRestorable.js'), + // 'rdsMultiAz' : require(__dirname + '/plugins/aws/rds/rdsMultiAz.js'), + // 'rdsSnapshotEncryption' : require(__dirname + '/plugins/aws/rds/rdsSnapshotEncryption.js'), + // 'rdsMinorVersionUpgrade' : require(__dirname + '/plugins/aws/rds/rdsMinorVersionUpgrade.js'), + // 'sqlServerTLSVersion' : require(__dirname + '/plugins/aws/rds/sqlServerTLSVersion'), + // 'rdsTransportEncryption' : require(__dirname + '/plugins/aws/rds/rdsTransportEncryption'), + // 'rdsDeletionProtectionEnabled' : require(__dirname + '/plugins/aws/rds/rdsDeletionProtectionEnabled.js'), + + // 'redisClusterEncryptionInTransit': require(__dirname + '/plugins/aws/elasticache/redisClusterEncryptionInTransit.js'), + // 'elasticacheClusterInVpc' : require(__dirname + '/plugins/aws/elasticache/elasticacheClusterInVpc.js'), + // 'elasticacheInstanceGeneration' : require(__dirname + '/plugins/aws/elasticache/elasticacheInstanceGeneration.js'), + // 'redisEngineVersions' : require(__dirname + '/plugins/aws/elasticache/redisEngineVersions.js'), + // 'elasticacheNodesCount' : require(__dirname + '/plugins/aws/elasticache/elasticacheNodesCount.js'), + // 'elasticacheRedisMultiAZ' : require(__dirname + '/plugins/aws/elasticache/elasticacheRedisMultiAZ.js'), + // 'idleElastiCacheNode' : require(__dirname + '/plugins/aws/elasticache/idleElastiCacheNode.js'), + // 'elasticaheDesiredNodeType' : require(__dirname + '/plugins/aws/elasticache/elasticaheDesiredNodeType.js'), + + // 'domainAutoRenew' : require(__dirname + '/plugins/aws/route53/domainAutoRenew.js'), + // 'domainExpiry' : require(__dirname + '/plugins/aws/route53/domainExpiry.js'), + // 'domainTransferLock' : require(__dirname + '/plugins/aws/route53/domainTransferLock.js'), + // 'danglingDnsRecords' : require(__dirname + '/plugins/aws/route53/danglingDnsRecords.js'), + // 'privacyProtection' : require(__dirname + '/plugins/aws/route53/privacyProtection.js'), + // 'senderPolicyFwInUse' : require(__dirname + '/plugins/aws/route53/senderPolicyFwInUse.js'), + // 'senderPolicyFwRecordPresent' : require(__dirname + '/plugins/aws/route53/senderPolicyFwRecordPresent.js'), + + // 'bucketEncryptionInTransit' : require(__dirname + '/plugins/aws/s3/bucketEncryptionInTransit.js'), + // 'bucketAllUsersPolicy' : require(__dirname + '/plugins/aws/s3/bucketAllUsersPolicy.js'), + // 'bucketAllUsersAcl' : require(__dirname + '/plugins/aws/s3/bucketAllUsersAcl.js'), + // 'bucketPolicyCloudFrontOai' : require(__dirname + '/plugins/aws/s3/bucketPolicyCloudFrontOai.js'), + // 'bucketVersioning' : require(__dirname + '/plugins/aws/s3/bucketVersioning.js'), + // 'bucketLogging' : require(__dirname + '/plugins/aws/s3/bucketLogging.js'), + // 's3Encryption' : require(__dirname + '/plugins/aws/s3/s3Encryption.js'), + // 'bucketPublicAccessBlock' : require(__dirname + '/plugins/aws/s3/bucketPublicAccessBlock.js'), + // 'bucketEncryption' : require(__dirname + '/plugins/aws/s3/bucketEncryption.js'), + // 'bucketWebsiteEnabled' : require(__dirname + '/plugins/aws/s3/bucketWebsiteEnabled.js'), + // 'bucketEnforceEncryption' : require(__dirname + '/plugins/aws/s3/bucketEnforceEncryption.js'), + // 'bucketSecureTransportEnabled' : require(__dirname + '/plugins/aws/s3/bucketSecureTransportEnabled.js'), + // 'bucketLifecycleConfiguration' : require(__dirname + '/plugins/aws/s3/bucketLifecycleConfiguration'), + // 'bucketTransferAcceleration' : require(__dirname + '/plugins/aws/s3/bucketTransferAcceleration'), + // 'bucketDnsCompliantName' : require(__dirname + '/plugins/aws/s3/bucketDnsCompliantName.js'), + // 'versionedBucketsLC' : require(__dirname + '/plugins/aws/s3/versionedBucketsLC.js'), + + // 'notebookDataEncrypted' : require(__dirname + '/plugins/aws/sagemaker/notebookDataEncrypted.js'), + // 'notebookDirectInternetAccess' : require(__dirname + '/plugins/aws/sagemaker/notebookDirectInternetAccess.js'), + // 'notebookInstanceInVpc' : require(__dirname + '/plugins/aws/sagemaker/notebookInstanceInVpc.js'), + + // 'dkimEnabled' : require(__dirname + '/plugins/aws/ses/dkimEnabled.js'), + // 'emailMessagesEncrypted' : require(__dirname + '/plugins/aws/ses/emailMessagesEncrypted.js'), + + // 'topicEncrypted' : require(__dirname + '/plugins/aws/sns/topicEncrypted.js'), + // 'topicPolicies' : require(__dirname + '/plugins/aws/sns/topicPolicies.js'), + // 'topicCmkEncrypted' : require(__dirname + '/plugins/aws/sns/topicCmkEncrypted.js'), + // 'snsCrossAccount' : require(__dirname + '/plugins/aws/sns/snsCrossAccount.js'), + // 'snsValidSubscribers' : require(__dirname + '/plugins/aws/sns/snsValidSubscribers.js'), + + // 'sqsCrossAccount' : require(__dirname + '/plugins/aws/sqs/sqsCrossAccount.js'), + // 'sqsDeadLetterQueue' : require(__dirname + '/plugins/aws/sqs/sqsDeadLetterQueue.js'), + // 'sqsEncrypted' : require(__dirname + '/plugins/aws/sqs/sqsEncrypted.js'), + // 'sqsPublicAccess' : require(__dirname + '/plugins/aws/sqs/sqsPublicAccess.js'), + // 'queueUnprocessedMessages' : require(__dirname + '/plugins/aws/sqs/queueUnprocessedMessages.js'), + // 'sqsEncryptionEnabled' : require(__dirname + '/plugins/aws/sqs/sqsEncryptionEnabled.js'), + + // 'ssmEncryptedParameters' : require(__dirname + '/plugins/aws/ssm/ssmEncryptedParameters.js'), + // 'ssmActiveOnAllInstances' : require(__dirname + '/plugins/aws/ssm/ssmActiveOnAllInstances.js'), + // 'ssmAgentLatestVersion' : require(__dirname + '/plugins/aws/ssm/ssmAgentLatestVersion.js'), + // 'ssmAgentAutoUpdateEnabled' : require(__dirname + '/plugins/aws/ssm/ssmAgentAutoUpdateEnabled'), + // 'ssmDocumentPublicAccess' : require(__dirname + '/plugins/aws/ssm/ssmDocumentPublicAccess'), + // 'ssmManagedInstances' : require(__dirname + '/plugins/aws/ssm/ssmManagedInstances'), + // 'ssmSessionDuration' : require(__dirname + '/plugins/aws/ssm/ssmSessionDuration'), + + // 'ledgerEncrypted' : require(__dirname + '/plugins/aws/qldb/ledgerEncrypted'), + + // 'lambdaAdminPrivileges' : require(__dirname + '/plugins/aws/lambda/lambdaAdminPrivileges.js'), + // 'envVarsClientSideEncryption' : require(__dirname + '/plugins/aws/lambda/envVarsClientSideEncryption.js'), + // 'lambdaOldRuntimes' : require(__dirname + '/plugins/aws/lambda/lambdaOldRuntimes.js'), + // 'lambdaVpcConfig' : require(__dirname + '/plugins/aws/lambda/lambdaVpcConfig.js'), + // 'lambdaPublicAccess' : require(__dirname + '/plugins/aws/lambda/lambdaPublicAccess.js'), + // 'lambdaLogGroups' : require(__dirname + '/plugins/aws/lambda/lambdaLogGroups.js'), + // 'lambdaTracingEnabled' : require(__dirname + '/plugins/aws/lambda/lambdaTracingEnabled.js'), + + // 'webServerPublicAccess' : require(__dirname + '/plugins/aws/mwaa/webServerPublicAccess.js'), + // 'environmentAdminPrivileges' : require(__dirname + '/plugins/aws/mwaa/environmentAdminPrivileges.js'), + // 'environmentDataEncrypted' : require(__dirname + '/plugins/aws/mwaa/environmentDataEncrypted.js'), + + // 'neptuneDBInstanceEncrypted' : require(__dirname + '/plugins/aws/neptune/neptuneDBInstanceEncrypted.js'), + + // 'monitoringMetrics' : require(__dirname + '/plugins/aws/cloudwatchlogs/monitoringMetrics.js'), + + // 'customerProfilesDomainEncrypted' : require(__dirname + '/plugins/aws/connect/customerProfilesDomainEncrypted.js'), + // 'wisdomDomainEncrypted' : require(__dirname + '/plugins/aws/connect/wisdomDomainEncrypted.js'), + // 'voiceIdDomainEncrypted' : require(__dirname + '/plugins/aws/connect/voiceIdDomainEncrypted.js'), + + // 'logRetentionPeriod' : require(__dirname + '/plugins/aws/cloudwatchlogs/logRetentionPeriod.js'), + // 'logGroupsEncrypted' : require(__dirname + '/plugins/aws/cloudwatchlogs/logGroupsEncrypted.js'), + + // 'vpcFlowLogsMetricAlarm' : require(__dirname + '/plugins/aws/cloudwatch/vpcFlowLogsMetricAlarm.js'), + + // 'timestreamDatabaseEncrypted' : require(__dirname + '/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js'), + + // 'mqAutoMinorVersionUpgrade' : require(__dirname + '/plugins/aws/mq/mqAutoMinorVersionUpgrade.js'), + // 'mqLogExports' : require(__dirname + '/plugins/aws/mq/mqLogExports.js'), + // 'mqDeploymentMode' : require(__dirname + '/plugins/aws/mq/mqDeploymentMode.js'), + // 'mqDesiredInstanceType' : require(__dirname + '/plugins/aws/mq/mqDesiredInstanceType.js'), + // 'mqBrokerEncrypted' : require(__dirname + '/plugins/aws/mq/mqBrokerEncrypted.js'), - 'memorydbClusterEncrypted' : require(__dirname + '/plugins/aws/memorydb/memorydbClusterEncrypted.js'), + // 'memorydbClusterEncrypted' : require(__dirname + '/plugins/aws/memorydb/memorydbClusterEncrypted.js'), - 'mskClusterEncryptionAtRest' : require(__dirname + '/plugins/aws/msk/mskClusterEncryptionAtRest.js'), - 'mskClusterEncryptionInTransit' : require(__dirname + '/plugins/aws/msk/mskClusterEncryptionInTransit.js'), + // 'mskClusterEncryptionAtRest' : require(__dirname + '/plugins/aws/msk/mskClusterEncryptionAtRest.js'), + // 'mskClusterEncryptionInTransit' : require(__dirname + '/plugins/aws/msk/mskClusterEncryptionInTransit.js'), - 'auditLoggingEnabled' : require(__dirname + '/plugins/aws/redshift/auditLoggingEnabled.js'), - 'redshiftClusterCmkEncrypted' : require(__dirname + '/plugins/aws/redshift/redshiftClusterCmkEncrypted.js'), - 'redshiftEncryptionEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftEncryptionEnabled.js'), - 'redshiftPubliclyAccessible' : require(__dirname + '/plugins/aws/redshift/redshiftPubliclyAccessible.js'), - 'redshiftAllowVersionUpgrade' : require(__dirname + '/plugins/aws/redshift/redshiftAllowVersionUpgrade.js'), - 'redshiftSSLEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftSSLEnabled.js'), - 'redshiftClusterInVpc' : require(__dirname + '/plugins/aws/redshift/redshiftClusterInVpc.js'), - 'redshiftClusterDefaultPort' : require(__dirname + '/plugins/aws/redshift/redshiftClusterDefaultPort.js'), - 'redshiftClusterMasterUsername' : require(__dirname + '/plugins/aws/redshift/redshiftClusterMasterUsername.js'), - 'snapshotRetentionPeriod' : require(__dirname + '/plugins/aws/redshift/snapshotRetentionPeriod.js'), - 'userActivityLoggingEnabled' : require(__dirname + '/plugins/aws/redshift/userActivityLoggingEnabled.js'), - 'redshiftNodesCount' : require(__dirname + '/plugins/aws/redshift/redshiftNodesCount.js'), - 'redshiftUnusedReservedNodes' : require(__dirname + '/plugins/aws/redshift/redshiftUnusedReservedNodes.js'), - 'redshiftDesiredNodeType' : require(__dirname + '/plugins/aws/redshift/redshiftDesiredNodeType.js'), + // 'auditLoggingEnabled' : require(__dirname + '/plugins/aws/redshift/auditLoggingEnabled.js'), + // 'redshiftClusterCmkEncrypted' : require(__dirname + '/plugins/aws/redshift/redshiftClusterCmkEncrypted.js'), + // 'redshiftEncryptionEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftEncryptionEnabled.js'), + // 'redshiftPubliclyAccessible' : require(__dirname + '/plugins/aws/redshift/redshiftPubliclyAccessible.js'), + // 'redshiftAllowVersionUpgrade' : require(__dirname + '/plugins/aws/redshift/redshiftAllowVersionUpgrade.js'), + // 'redshiftSSLEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftSSLEnabled.js'), + // 'redshiftClusterInVpc' : require(__dirname + '/plugins/aws/redshift/redshiftClusterInVpc.js'), + // 'redshiftClusterDefaultPort' : require(__dirname + '/plugins/aws/redshift/redshiftClusterDefaultPort.js'), + // 'redshiftClusterMasterUsername' : require(__dirname + '/plugins/aws/redshift/redshiftClusterMasterUsername.js'), + // 'snapshotRetentionPeriod' : require(__dirname + '/plugins/aws/redshift/snapshotRetentionPeriod.js'), + // 'userActivityLoggingEnabled' : require(__dirname + '/plugins/aws/redshift/userActivityLoggingEnabled.js'), + // 'redshiftNodesCount' : require(__dirname + '/plugins/aws/redshift/redshiftNodesCount.js'), + // 'redshiftUnusedReservedNodes' : require(__dirname + '/plugins/aws/redshift/redshiftUnusedReservedNodes.js'), + // 'redshiftDesiredNodeType' : require(__dirname + '/plugins/aws/redshift/redshiftDesiredNodeType.js'), - 'redisClusterEncryptionAtRest' : require(__dirname + '/plugins/aws/elasticache/redisClusterEncryptionAtRest.js'), - 'reservedNodePaymentPending.js' : require(__dirname + '/plugins/aws/elasticache/reservedNodePaymentPending.js'), - 'unusedElastiCacheReservedNode' : require(__dirname + '/plugins/aws/elasticache/unusedElastiCacheReservedNode.js'), - 'reservedNodePaymentFailed' : require(__dirname + '/plugins/aws/elasticache/reservedNodePaymentFailed.js'), - 'reservedNodeLeaseExpiration' : require(__dirname + '/plugins/aws/elasticache/reservedNodeLeaseExpiration.js'), + // 'redisClusterEncryptionAtRest' : require(__dirname + '/plugins/aws/elasticache/redisClusterEncryptionAtRest.js'), + // 'reservedNodePaymentPending.js' : require(__dirname + '/plugins/aws/elasticache/reservedNodePaymentPending.js'), + // 'unusedElastiCacheReservedNode' : require(__dirname + '/plugins/aws/elasticache/unusedElastiCacheReservedNode.js'), + // 'reservedNodePaymentFailed' : require(__dirname + '/plugins/aws/elasticache/reservedNodePaymentFailed.js'), + // 'reservedNodeLeaseExpiration' : require(__dirname + '/plugins/aws/elasticache/reservedNodeLeaseExpiration.js'), - 'transferLoggingEnabled' : require(__dirname + '/plugins/aws/transfer/transferLoggingEnabled.js'), - 'transferPrivateLinkInUse' : require(__dirname + '/plugins/aws/transfer/transferPrivateLinkInUse.js'), + // 'transferLoggingEnabled' : require(__dirname + '/plugins/aws/transfer/transferLoggingEnabled.js'), + // 'transferPrivateLinkInUse' : require(__dirname + '/plugins/aws/transfer/transferPrivateLinkInUse.js'), - 'serviceEncrypted' : require(__dirname + '/plugins/aws/apprunner/serviceEncrypted.js'), + // 'serviceEncrypted' : require(__dirname + '/plugins/aws/apprunner/serviceEncrypted.js'), - 'secretRotationEnabled' : require(__dirname + '/plugins/aws/secretsmanager/secretRotationEnabled.js'), - 'secretsManagerEncrypted' : require(__dirname + '/plugins/aws/secretsmanager/secretsManagerEncrypted.js'), - 'secretsManagerInUse' : require(__dirname + '/plugins/aws/secretsmanager/secretsManagerInUse.js'), + // 'secretRotationEnabled' : require(__dirname + '/plugins/aws/secretsmanager/secretRotationEnabled.js'), + // 'secretsManagerEncrypted' : require(__dirname + '/plugins/aws/secretsmanager/secretsManagerEncrypted.js'), + // 'secretsManagerInUse' : require(__dirname + '/plugins/aws/secretsmanager/secretsManagerInUse.js'), - 'finspaceEnvironmentEncrypted' : require(__dirname + '/plugins/aws/finspace/finspaceEnvironmentEncrypted.js'), + // 'finspaceEnvironmentEncrypted' : require(__dirname + '/plugins/aws/finspace/finspaceEnvironmentEncrypted.js'), - 'shieldAdvancedEnabled' : require(__dirname + '/plugins/aws/shield/shieldAdvancedEnabled.js'), - 'shieldEmergencyContacts' : require(__dirname + '/plugins/aws/shield/shieldEmergencyContacts.js'), - 'shieldProtections' : require(__dirname + '/plugins/aws/shield/shieldProtections.js'), + // 'shieldAdvancedEnabled' : require(__dirname + '/plugins/aws/shield/shieldAdvancedEnabled.js'), + // 'shieldEmergencyContacts' : require(__dirname + '/plugins/aws/shield/shieldEmergencyContacts.js'), + // 'shieldProtections' : require(__dirname + '/plugins/aws/shield/shieldProtections.js'), - 'enableAllFeatures' : require(__dirname + '/plugins/aws/organizations/enableAllFeatures.js'), - 'organizationInvite' : require(__dirname + '/plugins/aws/organizations/organizationInvite.js'), + // 'enableAllFeatures' : require(__dirname + '/plugins/aws/organizations/enableAllFeatures.js'), + // 'organizationInvite' : require(__dirname + '/plugins/aws/organizations/organizationInvite.js'), - 'guardDutyEnabled' : require(__dirname + '/plugins/aws/guardduty/guarddutyEnabled.js'), - 'guardDutyMaster' : require(__dirname + '/plugins/aws/guardduty/guarddutyMaster.js'), - 'noActiveFindings' : require(__dirname + '/plugins/aws/guardduty/noActiveFindings'), - 'exportedFindingsEncrypted' : require(__dirname + '/plugins/aws/guardduty/exportedFindingsEncrypted.js'), + // 'guardDutyEnabled' : require(__dirname + '/plugins/aws/guardduty/guarddutyEnabled.js'), + // 'guardDutyMaster' : require(__dirname + '/plugins/aws/guardduty/guarddutyMaster.js'), + // 'noActiveFindings' : require(__dirname + '/plugins/aws/guardduty/noActiveFindings'), + // 'exportedFindingsEncrypted' : require(__dirname + '/plugins/aws/guardduty/exportedFindingsEncrypted.js'), - 'workspacesVolumeEncryption' : require(__dirname + '/plugins/aws/workspaces/workspacesVolumeEncryption.js'), - 'workspacesIpAccessControl' : require(__dirname + '/plugins/aws/workspaces/workspacesIpAccessControl.js'), - 'unusedWorkspaces' : require(__dirname + '/plugins/aws/workspaces/unusedWorkspaces.js'), - 'workspacesInstanceCount' : require(__dirname + '/plugins/aws/workspaces/workspacesInstanceCount.js'), - 'workspacesDesiredBundleType' : require(__dirname + '/plugins/aws/workspaces/workspacesDesiredBundleType.js'), + // 'workspacesVolumeEncryption' : require(__dirname + '/plugins/aws/workspaces/workspacesVolumeEncryption.js'), + // 'workspacesIpAccessControl' : require(__dirname + '/plugins/aws/workspaces/workspacesIpAccessControl.js'), + // 'unusedWorkspaces' : require(__dirname + '/plugins/aws/workspaces/unusedWorkspaces.js'), + // 'workspacesInstanceCount' : require(__dirname + '/plugins/aws/workspaces/workspacesInstanceCount.js'), + // 'workspacesDesiredBundleType' : require(__dirname + '/plugins/aws/workspaces/workspacesDesiredBundleType.js'), - 'xrayEncryptionEnabled' : require(__dirname + '/plugins/aws/xray/xrayEncryptionEnabled.js'), + // 'xrayEncryptionEnabled' : require(__dirname + '/plugins/aws/xray/xrayEncryptionEnabled.js'), - 'codebuildValidSourceProviders' : require(__dirname + '/plugins/aws/codebuild/codebuildValidSourceProviders.js'), - 'projectArtifactsEncrypted' : require(__dirname + '/plugins/aws/codebuild/projectArtifactsEncrypted.js'), + // 'codebuildValidSourceProviders' : require(__dirname + '/plugins/aws/codebuild/codebuildValidSourceProviders.js'), + // 'projectArtifactsEncrypted' : require(__dirname + '/plugins/aws/codebuild/projectArtifactsEncrypted.js'), - 'codestarValidRepoProviders' : require(__dirname + '/plugins/aws/codestar/codestarValidRepoProviders.js'), + // 'codestarValidRepoProviders' : require(__dirname + '/plugins/aws/codestar/codestarValidRepoProviders.js'), - 'pipelineArtifactsEncrypted' : require(__dirname + '/plugins/aws/codepipeline/pipelineArtifactsEncrypted.js'), + // 'pipelineArtifactsEncrypted' : require(__dirname + '/plugins/aws/codepipeline/pipelineArtifactsEncrypted.js'), - 'dataStoreEncrypted' : require(__dirname + '/plugins/aws/healthlake/dataStoreEncrypted.js'), + // 'dataStoreEncrypted' : require(__dirname + '/plugins/aws/healthlake/dataStoreEncrypted.js'), - 'codeartifactDomainEncrypted' : require(__dirname + '/plugins/aws/codeartifact/codeartifactDomainEncrypted.js'), + // 'codeartifactDomainEncrypted' : require(__dirname + '/plugins/aws/codeartifact/codeartifactDomainEncrypted.js'), - 'auditmanagerDataEncrypted' : require(__dirname + '/plugins/aws/auditmanager/auditmanagerDataEncrypted.js'), + // 'auditmanagerDataEncrypted' : require(__dirname + '/plugins/aws/auditmanager/auditmanagerDataEncrypted.js'), - 'flowEncrypted' : require(__dirname + '/plugins/aws/appflow/flowEncrypted.js'), + // 'flowEncrypted' : require(__dirname + '/plugins/aws/appflow/flowEncrypted.js'), - 'pipelineDataEncrypted' : require(__dirname + '/plugins/aws/elastictranscoder/pipelineDataEncrypted.js'), - 'jobOutputsEncrypted' : require(__dirname + '/plugins/aws/elastictranscoder/jobOutputsEncrypted.js'), + // 'pipelineDataEncrypted' : require(__dirname + '/plugins/aws/elastictranscoder/pipelineDataEncrypted.js'), + // 'jobOutputsEncrypted' : require(__dirname + '/plugins/aws/elastictranscoder/jobOutputsEncrypted.js'), - 'translateJobOutputEncrypted' : require(__dirname + '/plugins/aws/translate/translateJobOutputEncrypted.js'), + // 'translateJobOutputEncrypted' : require(__dirname + '/plugins/aws/translate/translateJobOutputEncrypted.js'), - 'databrewJobOutputEncrypted' : require(__dirname + '/plugins/aws/gluedatabrew/databrewJobOutputEncrypted.js'), + // 'databrewJobOutputEncrypted' : require(__dirname + '/plugins/aws/gluedatabrew/databrewJobOutputEncrypted.js'), - 'networkMemberDataEncrypted' : require(__dirname + '/plugins/aws/managedblockchain/networkMemberDataEncrypted.js'), + // 'networkMemberDataEncrypted' : require(__dirname + '/plugins/aws/managedblockchain/networkMemberDataEncrypted.js'), - 'docdbClusterEncrypted' : require(__dirname + '/plugins/aws/documentDB/docdbClusterEncrypted.js'), - 'docdbClusterBackupRetention' : require(__dirname + '/plugins/aws/documentDB/docdbClusterBackupRetention.js'), + // 'docdbClusterEncrypted' : require(__dirname + '/plugins/aws/documentDB/docdbClusterEncrypted.js'), + // 'docdbClusterBackupRetention' : require(__dirname + '/plugins/aws/documentDB/docdbClusterBackupRetention.js'), - 'instanceMediaStreamsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceMediaStreamsEncrypted.js'), - 'instanceTranscriptsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceTranscriptsEncrypted.js'), - 'instanceReportsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceReportsEncrypted.js'), - 'instanceCallRecordingEncrypted': require(__dirname + '/plugins/aws/connect/instanceCallRecordingEncrypted.js'), - 'instanceAttachmentsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceAttachmentsEncrypted.js'), + // 'instanceMediaStreamsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceMediaStreamsEncrypted.js'), + // 'instanceTranscriptsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceTranscriptsEncrypted.js'), + // 'instanceReportsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceReportsEncrypted.js'), + // 'instanceCallRecordingEncrypted': require(__dirname + '/plugins/aws/connect/instanceCallRecordingEncrypted.js'), + // 'instanceAttachmentsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceAttachmentsEncrypted.js'), - 'backupVaultEncrypted' : require(__dirname + '/plugins/aws/backup/backupVaultEncrypted.js'), - 'backupResourceProtection' : require(__dirname + '/plugins/aws/backup/backupResourceProtection.js'), - 'backupInUseForRDSSnapshots' : require(__dirname + '/plugins/aws/backup/backupInUseForRDSSnapshots.js'), - 'backupNotificationEnabled' : require(__dirname + '/plugins/aws/backup/backupNotificationEnabled.js'), - 'backupDeletionProtection' : require(__dirname + '/plugins/aws/backup/backupDeletionProtection.js'), - 'compliantLifecyleConfigured' : require(__dirname + '/plugins/aws/backup/compliantLifecyleConfigured.js'), + // 'backupVaultEncrypted' : require(__dirname + '/plugins/aws/backup/backupVaultEncrypted.js'), + // 'backupResourceProtection' : require(__dirname + '/plugins/aws/backup/backupResourceProtection.js'), + // 'backupInUseForRDSSnapshots' : require(__dirname + '/plugins/aws/backup/backupInUseForRDSSnapshots.js'), + // 'backupNotificationEnabled' : require(__dirname + '/plugins/aws/backup/backupNotificationEnabled.js'), + // 'backupDeletionProtection' : require(__dirname + '/plugins/aws/backup/backupDeletionProtection.js'), + // 'compliantLifecyleConfigured' : require(__dirname + '/plugins/aws/backup/compliantLifecyleConfigured.js'), - 'equipmentdatasetEncrypted' : require(__dirname + '/plugins/aws/lookout/equipmentdatasetEncrypted.js'), + // 'equipmentdatasetEncrypted' : require(__dirname + '/plugins/aws/lookout/equipmentdatasetEncrypted.js'), - 'iotsitewiseDataEncrypted' : require(__dirname + '/plugins/aws/iotsitewise/iotsitewiseDataEncrypted.js'), + // 'iotsitewiseDataEncrypted' : require(__dirname + '/plugins/aws/iotsitewise/iotsitewiseDataEncrypted.js'), - 'trackerDataEncrypted' : require(__dirname + '/plugins/aws/location/trackerDataEncrypted.js'), - 'geoCollectionDataEncrypted' : require(__dirname + '/plugins/aws/location/geoCollectionDataEncrypted.js'), + // 'trackerDataEncrypted' : require(__dirname + '/plugins/aws/location/trackerDataEncrypted.js'), + // 'geoCollectionDataEncrypted' : require(__dirname + '/plugins/aws/location/geoCollectionDataEncrypted.js'), - 'modelDataEncrypted' : require(__dirname + '/plugins/aws/lookout/modelDataEncrypted.js'), - 'anomalyDetectorEncrypted' : require(__dirname + '/plugins/aws/lookout/anomalyDetectorEncrypted.js'), + // 'modelDataEncrypted' : require(__dirname + '/plugins/aws/lookout/modelDataEncrypted.js'), + // 'anomalyDetectorEncrypted' : require(__dirname + '/plugins/aws/lookout/anomalyDetectorEncrypted.js'), - 'lexAudioLogsEncrypted' : require(__dirname + '/plugins/aws/lex/lexAudioLogsEncrypted.js'), + // 'lexAudioLogsEncrypted' : require(__dirname + '/plugins/aws/lex/lexAudioLogsEncrypted.js'), - 'forecastDatasetEncrypted' : require(__dirname + '/plugins/aws/forecast/forecastDatasetEncrypted.js'), - 'datasetExportEncrypted' : require(__dirname + '/plugins/aws/forecast/datasetExportEncrypted.js'), + // 'forecastDatasetEncrypted' : require(__dirname + '/plugins/aws/forecast/forecastDatasetEncrypted.js'), + // 'datasetExportEncrypted' : require(__dirname + '/plugins/aws/forecast/datasetExportEncrypted.js'), - 'fsxFileSystemEncrypted' : require(__dirname + '/plugins/aws/fsx/fsxFileSystemEncrypted.js'), + // 'fsxFileSystemEncrypted' : require(__dirname + '/plugins/aws/fsx/fsxFileSystemEncrypted.js'), - 'wafv2InUse' : require(__dirname + '/plugins/aws/wafv2/wafv2InUse.js'), + // 'wafv2InUse' : require(__dirname + '/plugins/aws/wafv2/wafv2InUse.js'), - 'wafInUse' : require(__dirname + '/plugins/aws/waf/wafInUse.js'), + // 'wafInUse' : require(__dirname + '/plugins/aws/waf/wafInUse.js'), - 'fraudDetectorDataEncrypted' : require(__dirname + '/plugins/aws/frauddetector/fraudDetectorDataEncrypted.js'), + // 'fraudDetectorDataEncrypted' : require(__dirname + '/plugins/aws/frauddetector/fraudDetectorDataEncrypted.js'), }, azure : { 'fileServiceEncryption' : require(__dirname + '/plugins/azure/storageaccounts/fileServiceEncryption.js'), diff --git a/helpers/aws/api.js b/helpers/aws/api.js index 27d7904da9..adc6188406 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -181,6 +181,12 @@ var calls = { paginate: 'nextToken' } }, + ComputeOptimizer: { + getRecommendationSummaries : { + property: 'recommendationSummaries', + paginate: 'nextToken' + } + }, Comprehend: { listEntitiesDetectionJobs: { property: 'EntitiesDetectionJobPropertiesList', diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index 52d8f9f211..4de2d08f9f 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -193,5 +193,6 @@ module.exports = { appmesh: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1'], - frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'] + frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'], + computeoptimizer: ['us-east-1'] }; diff --git a/plugins/aws/computeoptimizer/ec2InstancesOptimized.js b/plugins/aws/computeoptimizer/ec2InstancesOptimized.js new file mode 100644 index 0000000000..9e36cdb754 --- /dev/null +++ b/plugins/aws/computeoptimizer/ec2InstancesOptimized.js @@ -0,0 +1,65 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'EC2 Instances Optimized', + category: 'Compute Optimizer', + domain: 'Management and Governance', + description: 'Ensure that Compute Optimizer EC2 findings are in order to take the actions to optimize Amazon EC2 instances that are under-provisioned and over-provisioned.', + more_info: 'An EC2 instance is considered optimized when all specifications of an instance, such as CPU, memory, and network, meet the performance requirements of your workload, and the instance is not over-provisioned. For optimized instances, Compute Optimizer might sometimes recommend a new generation instance type.', + link: 'https://docs.aws.amazon.com/compute-optimizer/latest/ug/view-ec2-recommendations.html', + recommended_action: 'Enable Compute Optimizer Opt In options for Ec2 instances recommendations', + apis: ['ComputeOptimizer:getRecommendationSummaries'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + async.each(regions.computeoptimizer, function(region, rcb){ + var getRecommendationSummaries = helpers.addSource(cache, source, + ['computeoptimizer', 'getRecommendationSummaries', region]); + + if (!getRecommendationSummaries) return rcb(); + + if (getRecommendationSummaries && getRecommendationSummaries.err && + getRecommendationSummaries.err.code === 'OptInRequiredException'){ + helpers.addResult(results, 0, + 'Compute Optimizer is not enabled', region); + return rcb(); + } + + if (getRecommendationSummaries.err || !getRecommendationSummaries.data) { + helpers.addResult(results, 3, + 'Unable to get recommendation summaries: ' + helpers.addError(getRecommendationSummaries), region); + return rcb(); + } + + if (!getRecommendationSummaries.data.length) { + helpers.addResult(results, 0, + 'Optimization for summaries is not configured', region); + return rcb(); + } + + let findings = getRecommendationSummaries.data.find(resourceType => resourceType.recommendationResourceType === 'Ec2Instance'); + if (findings) { + let underProvisioned = findings.summaries.find(summary => summary.name === 'UNDER_PROVISIONED' ); + let overProvisioned = findings.summaries.find(summary => summary.name === 'OVER_PROVISIONED' ); + if (underProvisioned.value || overProvisioned.value){ + helpers.addResult(results, 2, + `EC2 instances are not optimized, under provisioned: ${underProvisioned.value}, over provisioned: ${underProvisioned.value} `, region); + } else { + helpers.addResult(results, 0, + 'All EC2 instances are optimized', region); + } + } else { + helpers.addResult(results, 2, + 'No EC2 instances configured', region); + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; diff --git a/plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js b/plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js new file mode 100644 index 0000000000..b94e3d75e2 --- /dev/null +++ b/plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js @@ -0,0 +1,117 @@ +var expect = require('chai').expect; +var ec2InstancesOptimized = require('./ec2InstancesOptimized'); + +const getRecommendationSummaries = [ + { + "summaries": [ + { + "name": "OPTIMIZED", + "value": 0.0 + }, + { + "name": "UNDER_PROVISIONED", + "value": 0.0 + }, + { + "name": "OVER_PROVISIONED", + "value": 0.0 + } + ], + "recommendationResourceType": "Ec2Instance", + "accountId": "000011112222", + "currentPerformanceRiskRatings": { + "high": 0, + "medium": 0, + "low": 0, + "veryLow": 0 + } + }, + { + "summaries": [ + { + "name": "OPTIMIZED", + "value": 0.0 + }, + { + "name": "UNDER_PROVISIONED", + "value": 0.0 + }, + { + "name": "OVER_PROVISIONED", + "value": 1.0 + } + ], + "recommendationResourceType": "Ec2Instance", + "accountId": "000011112222", + "currentPerformanceRiskRatings": { + "high": 0, + "medium": 0, + "low": 0, + "veryLow": 0 + } + } +]; + + +const createCache = (recommendation, recommendationErr) => { + return { + computeoptimizer: { + getRecommendationSummaries: { + 'us-east-1': { + err: recommendationErr, + data: recommendation + }, + }, + }, + }; +}; + +describe('ec2InstancesOptimized', function () { + describe('run', function () { + it('should PASS if EC2 instance is optimized', function (done) { + const cache = createCache([getRecommendationSummaries[0]]); + ec2InstancesOptimized.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 EC2 instance is not optimized', function (done) { + const cache = createCache([getRecommendationSummaries[1]]); + ec2InstancesOptimized.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 Optimization for summaries is not configured', function (done) { + const cache = createCache([]); + ec2InstancesOptimized.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 get recommendation summaries', function (done) { + const cache = createCache(null, { message: "Unable to obtain data" }); + ec2InstancesOptimized.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 not return anything if get recommendation summaries status response is not found', () => { + ec2InstancesOptimized.run({}, {}, (err, results) => { + expect(results.length).to.equal(0); + }) + }); + }); +}); \ No newline at end of file From 8bdebf625ed744bc27a9882666ecbfc1989e56f2 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Wed, 20 Apr 2022 21:15:46 +0500 Subject: [PATCH 079/350] Added Some Changes --- .../aws/computeoptimizer/ec2InstancesOptimized.spec.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js b/plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js index b94e3d75e2..dfe5196510 100644 --- a/plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js +++ b/plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js @@ -68,12 +68,13 @@ const createCache = (recommendation, recommendationErr) => { describe('ec2InstancesOptimized', function () { describe('run', function () { - it('should PASS if EC2 instance is optimized', function (done) { + it('should PASS if All EC2 instances are optimized', function (done) { const cache = createCache([getRecommendationSummaries[0]]); ec2InstancesOptimized.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('All EC2 instances are optimized'); done(); }); }); @@ -84,6 +85,7 @@ describe('ec2InstancesOptimized', 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('EC2 instances are not optimized'); done(); }); }); @@ -94,16 +96,18 @@ describe('ec2InstancesOptimized', 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('Optimization for summaries is not configured'); done(); }); }); it('should UNKNOWN if Unable to get recommendation summaries', function (done) { - const cache = createCache(null, { message: "Unable to obtain data" }); + const cache = createCache(null, { message: "Unable to get recommendation summaries" }); ec2InstancesOptimized.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 recommendation summaries'); done(); }); }); From cbbd73ed7a1f1979a2e2c13d9c2310ed9763df4c Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Wed, 20 Apr 2022 21:18:55 +0500 Subject: [PATCH 080/350] Added Some Changes --- helpers/aws/regions_china.js | 3 ++- helpers/aws/regions_gov.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/helpers/aws/regions_china.js b/helpers/aws/regions_china.js index 2a2b9af6de..ece0a63f17 100644 --- a/helpers/aws/regions_china.js +++ b/helpers/aws/regions_china.js @@ -116,5 +116,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + computeoptimizer: ['cn-north-1'] }; diff --git a/helpers/aws/regions_gov.js b/helpers/aws/regions_gov.js index 1eaf28407b..088c93f57b 100644 --- a/helpers/aws/regions_gov.js +++ b/helpers/aws/regions_gov.js @@ -115,5 +115,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + computeoptimizer: ['us-gov-west-1'] }; From 776dd2641f5094fc8d7bc3c5cfbfd0b684b2de52 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 21 Apr 2022 14:07:49 +0500 Subject: [PATCH 081/350] Added Some Changes --- exports.js | 984 ++++++++++++++++++++++++++--------------------------- 1 file changed, 492 insertions(+), 492 deletions(-) diff --git a/exports.js b/exports.js index 29fb5cd71f..2f0a489d4d 100644 --- a/exports.js +++ b/exports.js @@ -2,545 +2,545 @@ module.exports = { aws : { - // 'accessAnalyzerEnabled' : require(__dirname + '/plugins/aws/accessanalyzer/accessAnalyzerEnabled.js'), - // 'accessAnalyzerActiveFindings' : require(__dirname + '/plugins/aws/accessanalyzer/accessAnalyzerActiveFindings.js'), + 'accessAnalyzerEnabled' : require(__dirname + '/plugins/aws/accessanalyzer/accessAnalyzerEnabled.js'), + 'accessAnalyzerActiveFindings' : require(__dirname + '/plugins/aws/accessanalyzer/accessAnalyzerActiveFindings.js'), - // 'acmValidation' : require(__dirname + '/plugins/aws/acm/acmValidation.js'), - // 'acmCertificateExpiry' : require(__dirname + '/plugins/aws/acm/acmCertificateExpiry.js'), - // 'acmSingleDomainNameCertificate': require(__dirname + '/plugins/aws/acm/acmSingleDomainNameCertificate.js'), + 'acmValidation' : require(__dirname + '/plugins/aws/acm/acmValidation.js'), + 'acmCertificateExpiry' : require(__dirname + '/plugins/aws/acm/acmCertificateExpiry.js'), + 'acmSingleDomainNameCertificate': require(__dirname + '/plugins/aws/acm/acmSingleDomainNameCertificate.js'), - // 'appmeshVGAccessLogging' : require(__dirname + '/plugins/aws/appmesh/appmeshVGAccessLogging.js'), + 'appmeshVGAccessLogging' : require(__dirname + '/plugins/aws/appmesh/appmeshVGAccessLogging.js'), - // 'apigatewayCertificateRotation' : require(__dirname + '/plugins/aws/apigateway/apigatewayCertificateRotation.js'), - // 'apigatewayCloudwatchLogs' : require(__dirname + '/plugins/aws/apigateway/apigatewayCloudwatchLogs.js'), - // 'apigatewayPrivateEndpoints' : require(__dirname + '/plugins/aws/apigateway/apigatewayPrivateEndpoints.js'), - // 'apigatewayContentEncoding' : require(__dirname + '/plugins/aws/apigateway/apigatewayContentEncoding.js'), - // 'apigatewayTracingEnabled' : require(__dirname + '/plugins/aws/apigateway/apigatewayTracingEnabled.js'), - // 'apigatewayWafEnabled' : require(__dirname + '/plugins/aws/apigateway/apigatewayWafEnabled.js'), - // 'detailedCloudWatchMetrics' : require(__dirname + '/plugins/aws/apigateway/detailedCloudWatchMetrics.js'), - // 'apigatewayClientCertificate' : require(__dirname + '/plugins/aws/apigateway/apigatewayClientCertificate.js'), - // 'apigatewayResponseCaching' : require(__dirname + '/plugins/aws/apigateway/apigatewayResponseCaching.js'), - // 'apiStageLevelCacheEncryption' : require(__dirname + '/plugins/aws/apigateway/apiStageLevelCacheEncryption.js'), - - // 'restrictExternalTraffic' : require(__dirname + '/plugins/aws/appmesh/restrictExternalTraffic.js'), - // 'appmeshTLSRequired' : require(__dirname + '/plugins/aws/appmesh/appmeshTLSRequired.js'), - - // 'asgMultiAz' : require(__dirname + '/plugins/aws/autoscaling/asgMultiAz.js'), - // 'asgActiveNotifications' : require(__dirname + '/plugins/aws/autoscaling/asgActiveNotifications.js'), - // 'asgCooldownPeriod' : require(__dirname + '/plugins/aws/autoscaling/asgCooldownPeriod.js'), - // 'emptyASG' : require(__dirname + '/plugins/aws/autoscaling/emptyASG.js'), - // 'sameAzElb' : require(__dirname + '/plugins/aws/autoscaling/sameAzElb.js'), - // 'asgMissingELB' : require(__dirname + '/plugins/aws/autoscaling/asgMissingELB.js'), - // 'webTierAsgAssociatedElb' : require(__dirname + '/plugins/aws/autoscaling/webTierAsgAssociatedElb.js'), - // 'elbHealthCheckActive' : require(__dirname + '/plugins/aws/autoscaling/elbHealthCheckActive.js'), - // 'asgSuspendedProcesses' : require(__dirname + '/plugins/aws/autoscaling/asgSuspendedProcesses.js'), - // 'appTierAsgApprovedAmi' : require(__dirname + '/plugins/aws/autoscaling/appTierAsgApprovedAmi.js'), - // 'webTierAsgApprovedAmi' : require(__dirname + '/plugins/aws/autoscaling/webTierAsgApprovedAmi.js'), - // 'appTierAsgCloudwatchLogs' : require(__dirname + '/plugins/aws/autoscaling/appTierAsgCloudwatchLogs.js'), - // 'webTierAsgCloudwatchLogs' : require(__dirname + '/plugins/aws/autoscaling/webTierAsgCloudwatchLogs.js'), - // 'asgMissingSecurityGroups' : require(__dirname + '/plugins/aws/autoscaling/asgMissingSecurityGroups.js'), - // 'webTierIamRole' : require(__dirname + '/plugins/aws/autoscaling/webTierIamRole.js'), - // 'appTierIamRole' : require(__dirname + '/plugins/aws/autoscaling/appTierIamRole.js'), - // 'asgUnusedLaunchConfiguration' : require(__dirname + '/plugins/aws/autoscaling/asgUnusedLaunchConfiguration.js'), - - // 'workgroupEncrypted' : require(__dirname + '/plugins/aws/athena/workgroupEncrypted.js'), - // 'workgroupEnforceConfiguration' : require(__dirname + '/plugins/aws/athena/workgroupEnforceConfiguration.js'), - - // 'publicS3Origin' : require(__dirname + '/plugins/aws/cloudfront/publicS3Origin.js'), - // 'secureOrigin' : require(__dirname + '/plugins/aws/cloudfront/secureOrigin.js'), - // 'insecureProtocols' : require(__dirname + '/plugins/aws/cloudfront/insecureProtocols.js'), - // 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), - // 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), - // 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), - // 'cloudfrontFieldLevelEncryption': require(__dirname + '/plugins/aws/cloudfront/cloudfrontFieldLevelEncryption.js'), - // 'cloudfrontInUse' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontInUse.js'), - // 'enableOriginFailOver' : require(__dirname + '/plugins/aws/cloudfront/enableOriginFailOver.js'), - // 'cloudfrontGeoRestriction' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontGeoRestriction.js'), - // 'compressObjectsAutomatically' : require(__dirname + '/plugins/aws/cloudfront/compressObjectsAutomatically.js'), - - // 'volumeEncryption' : require(__dirname + '/plugins/aws/comprehend/volumeEncryption.js'), - // 'outputResultEncryption' : require(__dirname + '/plugins/aws/comprehend/outputResultEncryption.js'), - - // 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), - // 'stackFailedStatus' : require(__dirname + '/plugins/aws/cloudformation/stackFailedStatus.js'), - // 'driftDetection' : require(__dirname + '/plugins/aws/cloudformation/driftDetection.js'), - // 'stackTerminationProtection' : require(__dirname + '/plugins/aws/cloudformation/stackTerminationProtection.js'), - // 'stackNotifications' : require(__dirname + '/plugins/aws/cloudformation/stackNotifications.js'), - // 'cloudformationAdminPriviliges' : require(__dirname + '/plugins/aws/cloudformation/cloudformationAdminPriviliges.js'), - // 'cloudformationInUse' : require(__dirname + '/plugins/aws/cloudformation/cloudformationInUse.js'), - - // 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), - // 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), - // 'cloudtrailDataEvents' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailDataEvents.js'), - // 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), - // 'cloudtrailEncryption' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEncryption.js'), - // 'cloudtrailFileValidation' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailFileValidation.js'), - // 'cloudtrailObjectLock' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailObjectLock.js'), - // 'cloudtrailToCloudwatch' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailToCloudwatch.js'), - // 'cloudtrailBucketPrivate' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js'), - // 'cloudtrailDeliveryFailing' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailDeliveryFailing.js'), - // 'cloudtrailManagementEvents' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailManagementEvents.js'), - // 'cloudtrailS3Bucket' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailS3Bucket.js'), - // 'globalLoggingDuplicated' : require(__dirname + '/plugins/aws/cloudtrail/globalLoggingDuplicated.js'), - // 'cloudtrailNotificationsEnabled': require(__dirname + '/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js'), - - // 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), - // 'configComplaintRules' : require(__dirname + '/plugins/aws/configservice/configComplaintRules.js'), - // 'configDeliveryFailing' : require(__dirname + '/plugins/aws/configservice/configDeliveryFailing.js'), - // 'configServiceMissingBucket' : require(__dirname + '/plugins/aws/configservice/configServiceMissingBucket.js'), + 'apigatewayCertificateRotation' : require(__dirname + '/plugins/aws/apigateway/apigatewayCertificateRotation.js'), + 'apigatewayCloudwatchLogs' : require(__dirname + '/plugins/aws/apigateway/apigatewayCloudwatchLogs.js'), + 'apigatewayPrivateEndpoints' : require(__dirname + '/plugins/aws/apigateway/apigatewayPrivateEndpoints.js'), + 'apigatewayContentEncoding' : require(__dirname + '/plugins/aws/apigateway/apigatewayContentEncoding.js'), + 'apigatewayTracingEnabled' : require(__dirname + '/plugins/aws/apigateway/apigatewayTracingEnabled.js'), + 'apigatewayWafEnabled' : require(__dirname + '/plugins/aws/apigateway/apigatewayWafEnabled.js'), + 'detailedCloudWatchMetrics' : require(__dirname + '/plugins/aws/apigateway/detailedCloudWatchMetrics.js'), + 'apigatewayClientCertificate' : require(__dirname + '/plugins/aws/apigateway/apigatewayClientCertificate.js'), + 'apigatewayResponseCaching' : require(__dirname + '/plugins/aws/apigateway/apigatewayResponseCaching.js'), + 'apiStageLevelCacheEncryption' : require(__dirname + '/plugins/aws/apigateway/apiStageLevelCacheEncryption.js'), + + 'restrictExternalTraffic' : require(__dirname + '/plugins/aws/appmesh/restrictExternalTraffic.js'), + 'appmeshTLSRequired' : require(__dirname + '/plugins/aws/appmesh/appmeshTLSRequired.js'), + + 'asgMultiAz' : require(__dirname + '/plugins/aws/autoscaling/asgMultiAz.js'), + 'asgActiveNotifications' : require(__dirname + '/plugins/aws/autoscaling/asgActiveNotifications.js'), + 'asgCooldownPeriod' : require(__dirname + '/plugins/aws/autoscaling/asgCooldownPeriod.js'), + 'emptyASG' : require(__dirname + '/plugins/aws/autoscaling/emptyASG.js'), + 'sameAzElb' : require(__dirname + '/plugins/aws/autoscaling/sameAzElb.js'), + 'asgMissingELB' : require(__dirname + '/plugins/aws/autoscaling/asgMissingELB.js'), + 'webTierAsgAssociatedElb' : require(__dirname + '/plugins/aws/autoscaling/webTierAsgAssociatedElb.js'), + 'elbHealthCheckActive' : require(__dirname + '/plugins/aws/autoscaling/elbHealthCheckActive.js'), + 'asgSuspendedProcesses' : require(__dirname + '/plugins/aws/autoscaling/asgSuspendedProcesses.js'), + 'appTierAsgApprovedAmi' : require(__dirname + '/plugins/aws/autoscaling/appTierAsgApprovedAmi.js'), + 'webTierAsgApprovedAmi' : require(__dirname + '/plugins/aws/autoscaling/webTierAsgApprovedAmi.js'), + 'appTierAsgCloudwatchLogs' : require(__dirname + '/plugins/aws/autoscaling/appTierAsgCloudwatchLogs.js'), + 'webTierAsgCloudwatchLogs' : require(__dirname + '/plugins/aws/autoscaling/webTierAsgCloudwatchLogs.js'), + 'asgMissingSecurityGroups' : require(__dirname + '/plugins/aws/autoscaling/asgMissingSecurityGroups.js'), + 'webTierIamRole' : require(__dirname + '/plugins/aws/autoscaling/webTierIamRole.js'), + 'appTierIamRole' : require(__dirname + '/plugins/aws/autoscaling/appTierIamRole.js'), + 'asgUnusedLaunchConfiguration' : require(__dirname + '/plugins/aws/autoscaling/asgUnusedLaunchConfiguration.js'), + + 'workgroupEncrypted' : require(__dirname + '/plugins/aws/athena/workgroupEncrypted.js'), + 'workgroupEnforceConfiguration' : require(__dirname + '/plugins/aws/athena/workgroupEnforceConfiguration.js'), + + 'publicS3Origin' : require(__dirname + '/plugins/aws/cloudfront/publicS3Origin.js'), + 'secureOrigin' : require(__dirname + '/plugins/aws/cloudfront/secureOrigin.js'), + 'insecureProtocols' : require(__dirname + '/plugins/aws/cloudfront/insecureProtocols.js'), + 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), + 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), + 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), + 'cloudfrontFieldLevelEncryption': require(__dirname + '/plugins/aws/cloudfront/cloudfrontFieldLevelEncryption.js'), + 'cloudfrontInUse' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontInUse.js'), + 'enableOriginFailOver' : require(__dirname + '/plugins/aws/cloudfront/enableOriginFailOver.js'), + 'cloudfrontGeoRestriction' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontGeoRestriction.js'), + 'compressObjectsAutomatically' : require(__dirname + '/plugins/aws/cloudfront/compressObjectsAutomatically.js'), + + 'volumeEncryption' : require(__dirname + '/plugins/aws/comprehend/volumeEncryption.js'), + 'outputResultEncryption' : require(__dirname + '/plugins/aws/comprehend/outputResultEncryption.js'), + + 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), + 'stackFailedStatus' : require(__dirname + '/plugins/aws/cloudformation/stackFailedStatus.js'), + 'driftDetection' : require(__dirname + '/plugins/aws/cloudformation/driftDetection.js'), + 'stackTerminationProtection' : require(__dirname + '/plugins/aws/cloudformation/stackTerminationProtection.js'), + 'stackNotifications' : require(__dirname + '/plugins/aws/cloudformation/stackNotifications.js'), + 'cloudformationAdminPriviliges' : require(__dirname + '/plugins/aws/cloudformation/cloudformationAdminPriviliges.js'), + 'cloudformationInUse' : require(__dirname + '/plugins/aws/cloudformation/cloudformationInUse.js'), + + 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), + 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), + 'cloudtrailDataEvents' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailDataEvents.js'), + 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), + 'cloudtrailEncryption' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEncryption.js'), + 'cloudtrailFileValidation' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailFileValidation.js'), + 'cloudtrailObjectLock' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailObjectLock.js'), + 'cloudtrailToCloudwatch' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailToCloudwatch.js'), + 'cloudtrailBucketPrivate' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js'), + 'cloudtrailDeliveryFailing' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailDeliveryFailing.js'), + 'cloudtrailManagementEvents' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailManagementEvents.js'), + 'cloudtrailS3Bucket' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailS3Bucket.js'), + 'globalLoggingDuplicated' : require(__dirname + '/plugins/aws/cloudtrail/globalLoggingDuplicated.js'), + 'cloudtrailNotificationsEnabled': require(__dirname + '/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js'), + + 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), + 'configComplaintRules' : require(__dirname + '/plugins/aws/configservice/configComplaintRules.js'), + 'configDeliveryFailing' : require(__dirname + '/plugins/aws/configservice/configDeliveryFailing.js'), + 'configServiceMissingBucket' : require(__dirname + '/plugins/aws/configservice/configServiceMissingBucket.js'), 'ec2InstancesOptimized' : require(__dirname + '/plugins/aws/computeoptimizer/ec2InstancesOptimized.js'), - // 'devOpsGuruNotificationEnabled' : require(__dirname + '/plugins/aws/devopsguru/devOpsGuruNotificationEnabled.js'), + 'devOpsGuruNotificationEnabled' : require(__dirname + '/plugins/aws/devopsguru/devOpsGuruNotificationEnabled.js'), - // 'dmsEncryptionEnabled' : require(__dirname + '/plugins/aws/dms/dmsEncryptionEnabled.js'), - // 'dmsPubliclyAccessibleInstances': require(__dirname + '/plugins/aws/dms/dmsPubliclyAccessibleInstances.js'), - // 'dmsMultiAZFeatureEnabled' : require(__dirname + '/plugins/aws/dms/dmsMultiAZFeatureEnabled.js'), - // 'autoMinorVersionUpgrade' : require(__dirname + '/plugins/aws/dms/autoMinorVersionUpgrade.js'), - - // 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), - // 'daxClusterEncryption' : require(__dirname + '/plugins/aws/dynamodb/daxClusterEncryption.js'), - // 'dynamoContinuousBackups' : require(__dirname + '/plugins/aws/dynamodb/dynamoContinuousBackups.js'), - // 'dynamoTableBackupExists' : require(__dirname + '/plugins/aws/dynamodb/dynamoTableBackupExists.js'), - - // 'appTierInstanceIamRole' : require(__dirname + '/plugins/aws/ec2/appTierInstanceIamRole.js'), - // 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), - // 'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'), - // 'securityGroupRfc1918' : require(__dirname + '/plugins/aws/ec2/securityGroupRfc1918.js'), - // 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), - // 'unassociatedElasticIp' : require(__dirname + '/plugins/aws/ec2/unassociatedElasticIp.js'), - // 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), - // 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), - // 'instanceLimit' : require(__dirname + '/plugins/aws/ec2/instanceLimit.js'), - // 'instanceVcpusLimit' : require(__dirname + '/plugins/aws/ec2/instanceVcpusLimit.js'), - // 'instanceMaxCount' : require(__dirname + '/plugins/aws/ec2/instanceMaxCount.js'), - // 'instanceKeyBasedLogin' : require(__dirname + '/plugins/aws/ec2/instanceKeyBasedLogin.js'), - // 'openAllPortsProtocols' : require(__dirname + '/plugins/aws/ec2/openAllPortsProtocols.js'), - // 'openCIFS' : require(__dirname + '/plugins/aws/ec2/openCIFS.js'), - // 'openCustomPorts' : require(__dirname + '/plugins/aws/ec2/openCustomPorts.js'), - // 'openDNS' : require(__dirname + '/plugins/aws/ec2/openDNS.js'), - // 'openDocker' : require(__dirname + '/plugins/aws/ec2/openDocker.js'), - // 'openFTP' : require(__dirname + '/plugins/aws/ec2/openFTP.js'), - // 'openHadoopNameNode' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNode.js'), - // 'openHadoopNameNodeWebUI' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNodeWebUI.js'), - // 'openOracleAutoDataWarehouse' : require(__dirname + '/plugins/aws/ec2/openOracleAutoDataWarehouse.js'), - // 'openKibana' : require(__dirname + '/plugins/aws/ec2/openKibana.js'), - // 'openMySQL' : require(__dirname + '/plugins/aws/ec2/openMySQL.js'), - // 'openOracle' : require(__dirname + '/plugins/aws/ec2/openOracle.js'), - // 'openNetBIOS' : require(__dirname + '/plugins/aws/ec2/openNetBIOS.js'), - // 'openPostgreSQL' : require(__dirname + '/plugins/aws/ec2/openPostgreSQL.js'), - // 'openRDP' : require(__dirname + '/plugins/aws/ec2/openRDP.js'), - // 'openRPC' : require(__dirname + '/plugins/aws/ec2/openRPC.js'), - // 'openSalt' : require(__dirname + '/plugins/aws/ec2/openSalt.js'), - // 'openSMBoTCP' : require(__dirname + '/plugins/aws/ec2/openSMBoTCP.js'), - // 'openSMTP' : require(__dirname + '/plugins/aws/ec2/openSMTP.js'), - // 'openSQLServer' : require(__dirname + '/plugins/aws/ec2/openSQLServer.js'), - // 'openSSH' : require(__dirname + '/plugins/aws/ec2/openSSH.js'), - // 'openTelnet' : require(__dirname + '/plugins/aws/ec2/openTelnet.js'), - // 'openVNCClient' : require(__dirname + '/plugins/aws/ec2/openVNCClient.js'), - // 'openVNCServer' : require(__dirname + '/plugins/aws/ec2/openVNCServer.js'), - // 'openElasticsearch' : require(__dirname + '/plugins/aws/ec2/openElasticsearch.js'), - // 'vpcElasticIpLimit' : require(__dirname + '/plugins/aws/ec2/vpcElasticIpLimit.js'), - // 'classicInstances' : require(__dirname + '/plugins/aws/ec2/classicInstances.js'), - // 'flowLogsEnabled' : require(__dirname + '/plugins/aws/ec2/flowLogsEnabled.js'), - // 'vpcMultipleSubnets' : require(__dirname + '/plugins/aws/ec2/multipleSubnets.js'), - // 'overlappingSecurityGroups' : require(__dirname + '/plugins/aws/ec2/overlappingSecurityGroups.js'), - // 'publicAmi' : require(__dirname + '/plugins/aws/ec2/publicAmi.js'), - // 'encryptedAmi' : require(__dirname + '/plugins/aws/ec2/encryptedAmi.js'), - // 'instanceIamRole' : require(__dirname + '/plugins/aws/ec2/instanceIamRole.js'), - // 'ebsBackupEnabled' : require(__dirname + '/plugins/aws/ec2/ebsBackupEnabled.js'), - // 'ebsEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsEncryptionEnabled.js'), - // 'ebsSnapshotLifecycle' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotLifecycle.js'), - // 'ebsOldSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsOldSnapshots.js'), - // 'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'), - // 'ebsSnapshotPublic' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPublic.js'), - // 'unusedSecurityGroups' : require(__dirname + '/plugins/aws/ec2/unusedSecurityGroups.js'), - - // 'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'), - // 'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'), - // 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), - // 'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'), - // 'vpcEndpointAcceptance' : require(__dirname + '/plugins/aws/ec2/vpcEndpointAcceptance'), - // 'vpcEndpointExposed' : require(__dirname + '/plugins/aws/ec2/vpcEndpointExposed.js'), - // 'vpcEndpointCrossAccount' : require(__dirname + '/plugins/aws/ec2/vpcEndpointCrossAccount.js'), - // 'vpcPeeringConnections' : require(__dirname + '/plugins/aws/ec2/vpcPeeringConnections.js'), - // 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), - // 'ebsDefaultEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsDefaultEncryptionEnabled.js'), - // 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), - // 'unusedEni' : require(__dirname + '/plugins/aws/ec2/unusedEni.js'), - // 'unusedAmi' : require(__dirname + '/plugins/aws/ec2/unusedAmi.js'), - // 'unusedVpcInternetGateways' : require(__dirname + '/plugins/aws/ec2/unusedVpcInternetGateways.js'), - // 'managedNatGateway' : require(__dirname + '/plugins/aws/ec2/managedNatGateway.js'), - // 'allowedCustomPorts' : require(__dirname + '/plugins/aws/ec2/allowedCustomPorts.js'), - // 'ebsUnusedVolumes' : require(__dirname + '/plugins/aws/ec2/ebsUnusedVolumes.js'), - // 'publicIpAddress' : require(__dirname + '/plugins/aws/ec2/publicIpAddress.js'), - // 'unusedVirtualPrivateGateway' : require(__dirname + '/plugins/aws/ec2/unusedVirtualPrivateGateway.js'), - // 'vpcSubnetInstancesPresent' : require(__dirname + '/plugins/aws/ec2/vpcSubnetInstancesPresent.js'), - // 'webTierInstanceIamRole' : require(__dirname + '/plugins/aws/ec2/webTierInstanceIamRole.js'), - // 'vpnTunnelState' : require(__dirname + '/plugins/aws/ec2/vpnTunnelState.js'), - // 'networkAclOutboundTraffic' : require(__dirname + '/plugins/aws/ec2/networkAclOutboundTraffic.js'), - // 'outdatedAmiInUse' : require(__dirname + '/plugins/aws/ec2/outdatedAmiInUse.js'), - - // 'efsCmkEncrypted' : require(__dirname + '/plugins/aws/efs/efsCmkEncrypted.js'), - // 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), - - // 'ecrRepositoryPolicy' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryPolicy.js'), - // 'ecrRepositoryEncrypted' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryEncrypted.js'), - // 'ecrRepositoryTagImmutability' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryTagImmutability.js'), - - // 'managedPlatformUpdates' : require(__dirname + '/plugins/aws/elasticbeanstalk/managedPlatformUpdates.js'), - // 'enhancedHealthReporting' : require(__dirname + '/plugins/aws/elasticbeanstalk/enhancedHealthReporting.js'), - // 'environmentAccessLogs' : require(__dirname + '/plugins/aws/elasticbeanstalk/environmentAccessLogs.js'), - // 'environmentPersistentLogs' : require(__dirname + '/plugins/aws/elasticbeanstalk/environmentPersistentLogs.js'), - - // 'eksKubernetesVersion' : require(__dirname + '/plugins/aws/eks/eksKubernetesVersion.js'), - // 'eksLoggingEnabled' : require(__dirname + '/plugins/aws/eks/eksLoggingEnabled.js'), - // 'eksPrivateEndpoint' : require(__dirname + '/plugins/aws/eks/eksPrivateEndpoint.js'), - // 'eksSecretsEncrypted' : require(__dirname + '/plugins/aws/eks/eksSecretsEncrypted.js'), - // 'eksSecurityGroups' : require(__dirname + '/plugins/aws/eks/eksSecurityGroups.js'), - // 'eksLatestPlatformVersion' : require(__dirname + '/plugins/aws/eks/eksLatestPlatformVersion.js'), + 'dmsEncryptionEnabled' : require(__dirname + '/plugins/aws/dms/dmsEncryptionEnabled.js'), + 'dmsPubliclyAccessibleInstances': require(__dirname + '/plugins/aws/dms/dmsPubliclyAccessibleInstances.js'), + 'dmsMultiAZFeatureEnabled' : require(__dirname + '/plugins/aws/dms/dmsMultiAZFeatureEnabled.js'), + 'autoMinorVersionUpgrade' : require(__dirname + '/plugins/aws/dms/autoMinorVersionUpgrade.js'), + + 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), + 'daxClusterEncryption' : require(__dirname + '/plugins/aws/dynamodb/daxClusterEncryption.js'), + 'dynamoContinuousBackups' : require(__dirname + '/plugins/aws/dynamodb/dynamoContinuousBackups.js'), + 'dynamoTableBackupExists' : require(__dirname + '/plugins/aws/dynamodb/dynamoTableBackupExists.js'), + + 'appTierInstanceIamRole' : require(__dirname + '/plugins/aws/ec2/appTierInstanceIamRole.js'), + 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), + 'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'), + 'securityGroupRfc1918' : require(__dirname + '/plugins/aws/ec2/securityGroupRfc1918.js'), + 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), + 'unassociatedElasticIp' : require(__dirname + '/plugins/aws/ec2/unassociatedElasticIp.js'), + 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), + 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), + 'instanceLimit' : require(__dirname + '/plugins/aws/ec2/instanceLimit.js'), + 'instanceVcpusLimit' : require(__dirname + '/plugins/aws/ec2/instanceVcpusLimit.js'), + 'instanceMaxCount' : require(__dirname + '/plugins/aws/ec2/instanceMaxCount.js'), + 'instanceKeyBasedLogin' : require(__dirname + '/plugins/aws/ec2/instanceKeyBasedLogin.js'), + 'openAllPortsProtocols' : require(__dirname + '/plugins/aws/ec2/openAllPortsProtocols.js'), + 'openCIFS' : require(__dirname + '/plugins/aws/ec2/openCIFS.js'), + 'openCustomPorts' : require(__dirname + '/plugins/aws/ec2/openCustomPorts.js'), + 'openDNS' : require(__dirname + '/plugins/aws/ec2/openDNS.js'), + 'openDocker' : require(__dirname + '/plugins/aws/ec2/openDocker.js'), + 'openFTP' : require(__dirname + '/plugins/aws/ec2/openFTP.js'), + 'openHadoopNameNode' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNode.js'), + 'openHadoopNameNodeWebUI' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNodeWebUI.js'), + 'openOracleAutoDataWarehouse' : require(__dirname + '/plugins/aws/ec2/openOracleAutoDataWarehouse.js'), + 'openKibana' : require(__dirname + '/plugins/aws/ec2/openKibana.js'), + 'openMySQL' : require(__dirname + '/plugins/aws/ec2/openMySQL.js'), + 'openOracle' : require(__dirname + '/plugins/aws/ec2/openOracle.js'), + 'openNetBIOS' : require(__dirname + '/plugins/aws/ec2/openNetBIOS.js'), + 'openPostgreSQL' : require(__dirname + '/plugins/aws/ec2/openPostgreSQL.js'), + 'openRDP' : require(__dirname + '/plugins/aws/ec2/openRDP.js'), + 'openRPC' : require(__dirname + '/plugins/aws/ec2/openRPC.js'), + 'openSalt' : require(__dirname + '/plugins/aws/ec2/openSalt.js'), + 'openSMBoTCP' : require(__dirname + '/plugins/aws/ec2/openSMBoTCP.js'), + 'openSMTP' : require(__dirname + '/plugins/aws/ec2/openSMTP.js'), + 'openSQLServer' : require(__dirname + '/plugins/aws/ec2/openSQLServer.js'), + 'openSSH' : require(__dirname + '/plugins/aws/ec2/openSSH.js'), + 'openTelnet' : require(__dirname + '/plugins/aws/ec2/openTelnet.js'), + 'openVNCClient' : require(__dirname + '/plugins/aws/ec2/openVNCClient.js'), + 'openVNCServer' : require(__dirname + '/plugins/aws/ec2/openVNCServer.js'), + 'openElasticsearch' : require(__dirname + '/plugins/aws/ec2/openElasticsearch.js'), + 'vpcElasticIpLimit' : require(__dirname + '/plugins/aws/ec2/vpcElasticIpLimit.js'), + 'classicInstances' : require(__dirname + '/plugins/aws/ec2/classicInstances.js'), + 'flowLogsEnabled' : require(__dirname + '/plugins/aws/ec2/flowLogsEnabled.js'), + 'vpcMultipleSubnets' : require(__dirname + '/plugins/aws/ec2/multipleSubnets.js'), + 'overlappingSecurityGroups' : require(__dirname + '/plugins/aws/ec2/overlappingSecurityGroups.js'), + 'publicAmi' : require(__dirname + '/plugins/aws/ec2/publicAmi.js'), + 'encryptedAmi' : require(__dirname + '/plugins/aws/ec2/encryptedAmi.js'), + 'instanceIamRole' : require(__dirname + '/plugins/aws/ec2/instanceIamRole.js'), + 'ebsBackupEnabled' : require(__dirname + '/plugins/aws/ec2/ebsBackupEnabled.js'), + 'ebsEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsEncryptionEnabled.js'), + 'ebsSnapshotLifecycle' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotLifecycle.js'), + 'ebsOldSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsOldSnapshots.js'), + 'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'), + 'ebsSnapshotPublic' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPublic.js'), + 'unusedSecurityGroups' : require(__dirname + '/plugins/aws/ec2/unusedSecurityGroups.js'), + + 'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'), + 'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'), + 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), + 'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'), + 'vpcEndpointAcceptance' : require(__dirname + '/plugins/aws/ec2/vpcEndpointAcceptance'), + 'vpcEndpointExposed' : require(__dirname + '/plugins/aws/ec2/vpcEndpointExposed.js'), + 'vpcEndpointCrossAccount' : require(__dirname + '/plugins/aws/ec2/vpcEndpointCrossAccount.js'), + 'vpcPeeringConnections' : require(__dirname + '/plugins/aws/ec2/vpcPeeringConnections.js'), + 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), + 'ebsDefaultEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsDefaultEncryptionEnabled.js'), + 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), + 'unusedEni' : require(__dirname + '/plugins/aws/ec2/unusedEni.js'), + 'unusedAmi' : require(__dirname + '/plugins/aws/ec2/unusedAmi.js'), + 'unusedVpcInternetGateways' : require(__dirname + '/plugins/aws/ec2/unusedVpcInternetGateways.js'), + 'managedNatGateway' : require(__dirname + '/plugins/aws/ec2/managedNatGateway.js'), + 'allowedCustomPorts' : require(__dirname + '/plugins/aws/ec2/allowedCustomPorts.js'), + 'ebsUnusedVolumes' : require(__dirname + '/plugins/aws/ec2/ebsUnusedVolumes.js'), + 'publicIpAddress' : require(__dirname + '/plugins/aws/ec2/publicIpAddress.js'), + 'unusedVirtualPrivateGateway' : require(__dirname + '/plugins/aws/ec2/unusedVirtualPrivateGateway.js'), + 'vpcSubnetInstancesPresent' : require(__dirname + '/plugins/aws/ec2/vpcSubnetInstancesPresent.js'), + 'webTierInstanceIamRole' : require(__dirname + '/plugins/aws/ec2/webTierInstanceIamRole.js'), + 'vpnTunnelState' : require(__dirname + '/plugins/aws/ec2/vpnTunnelState.js'), + 'networkAclOutboundTraffic' : require(__dirname + '/plugins/aws/ec2/networkAclOutboundTraffic.js'), + 'outdatedAmiInUse' : require(__dirname + '/plugins/aws/ec2/outdatedAmiInUse.js'), + + 'efsCmkEncrypted' : require(__dirname + '/plugins/aws/efs/efsCmkEncrypted.js'), + 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), + + 'ecrRepositoryPolicy' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryPolicy.js'), + 'ecrRepositoryEncrypted' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryEncrypted.js'), + 'ecrRepositoryTagImmutability' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryTagImmutability.js'), + + 'managedPlatformUpdates' : require(__dirname + '/plugins/aws/elasticbeanstalk/managedPlatformUpdates.js'), + 'enhancedHealthReporting' : require(__dirname + '/plugins/aws/elasticbeanstalk/enhancedHealthReporting.js'), + 'environmentAccessLogs' : require(__dirname + '/plugins/aws/elasticbeanstalk/environmentAccessLogs.js'), + 'environmentPersistentLogs' : require(__dirname + '/plugins/aws/elasticbeanstalk/environmentPersistentLogs.js'), + + 'eksKubernetesVersion' : require(__dirname + '/plugins/aws/eks/eksKubernetesVersion.js'), + 'eksLoggingEnabled' : require(__dirname + '/plugins/aws/eks/eksLoggingEnabled.js'), + 'eksPrivateEndpoint' : require(__dirname + '/plugins/aws/eks/eksPrivateEndpoint.js'), + 'eksSecretsEncrypted' : require(__dirname + '/plugins/aws/eks/eksSecretsEncrypted.js'), + 'eksSecurityGroups' : require(__dirname + '/plugins/aws/eks/eksSecurityGroups.js'), + 'eksLatestPlatformVersion' : require(__dirname + '/plugins/aws/eks/eksLatestPlatformVersion.js'), - // 'kendraIndexEncrypted' : require(__dirname + '/plugins/aws/kendra/kendraIndexEncrypted.js'), + 'kendraIndexEncrypted' : require(__dirname + '/plugins/aws/kendra/kendraIndexEncrypted.js'), - // 'environmentTemplateEncrypted' : require(__dirname + '/plugins/aws/proton/environmentTemplateEncrypted.js'), + 'environmentTemplateEncrypted' : require(__dirname + '/plugins/aws/proton/environmentTemplateEncrypted.js'), - // 'crosszoneLoadBalancing' : require(__dirname + '/plugins/aws/elb/crosszoneLoadBalancing.js'), - // 'insecureCiphers' : require(__dirname + '/plugins/aws/elb/insecureCiphers.js'), - // 'elbHttpsOnly' : require(__dirname + '/plugins/aws/elb/elbHttpsOnly.js'), - // 'elbLoggingEnabled' : require(__dirname + '/plugins/aws/elb/elbLoggingEnabled.js'), - // 'elbNoInstances' : require(__dirname + '/plugins/aws/elb/elbNoInstances.js'), - // 'classicELBInUse' : require(__dirname + '/plugins/aws/elb/classicELBInUse.js'), - // 'connectionDrainingEnabled' : require(__dirname + '/plugins/aws/elb/connectionDrainingEnabled.js'), - // 'appTierElbSecurity' : require(__dirname + '/plugins/aws/elb/appTierElbSecurity.js'), - - // 'elbv2DeletionProtection' : require(__dirname + '/plugins/aws/elbv2/elbv2DeletionProtection.js'), - // 'elbv2LoggingEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2LoggingEnabled.js'), - // 'elbv2HttpsOnly' : require(__dirname + '/plugins/aws/elbv2/elbv2HttpsOnly.js'), - // 'elbv2NoInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2NoInstances.js'), - // 'elbv2WafEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2WafEnabled.js'), - // 'elbv2MinimumTargetInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2MinimumTargetInstances.js'), - // 'elbv2NlbListenerSecurity' : require(__dirname + '/plugins/aws/elbv2/elbv2NlbListenerSecurity.js'), - // 'elbv2DeregistrationDelay' : require(__dirname + '/plugins/aws/elbv2/elbv2DeregistrationDelay.js'), - // 'elbv2SslTermination' : require(__dirname + '/plugins/aws/elbv2/elbv2SslTermination.js'), - - // 'elasticacheDefaultPorts' : require(__dirname + '/plugins/aws/elasticache/elasticacheDefaultPorts.js'), - - // 'emrClusterLogging' : require(__dirname + '/plugins/aws/emr/emrClusterLogging.js'), - // 'emrClusterInVPC' : require(__dirname + '/plugins/aws/emr/emrClusterInVPC.js'), - // 'emrEncryptionInTransit' : require(__dirname + '/plugins/aws/emr/emrEncryptionInTransit.js'), - // 'emrEncryptionAtRest' : require(__dirname + '/plugins/aws/emr/emrEncryptionAtRest.js'), - // 'emrDesiredInstanceType' : require(__dirname + '/plugins/aws/emr/emrDesiredInstanceType.js'), - // 'emrInstanceCount' : require(__dirname + '/plugins/aws/emr/emrInstanceCount.js'), - - // 'esAccessFromIps' : require(__dirname + '/plugins/aws/es/esAccessFromIps.js'), - // 'esPublicEndpoint' : require(__dirname + '/plugins/aws/es/esPublicEndpoint.js'), - // 'esRequireIAMAuth' : require(__dirname + '/plugins/aws/es/esRequireIAMAuth.js'), - // 'esEncryptedDomain' : require(__dirname + '/plugins/aws/es/esEncryptedDomain.js'), - // 'esExposedDomain' : require(__dirname + '/plugins/aws/es/esExposedDomain.js'), - // 'esNodeToNodeEncryption' : require(__dirname + '/plugins/aws/es/esNodeToNodeEncryption.js'), - // 'esLoggingEnabled' : require(__dirname + '/plugins/aws/es/esLoggingEnabled.js'), - // 'esUpgradeAvailable' : require(__dirname + '/plugins/aws/es/esUpgradeAvailable.js'), - // 'esHttpsOnly' : require(__dirname + '/plugins/aws/es/esHttpsOnly.js'), - // 'esCrossAccountAccess' : require(__dirname + '/plugins/aws/es/esCrossAccountAccess.js'), - // 'esClusterStatus' : require(__dirname + '/plugins/aws/es/esClusterStatus.js'), - // 'esDedicatedMasterEnabled' : require(__dirname + '/plugins/aws/es/esDedicatedMasterEnabled.js'), - // 'esDesiredInstanceTypes' : require(__dirname + '/plugins/aws/es/esDesiredInstanceTypes.js'), - // 'esTlsVersion' : require(__dirname + '/plugins/aws/es/esTlsVersion.js'), - // 'esDomainEncryptionEnabled' : require(__dirname + '/plugins/aws/es/esDomainEncryptionEnabled.js'), - // 'vaultPublicAccess' : require(__dirname + '/plugins/aws/s3glacier/vaultPublicAccess.js'), - // 'firehoseEncrypted' : require(__dirname + '/plugins/aws/firehose/firehoseEncrypted.js'), - // 'deliveryStreamEncrypted' : require(__dirname + '/plugins/aws/firehose/deliveryStreamEncrypted.js'), - - // 'eventBusCrossAccountAccess' : require(__dirname + '/plugins/aws/eventbridge/eventBusCrossAccountAccess.js'), - // 'eventBusPublicAccess' : require(__dirname + '/plugins/aws/eventbridge/eventBusPublicAccess.js'), - // 'eventsInUse' : require(__dirname + '/plugins/aws/eventbridge/eventsInUse.js'), - - // 'glueCloudwatchLogsEncrypted' : require(__dirname + '/plugins/aws/glue/glueCloudwatchLogsEncrypted.js'), - // 'glueS3EncryptionEnabled' : require(__dirname + '/plugins/aws/glue/glueS3EncryptionEnabled.js'), - // 'dataCatalogCmkEncrypted' : require(__dirname + '/plugins/aws/glue/dataCatalogCmkEncrypted.js'), - // 'bookmarkEncryptionEnabled' : require(__dirname + '/plugins/aws/glue/bookmarkEncryptionEnabled.js'), - // 'dataCatalogEncryptionEnabled' : require(__dirname + '/plugins/aws/glue/dataCatalogEncryptionEnabled.js'), - - // 'accessKeysExtra' : require(__dirname + '/plugins/aws/iam/accessKeysExtra.js'), - // 'accessKeysLastUsed' : require(__dirname + '/plugins/aws/iam/accessKeysLastUsed.js'), - // 'accessKeysRotated' : require(__dirname + '/plugins/aws/iam/accessKeysRotated.js'), - // 'certificateExpiry' : require(__dirname + '/plugins/aws/iam/certificateExpiry.js'), - // 'crossAccountMfaExtIdAccess' : require(__dirname + '/plugins/aws/iam/crossAccountMfaExtIdAccess.js'), - // 'emptyGroups' : require(__dirname + '/plugins/aws/iam/emptyGroups.js'), - // 'groupInlinePolicies' : require(__dirname + '/plugins/aws/iam/groupInlinePolicies.js'), - // 'iamMasterManagerRoles' : require(__dirname + '/plugins/aws/iam/iamMasterManagerRoles.js'), - // 'iamUserAdmins' : require(__dirname + '/plugins/aws/iam/iamUserAdmins.js'), - // 'iamUserNameRegex' : require(__dirname + '/plugins/aws/iam/iamUserNameRegex.js'), - // 'iamUserUnauthorizedToEdit' : require(__dirname + '/plugins/aws/iam/iamUserUnauthorizedToEdit'), - // 'iamRolePolicies' : require(__dirname + '/plugins/aws/iam/iamRolePolicies.js'), - // 'iamRoleLastUsed' : require(__dirname + '/plugins/aws/iam/iamRoleLastUsed.js'), - // 'maxPasswordAge' : require(__dirname + '/plugins/aws/iam/maxPasswordAge.js'), - // 'minPasswordLength' : require(__dirname + '/plugins/aws/iam/minPasswordLength.js'), - // 'noUserIamPolicies' : require(__dirname + '/plugins/aws/iam/noUserIamPolicies.js'), - // 'passwordExpiration' : require(__dirname + '/plugins/aws/iam/passwordExpiration.js'), - // 'passwordRequiresLowercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresLowercase.js'), - // 'passwordRequiresNumbers' : require(__dirname + '/plugins/aws/iam/passwordRequiresNumbers.js'), - // 'passwordRequiresSymbols' : require(__dirname + '/plugins/aws/iam/passwordRequiresSymbols.js'), - // 'passwordRequiresUppercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresUppercase.js'), - // 'passwordReusePrevention' : require(__dirname + '/plugins/aws/iam/passwordReusePrevention.js'), - // 'rootAccessKeys' : require(__dirname + '/plugins/aws/iam/rootAccessKeys.js'), - // 'rootSigningCertificate' : require(__dirname + '/plugins/aws/iam/rootSigningCertificate.js'), - // 'rootAccountInUse' : require(__dirname + '/plugins/aws/iam/rootAccountInUse.js'), - // 'rootHardwareMfa' : require(__dirname + '/plugins/aws/iam/rootHardwareMfa.js'), - // 'rootMfaEnabled' : require(__dirname + '/plugins/aws/iam/rootMfaEnabled.js'), - // 'sshKeysRotated' : require(__dirname + '/plugins/aws/iam/sshKeysRotated.js'), - // 'trustedCrossAccountRoles' : require(__dirname + '/plugins/aws/iam/trustedCrossAccountRoles.js'), - // 'usersMfaEnabled' : require(__dirname + '/plugins/aws/iam/usersMfaEnabled.js'), - // 'usersPasswordAndKeys' : require(__dirname + '/plugins/aws/iam/usersPasswordAndKeys.js'), - // 'usersPasswordLastUsed' : require(__dirname + '/plugins/aws/iam/usersPasswordLastUsed.js'), - // 'canaryKeysUsed' : require(__dirname + '/plugins/aws/iam/canaryKeysUsed.js'), - // 'iamPoliciesPresent' : require(__dirname + '/plugins/aws/iam/iamPoliciesPresent.js'), - // 'iamDbAuthenticationEnabled' : require(__dirname + '/plugins/aws/rds/iamDbAuthenticationEnabled.js'), - // 'iamSupportPolicy' : require(__dirname + '/plugins/aws/iam/iamSupportPolicy.js'), - // 'iamUserPresent' : require(__dirname + '/plugins/aws/iam/iamUserPresent.js'), - - // 'iamUserInUse' : require(__dirname + '/plugins/aws/iam/iamUserInUse.js'), - // 'kinesisEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisEncrypted.js'), - // 'kinesisDataStreamsEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisDataStreamsEncrypted.js'), - // 'videostreamDataEncrypted' : require(__dirname + '/plugins/aws/kinesisvideo/videostreamDataEncrypted.js'), - - // 'kmsKeyRotation' : require(__dirname + '/plugins/aws/kms/kmsKeyRotation.js'), - // 'kmsScheduledDeletion' : require(__dirname + '/plugins/aws/kms/kmsScheduledDeletion.js'), - // 'kmsKeyPolicy' : require(__dirname + '/plugins/aws/kms/kmsKeyPolicy.js'), - // 'kmsDefaultKeyUsage' : require(__dirname + '/plugins/aws/kms/kmsDefaultKeyUsage.js'), - // 'kmsAppTierCmk' : require(__dirname + '/plugins/aws/kms/kmsAppTierCmk.js'), - // 'kmsGrantLeastPrivilege' : require(__dirname + '/plugins/aws/kms/kmsGrantLeastPrivilege.js'), - // 'kmsDuplicateGrants' : require(__dirname + '/plugins/aws/kms/kmsDuplicateGrants.js'), - - // 'rdsAutomatedBackups' : require(__dirname + '/plugins/aws/rds/rdsAutomatedBackups.js'), - // 'rdsEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsEncryptionEnabled.js'), - // 'rdsCmkEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsCmkEncryptionEnabled.js'), - // 'rdsLoggingEnabled' : require(__dirname + '/plugins/aws/rds/rdsLoggingEnabled.js'), - // 'rdsPubliclyAccessible' : require(__dirname + '/plugins/aws/rds/rdsPubliclyAccessible.js'), - // 'rdsRestorable' : require(__dirname + '/plugins/aws/rds/rdsRestorable.js'), - // 'rdsMultiAz' : require(__dirname + '/plugins/aws/rds/rdsMultiAz.js'), - // 'rdsSnapshotEncryption' : require(__dirname + '/plugins/aws/rds/rdsSnapshotEncryption.js'), - // 'rdsMinorVersionUpgrade' : require(__dirname + '/plugins/aws/rds/rdsMinorVersionUpgrade.js'), - // 'sqlServerTLSVersion' : require(__dirname + '/plugins/aws/rds/sqlServerTLSVersion'), - // 'rdsTransportEncryption' : require(__dirname + '/plugins/aws/rds/rdsTransportEncryption'), - // 'rdsDeletionProtectionEnabled' : require(__dirname + '/plugins/aws/rds/rdsDeletionProtectionEnabled.js'), - - // 'redisClusterEncryptionInTransit': require(__dirname + '/plugins/aws/elasticache/redisClusterEncryptionInTransit.js'), - // 'elasticacheClusterInVpc' : require(__dirname + '/plugins/aws/elasticache/elasticacheClusterInVpc.js'), - // 'elasticacheInstanceGeneration' : require(__dirname + '/plugins/aws/elasticache/elasticacheInstanceGeneration.js'), - // 'redisEngineVersions' : require(__dirname + '/plugins/aws/elasticache/redisEngineVersions.js'), - // 'elasticacheNodesCount' : require(__dirname + '/plugins/aws/elasticache/elasticacheNodesCount.js'), - // 'elasticacheRedisMultiAZ' : require(__dirname + '/plugins/aws/elasticache/elasticacheRedisMultiAZ.js'), - // 'idleElastiCacheNode' : require(__dirname + '/plugins/aws/elasticache/idleElastiCacheNode.js'), - // 'elasticaheDesiredNodeType' : require(__dirname + '/plugins/aws/elasticache/elasticaheDesiredNodeType.js'), - - // 'domainAutoRenew' : require(__dirname + '/plugins/aws/route53/domainAutoRenew.js'), - // 'domainExpiry' : require(__dirname + '/plugins/aws/route53/domainExpiry.js'), - // 'domainTransferLock' : require(__dirname + '/plugins/aws/route53/domainTransferLock.js'), - // 'danglingDnsRecords' : require(__dirname + '/plugins/aws/route53/danglingDnsRecords.js'), - // 'privacyProtection' : require(__dirname + '/plugins/aws/route53/privacyProtection.js'), - // 'senderPolicyFwInUse' : require(__dirname + '/plugins/aws/route53/senderPolicyFwInUse.js'), - // 'senderPolicyFwRecordPresent' : require(__dirname + '/plugins/aws/route53/senderPolicyFwRecordPresent.js'), - - // 'bucketEncryptionInTransit' : require(__dirname + '/plugins/aws/s3/bucketEncryptionInTransit.js'), - // 'bucketAllUsersPolicy' : require(__dirname + '/plugins/aws/s3/bucketAllUsersPolicy.js'), - // 'bucketAllUsersAcl' : require(__dirname + '/plugins/aws/s3/bucketAllUsersAcl.js'), - // 'bucketPolicyCloudFrontOai' : require(__dirname + '/plugins/aws/s3/bucketPolicyCloudFrontOai.js'), - // 'bucketVersioning' : require(__dirname + '/plugins/aws/s3/bucketVersioning.js'), - // 'bucketLogging' : require(__dirname + '/plugins/aws/s3/bucketLogging.js'), - // 's3Encryption' : require(__dirname + '/plugins/aws/s3/s3Encryption.js'), - // 'bucketPublicAccessBlock' : require(__dirname + '/plugins/aws/s3/bucketPublicAccessBlock.js'), - // 'bucketEncryption' : require(__dirname + '/plugins/aws/s3/bucketEncryption.js'), - // 'bucketWebsiteEnabled' : require(__dirname + '/plugins/aws/s3/bucketWebsiteEnabled.js'), - // 'bucketEnforceEncryption' : require(__dirname + '/plugins/aws/s3/bucketEnforceEncryption.js'), - // 'bucketSecureTransportEnabled' : require(__dirname + '/plugins/aws/s3/bucketSecureTransportEnabled.js'), - // 'bucketLifecycleConfiguration' : require(__dirname + '/plugins/aws/s3/bucketLifecycleConfiguration'), - // 'bucketTransferAcceleration' : require(__dirname + '/plugins/aws/s3/bucketTransferAcceleration'), - // 'bucketDnsCompliantName' : require(__dirname + '/plugins/aws/s3/bucketDnsCompliantName.js'), - // 'versionedBucketsLC' : require(__dirname + '/plugins/aws/s3/versionedBucketsLC.js'), - - // 'notebookDataEncrypted' : require(__dirname + '/plugins/aws/sagemaker/notebookDataEncrypted.js'), - // 'notebookDirectInternetAccess' : require(__dirname + '/plugins/aws/sagemaker/notebookDirectInternetAccess.js'), - // 'notebookInstanceInVpc' : require(__dirname + '/plugins/aws/sagemaker/notebookInstanceInVpc.js'), - - // 'dkimEnabled' : require(__dirname + '/plugins/aws/ses/dkimEnabled.js'), - // 'emailMessagesEncrypted' : require(__dirname + '/plugins/aws/ses/emailMessagesEncrypted.js'), - - // 'topicEncrypted' : require(__dirname + '/plugins/aws/sns/topicEncrypted.js'), - // 'topicPolicies' : require(__dirname + '/plugins/aws/sns/topicPolicies.js'), - // 'topicCmkEncrypted' : require(__dirname + '/plugins/aws/sns/topicCmkEncrypted.js'), - // 'snsCrossAccount' : require(__dirname + '/plugins/aws/sns/snsCrossAccount.js'), - // 'snsValidSubscribers' : require(__dirname + '/plugins/aws/sns/snsValidSubscribers.js'), - - // 'sqsCrossAccount' : require(__dirname + '/plugins/aws/sqs/sqsCrossAccount.js'), - // 'sqsDeadLetterQueue' : require(__dirname + '/plugins/aws/sqs/sqsDeadLetterQueue.js'), - // 'sqsEncrypted' : require(__dirname + '/plugins/aws/sqs/sqsEncrypted.js'), - // 'sqsPublicAccess' : require(__dirname + '/plugins/aws/sqs/sqsPublicAccess.js'), - // 'queueUnprocessedMessages' : require(__dirname + '/plugins/aws/sqs/queueUnprocessedMessages.js'), - // 'sqsEncryptionEnabled' : require(__dirname + '/plugins/aws/sqs/sqsEncryptionEnabled.js'), - - // 'ssmEncryptedParameters' : require(__dirname + '/plugins/aws/ssm/ssmEncryptedParameters.js'), - // 'ssmActiveOnAllInstances' : require(__dirname + '/plugins/aws/ssm/ssmActiveOnAllInstances.js'), - // 'ssmAgentLatestVersion' : require(__dirname + '/plugins/aws/ssm/ssmAgentLatestVersion.js'), - // 'ssmAgentAutoUpdateEnabled' : require(__dirname + '/plugins/aws/ssm/ssmAgentAutoUpdateEnabled'), - // 'ssmDocumentPublicAccess' : require(__dirname + '/plugins/aws/ssm/ssmDocumentPublicAccess'), - // 'ssmManagedInstances' : require(__dirname + '/plugins/aws/ssm/ssmManagedInstances'), - // 'ssmSessionDuration' : require(__dirname + '/plugins/aws/ssm/ssmSessionDuration'), - - // 'ledgerEncrypted' : require(__dirname + '/plugins/aws/qldb/ledgerEncrypted'), - - // 'lambdaAdminPrivileges' : require(__dirname + '/plugins/aws/lambda/lambdaAdminPrivileges.js'), - // 'envVarsClientSideEncryption' : require(__dirname + '/plugins/aws/lambda/envVarsClientSideEncryption.js'), - // 'lambdaOldRuntimes' : require(__dirname + '/plugins/aws/lambda/lambdaOldRuntimes.js'), - // 'lambdaVpcConfig' : require(__dirname + '/plugins/aws/lambda/lambdaVpcConfig.js'), - // 'lambdaPublicAccess' : require(__dirname + '/plugins/aws/lambda/lambdaPublicAccess.js'), - // 'lambdaLogGroups' : require(__dirname + '/plugins/aws/lambda/lambdaLogGroups.js'), - // 'lambdaTracingEnabled' : require(__dirname + '/plugins/aws/lambda/lambdaTracingEnabled.js'), - - // 'webServerPublicAccess' : require(__dirname + '/plugins/aws/mwaa/webServerPublicAccess.js'), - // 'environmentAdminPrivileges' : require(__dirname + '/plugins/aws/mwaa/environmentAdminPrivileges.js'), - // 'environmentDataEncrypted' : require(__dirname + '/plugins/aws/mwaa/environmentDataEncrypted.js'), - - // 'neptuneDBInstanceEncrypted' : require(__dirname + '/plugins/aws/neptune/neptuneDBInstanceEncrypted.js'), - - // 'monitoringMetrics' : require(__dirname + '/plugins/aws/cloudwatchlogs/monitoringMetrics.js'), - - // 'customerProfilesDomainEncrypted' : require(__dirname + '/plugins/aws/connect/customerProfilesDomainEncrypted.js'), - // 'wisdomDomainEncrypted' : require(__dirname + '/plugins/aws/connect/wisdomDomainEncrypted.js'), - // 'voiceIdDomainEncrypted' : require(__dirname + '/plugins/aws/connect/voiceIdDomainEncrypted.js'), - - // 'logRetentionPeriod' : require(__dirname + '/plugins/aws/cloudwatchlogs/logRetentionPeriod.js'), - // 'logGroupsEncrypted' : require(__dirname + '/plugins/aws/cloudwatchlogs/logGroupsEncrypted.js'), - - // 'vpcFlowLogsMetricAlarm' : require(__dirname + '/plugins/aws/cloudwatch/vpcFlowLogsMetricAlarm.js'), - - // 'timestreamDatabaseEncrypted' : require(__dirname + '/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js'), - - // 'mqAutoMinorVersionUpgrade' : require(__dirname + '/plugins/aws/mq/mqAutoMinorVersionUpgrade.js'), - // 'mqLogExports' : require(__dirname + '/plugins/aws/mq/mqLogExports.js'), - // 'mqDeploymentMode' : require(__dirname + '/plugins/aws/mq/mqDeploymentMode.js'), - // 'mqDesiredInstanceType' : require(__dirname + '/plugins/aws/mq/mqDesiredInstanceType.js'), - // 'mqBrokerEncrypted' : require(__dirname + '/plugins/aws/mq/mqBrokerEncrypted.js'), + 'crosszoneLoadBalancing' : require(__dirname + '/plugins/aws/elb/crosszoneLoadBalancing.js'), + 'insecureCiphers' : require(__dirname + '/plugins/aws/elb/insecureCiphers.js'), + 'elbHttpsOnly' : require(__dirname + '/plugins/aws/elb/elbHttpsOnly.js'), + 'elbLoggingEnabled' : require(__dirname + '/plugins/aws/elb/elbLoggingEnabled.js'), + 'elbNoInstances' : require(__dirname + '/plugins/aws/elb/elbNoInstances.js'), + 'classicELBInUse' : require(__dirname + '/plugins/aws/elb/classicELBInUse.js'), + 'connectionDrainingEnabled' : require(__dirname + '/plugins/aws/elb/connectionDrainingEnabled.js'), + 'appTierElbSecurity' : require(__dirname + '/plugins/aws/elb/appTierElbSecurity.js'), + + 'elbv2DeletionProtection' : require(__dirname + '/plugins/aws/elbv2/elbv2DeletionProtection.js'), + 'elbv2LoggingEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2LoggingEnabled.js'), + 'elbv2HttpsOnly' : require(__dirname + '/plugins/aws/elbv2/elbv2HttpsOnly.js'), + 'elbv2NoInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2NoInstances.js'), + 'elbv2WafEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2WafEnabled.js'), + 'elbv2MinimumTargetInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2MinimumTargetInstances.js'), + 'elbv2NlbListenerSecurity' : require(__dirname + '/plugins/aws/elbv2/elbv2NlbListenerSecurity.js'), + 'elbv2DeregistrationDelay' : require(__dirname + '/plugins/aws/elbv2/elbv2DeregistrationDelay.js'), + 'elbv2SslTermination' : require(__dirname + '/plugins/aws/elbv2/elbv2SslTermination.js'), + + 'elasticacheDefaultPorts' : require(__dirname + '/plugins/aws/elasticache/elasticacheDefaultPorts.js'), + + 'emrClusterLogging' : require(__dirname + '/plugins/aws/emr/emrClusterLogging.js'), + 'emrClusterInVPC' : require(__dirname + '/plugins/aws/emr/emrClusterInVPC.js'), + 'emrEncryptionInTransit' : require(__dirname + '/plugins/aws/emr/emrEncryptionInTransit.js'), + 'emrEncryptionAtRest' : require(__dirname + '/plugins/aws/emr/emrEncryptionAtRest.js'), + 'emrDesiredInstanceType' : require(__dirname + '/plugins/aws/emr/emrDesiredInstanceType.js'), + 'emrInstanceCount' : require(__dirname + '/plugins/aws/emr/emrInstanceCount.js'), + + 'esAccessFromIps' : require(__dirname + '/plugins/aws/es/esAccessFromIps.js'), + 'esPublicEndpoint' : require(__dirname + '/plugins/aws/es/esPublicEndpoint.js'), + 'esRequireIAMAuth' : require(__dirname + '/plugins/aws/es/esRequireIAMAuth.js'), + 'esEncryptedDomain' : require(__dirname + '/plugins/aws/es/esEncryptedDomain.js'), + 'esExposedDomain' : require(__dirname + '/plugins/aws/es/esExposedDomain.js'), + 'esNodeToNodeEncryption' : require(__dirname + '/plugins/aws/es/esNodeToNodeEncryption.js'), + 'esLoggingEnabled' : require(__dirname + '/plugins/aws/es/esLoggingEnabled.js'), + 'esUpgradeAvailable' : require(__dirname + '/plugins/aws/es/esUpgradeAvailable.js'), + 'esHttpsOnly' : require(__dirname + '/plugins/aws/es/esHttpsOnly.js'), + 'esCrossAccountAccess' : require(__dirname + '/plugins/aws/es/esCrossAccountAccess.js'), + 'esClusterStatus' : require(__dirname + '/plugins/aws/es/esClusterStatus.js'), + 'esDedicatedMasterEnabled' : require(__dirname + '/plugins/aws/es/esDedicatedMasterEnabled.js'), + 'esDesiredInstanceTypes' : require(__dirname + '/plugins/aws/es/esDesiredInstanceTypes.js'), + 'esTlsVersion' : require(__dirname + '/plugins/aws/es/esTlsVersion.js'), + 'esDomainEncryptionEnabled' : require(__dirname + '/plugins/aws/es/esDomainEncryptionEnabled.js'), + 'vaultPublicAccess' : require(__dirname + '/plugins/aws/s3glacier/vaultPublicAccess.js'), + 'firehoseEncrypted' : require(__dirname + '/plugins/aws/firehose/firehoseEncrypted.js'), + 'deliveryStreamEncrypted' : require(__dirname + '/plugins/aws/firehose/deliveryStreamEncrypted.js'), + + 'eventBusCrossAccountAccess' : require(__dirname + '/plugins/aws/eventbridge/eventBusCrossAccountAccess.js'), + 'eventBusPublicAccess' : require(__dirname + '/plugins/aws/eventbridge/eventBusPublicAccess.js'), + 'eventsInUse' : require(__dirname + '/plugins/aws/eventbridge/eventsInUse.js'), + + 'glueCloudwatchLogsEncrypted' : require(__dirname + '/plugins/aws/glue/glueCloudwatchLogsEncrypted.js'), + 'glueS3EncryptionEnabled' : require(__dirname + '/plugins/aws/glue/glueS3EncryptionEnabled.js'), + 'dataCatalogCmkEncrypted' : require(__dirname + '/plugins/aws/glue/dataCatalogCmkEncrypted.js'), + 'bookmarkEncryptionEnabled' : require(__dirname + '/plugins/aws/glue/bookmarkEncryptionEnabled.js'), + 'dataCatalogEncryptionEnabled' : require(__dirname + '/plugins/aws/glue/dataCatalogEncryptionEnabled.js'), + + 'accessKeysExtra' : require(__dirname + '/plugins/aws/iam/accessKeysExtra.js'), + 'accessKeysLastUsed' : require(__dirname + '/plugins/aws/iam/accessKeysLastUsed.js'), + 'accessKeysRotated' : require(__dirname + '/plugins/aws/iam/accessKeysRotated.js'), + 'certificateExpiry' : require(__dirname + '/plugins/aws/iam/certificateExpiry.js'), + 'crossAccountMfaExtIdAccess' : require(__dirname + '/plugins/aws/iam/crossAccountMfaExtIdAccess.js'), + 'emptyGroups' : require(__dirname + '/plugins/aws/iam/emptyGroups.js'), + 'groupInlinePolicies' : require(__dirname + '/plugins/aws/iam/groupInlinePolicies.js'), + 'iamMasterManagerRoles' : require(__dirname + '/plugins/aws/iam/iamMasterManagerRoles.js'), + 'iamUserAdmins' : require(__dirname + '/plugins/aws/iam/iamUserAdmins.js'), + 'iamUserNameRegex' : require(__dirname + '/plugins/aws/iam/iamUserNameRegex.js'), + 'iamUserUnauthorizedToEdit' : require(__dirname + '/plugins/aws/iam/iamUserUnauthorizedToEdit'), + 'iamRolePolicies' : require(__dirname + '/plugins/aws/iam/iamRolePolicies.js'), + 'iamRoleLastUsed' : require(__dirname + '/plugins/aws/iam/iamRoleLastUsed.js'), + 'maxPasswordAge' : require(__dirname + '/plugins/aws/iam/maxPasswordAge.js'), + 'minPasswordLength' : require(__dirname + '/plugins/aws/iam/minPasswordLength.js'), + 'noUserIamPolicies' : require(__dirname + '/plugins/aws/iam/noUserIamPolicies.js'), + 'passwordExpiration' : require(__dirname + '/plugins/aws/iam/passwordExpiration.js'), + 'passwordRequiresLowercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresLowercase.js'), + 'passwordRequiresNumbers' : require(__dirname + '/plugins/aws/iam/passwordRequiresNumbers.js'), + 'passwordRequiresSymbols' : require(__dirname + '/plugins/aws/iam/passwordRequiresSymbols.js'), + 'passwordRequiresUppercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresUppercase.js'), + 'passwordReusePrevention' : require(__dirname + '/plugins/aws/iam/passwordReusePrevention.js'), + 'rootAccessKeys' : require(__dirname + '/plugins/aws/iam/rootAccessKeys.js'), + 'rootSigningCertificate' : require(__dirname + '/plugins/aws/iam/rootSigningCertificate.js'), + 'rootAccountInUse' : require(__dirname + '/plugins/aws/iam/rootAccountInUse.js'), + 'rootHardwareMfa' : require(__dirname + '/plugins/aws/iam/rootHardwareMfa.js'), + 'rootMfaEnabled' : require(__dirname + '/plugins/aws/iam/rootMfaEnabled.js'), + 'sshKeysRotated' : require(__dirname + '/plugins/aws/iam/sshKeysRotated.js'), + 'trustedCrossAccountRoles' : require(__dirname + '/plugins/aws/iam/trustedCrossAccountRoles.js'), + 'usersMfaEnabled' : require(__dirname + '/plugins/aws/iam/usersMfaEnabled.js'), + 'usersPasswordAndKeys' : require(__dirname + '/plugins/aws/iam/usersPasswordAndKeys.js'), + 'usersPasswordLastUsed' : require(__dirname + '/plugins/aws/iam/usersPasswordLastUsed.js'), + 'canaryKeysUsed' : require(__dirname + '/plugins/aws/iam/canaryKeysUsed.js'), + 'iamPoliciesPresent' : require(__dirname + '/plugins/aws/iam/iamPoliciesPresent.js'), + 'iamDbAuthenticationEnabled' : require(__dirname + '/plugins/aws/rds/iamDbAuthenticationEnabled.js'), + 'iamSupportPolicy' : require(__dirname + '/plugins/aws/iam/iamSupportPolicy.js'), + 'iamUserPresent' : require(__dirname + '/plugins/aws/iam/iamUserPresent.js'), + + 'iamUserInUse' : require(__dirname + '/plugins/aws/iam/iamUserInUse.js'), + 'kinesisEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisEncrypted.js'), + 'kinesisDataStreamsEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisDataStreamsEncrypted.js'), + 'videostreamDataEncrypted' : require(__dirname + '/plugins/aws/kinesisvideo/videostreamDataEncrypted.js'), + + 'kmsKeyRotation' : require(__dirname + '/plugins/aws/kms/kmsKeyRotation.js'), + 'kmsScheduledDeletion' : require(__dirname + '/plugins/aws/kms/kmsScheduledDeletion.js'), + 'kmsKeyPolicy' : require(__dirname + '/plugins/aws/kms/kmsKeyPolicy.js'), + 'kmsDefaultKeyUsage' : require(__dirname + '/plugins/aws/kms/kmsDefaultKeyUsage.js'), + 'kmsAppTierCmk' : require(__dirname + '/plugins/aws/kms/kmsAppTierCmk.js'), + 'kmsGrantLeastPrivilege' : require(__dirname + '/plugins/aws/kms/kmsGrantLeastPrivilege.js'), + 'kmsDuplicateGrants' : require(__dirname + '/plugins/aws/kms/kmsDuplicateGrants.js'), + + 'rdsAutomatedBackups' : require(__dirname + '/plugins/aws/rds/rdsAutomatedBackups.js'), + 'rdsEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsEncryptionEnabled.js'), + 'rdsCmkEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsCmkEncryptionEnabled.js'), + 'rdsLoggingEnabled' : require(__dirname + '/plugins/aws/rds/rdsLoggingEnabled.js'), + 'rdsPubliclyAccessible' : require(__dirname + '/plugins/aws/rds/rdsPubliclyAccessible.js'), + 'rdsRestorable' : require(__dirname + '/plugins/aws/rds/rdsRestorable.js'), + 'rdsMultiAz' : require(__dirname + '/plugins/aws/rds/rdsMultiAz.js'), + 'rdsSnapshotEncryption' : require(__dirname + '/plugins/aws/rds/rdsSnapshotEncryption.js'), + 'rdsMinorVersionUpgrade' : require(__dirname + '/plugins/aws/rds/rdsMinorVersionUpgrade.js'), + 'sqlServerTLSVersion' : require(__dirname + '/plugins/aws/rds/sqlServerTLSVersion'), + 'rdsTransportEncryption' : require(__dirname + '/plugins/aws/rds/rdsTransportEncryption'), + 'rdsDeletionProtectionEnabled' : require(__dirname + '/plugins/aws/rds/rdsDeletionProtectionEnabled.js'), + + 'redisClusterEncryptionInTransit': require(__dirname + '/plugins/aws/elasticache/redisClusterEncryptionInTransit.js'), + 'elasticacheClusterInVpc' : require(__dirname + '/plugins/aws/elasticache/elasticacheClusterInVpc.js'), + 'elasticacheInstanceGeneration' : require(__dirname + '/plugins/aws/elasticache/elasticacheInstanceGeneration.js'), + 'redisEngineVersions' : require(__dirname + '/plugins/aws/elasticache/redisEngineVersions.js'), + 'elasticacheNodesCount' : require(__dirname + '/plugins/aws/elasticache/elasticacheNodesCount.js'), + 'elasticacheRedisMultiAZ' : require(__dirname + '/plugins/aws/elasticache/elasticacheRedisMultiAZ.js'), + 'idleElastiCacheNode' : require(__dirname + '/plugins/aws/elasticache/idleElastiCacheNode.js'), + 'elasticaheDesiredNodeType' : require(__dirname + '/plugins/aws/elasticache/elasticaheDesiredNodeType.js'), + + 'domainAutoRenew' : require(__dirname + '/plugins/aws/route53/domainAutoRenew.js'), + 'domainExpiry' : require(__dirname + '/plugins/aws/route53/domainExpiry.js'), + 'domainTransferLock' : require(__dirname + '/plugins/aws/route53/domainTransferLock.js'), + 'danglingDnsRecords' : require(__dirname + '/plugins/aws/route53/danglingDnsRecords.js'), + 'privacyProtection' : require(__dirname + '/plugins/aws/route53/privacyProtection.js'), + 'senderPolicyFwInUse' : require(__dirname + '/plugins/aws/route53/senderPolicyFwInUse.js'), + 'senderPolicyFwRecordPresent' : require(__dirname + '/plugins/aws/route53/senderPolicyFwRecordPresent.js'), + + 'bucketEncryptionInTransit' : require(__dirname + '/plugins/aws/s3/bucketEncryptionInTransit.js'), + 'bucketAllUsersPolicy' : require(__dirname + '/plugins/aws/s3/bucketAllUsersPolicy.js'), + 'bucketAllUsersAcl' : require(__dirname + '/plugins/aws/s3/bucketAllUsersAcl.js'), + 'bucketPolicyCloudFrontOai' : require(__dirname + '/plugins/aws/s3/bucketPolicyCloudFrontOai.js'), + 'bucketVersioning' : require(__dirname + '/plugins/aws/s3/bucketVersioning.js'), + 'bucketLogging' : require(__dirname + '/plugins/aws/s3/bucketLogging.js'), + 's3Encryption' : require(__dirname + '/plugins/aws/s3/s3Encryption.js'), + 'bucketPublicAccessBlock' : require(__dirname + '/plugins/aws/s3/bucketPublicAccessBlock.js'), + 'bucketEncryption' : require(__dirname + '/plugins/aws/s3/bucketEncryption.js'), + 'bucketWebsiteEnabled' : require(__dirname + '/plugins/aws/s3/bucketWebsiteEnabled.js'), + 'bucketEnforceEncryption' : require(__dirname + '/plugins/aws/s3/bucketEnforceEncryption.js'), + 'bucketSecureTransportEnabled' : require(__dirname + '/plugins/aws/s3/bucketSecureTransportEnabled.js'), + 'bucketLifecycleConfiguration' : require(__dirname + '/plugins/aws/s3/bucketLifecycleConfiguration'), + 'bucketTransferAcceleration' : require(__dirname + '/plugins/aws/s3/bucketTransferAcceleration'), + 'bucketDnsCompliantName' : require(__dirname + '/plugins/aws/s3/bucketDnsCompliantName.js'), + 'versionedBucketsLC' : require(__dirname + '/plugins/aws/s3/versionedBucketsLC.js'), + + 'notebookDataEncrypted' : require(__dirname + '/plugins/aws/sagemaker/notebookDataEncrypted.js'), + 'notebookDirectInternetAccess' : require(__dirname + '/plugins/aws/sagemaker/notebookDirectInternetAccess.js'), + 'notebookInstanceInVpc' : require(__dirname + '/plugins/aws/sagemaker/notebookInstanceInVpc.js'), + + 'dkimEnabled' : require(__dirname + '/plugins/aws/ses/dkimEnabled.js'), + 'emailMessagesEncrypted' : require(__dirname + '/plugins/aws/ses/emailMessagesEncrypted.js'), + + 'topicEncrypted' : require(__dirname + '/plugins/aws/sns/topicEncrypted.js'), + 'topicPolicies' : require(__dirname + '/plugins/aws/sns/topicPolicies.js'), + 'topicCmkEncrypted' : require(__dirname + '/plugins/aws/sns/topicCmkEncrypted.js'), + 'snsCrossAccount' : require(__dirname + '/plugins/aws/sns/snsCrossAccount.js'), + 'snsValidSubscribers' : require(__dirname + '/plugins/aws/sns/snsValidSubscribers.js'), + + 'sqsCrossAccount' : require(__dirname + '/plugins/aws/sqs/sqsCrossAccount.js'), + 'sqsDeadLetterQueue' : require(__dirname + '/plugins/aws/sqs/sqsDeadLetterQueue.js'), + 'sqsEncrypted' : require(__dirname + '/plugins/aws/sqs/sqsEncrypted.js'), + 'sqsPublicAccess' : require(__dirname + '/plugins/aws/sqs/sqsPublicAccess.js'), + 'queueUnprocessedMessages' : require(__dirname + '/plugins/aws/sqs/queueUnprocessedMessages.js'), + 'sqsEncryptionEnabled' : require(__dirname + '/plugins/aws/sqs/sqsEncryptionEnabled.js'), + + 'ssmEncryptedParameters' : require(__dirname + '/plugins/aws/ssm/ssmEncryptedParameters.js'), + 'ssmActiveOnAllInstances' : require(__dirname + '/plugins/aws/ssm/ssmActiveOnAllInstances.js'), + 'ssmAgentLatestVersion' : require(__dirname + '/plugins/aws/ssm/ssmAgentLatestVersion.js'), + 'ssmAgentAutoUpdateEnabled' : require(__dirname + '/plugins/aws/ssm/ssmAgentAutoUpdateEnabled'), + 'ssmDocumentPublicAccess' : require(__dirname + '/plugins/aws/ssm/ssmDocumentPublicAccess'), + 'ssmManagedInstances' : require(__dirname + '/plugins/aws/ssm/ssmManagedInstances'), + 'ssmSessionDuration' : require(__dirname + '/plugins/aws/ssm/ssmSessionDuration'), + + 'ledgerEncrypted' : require(__dirname + '/plugins/aws/qldb/ledgerEncrypted'), + + 'lambdaAdminPrivileges' : require(__dirname + '/plugins/aws/lambda/lambdaAdminPrivileges.js'), + 'envVarsClientSideEncryption' : require(__dirname + '/plugins/aws/lambda/envVarsClientSideEncryption.js'), + 'lambdaOldRuntimes' : require(__dirname + '/plugins/aws/lambda/lambdaOldRuntimes.js'), + 'lambdaVpcConfig' : require(__dirname + '/plugins/aws/lambda/lambdaVpcConfig.js'), + 'lambdaPublicAccess' : require(__dirname + '/plugins/aws/lambda/lambdaPublicAccess.js'), + 'lambdaLogGroups' : require(__dirname + '/plugins/aws/lambda/lambdaLogGroups.js'), + 'lambdaTracingEnabled' : require(__dirname + '/plugins/aws/lambda/lambdaTracingEnabled.js'), + + 'webServerPublicAccess' : require(__dirname + '/plugins/aws/mwaa/webServerPublicAccess.js'), + 'environmentAdminPrivileges' : require(__dirname + '/plugins/aws/mwaa/environmentAdminPrivileges.js'), + 'environmentDataEncrypted' : require(__dirname + '/plugins/aws/mwaa/environmentDataEncrypted.js'), + + 'neptuneDBInstanceEncrypted' : require(__dirname + '/plugins/aws/neptune/neptuneDBInstanceEncrypted.js'), + + 'monitoringMetrics' : require(__dirname + '/plugins/aws/cloudwatchlogs/monitoringMetrics.js'), + + 'customerProfilesDomainEncrypted' : require(__dirname + '/plugins/aws/connect/customerProfilesDomainEncrypted.js'), + 'wisdomDomainEncrypted' : require(__dirname + '/plugins/aws/connect/wisdomDomainEncrypted.js'), + 'voiceIdDomainEncrypted' : require(__dirname + '/plugins/aws/connect/voiceIdDomainEncrypted.js'), + + 'logRetentionPeriod' : require(__dirname + '/plugins/aws/cloudwatchlogs/logRetentionPeriod.js'), + 'logGroupsEncrypted' : require(__dirname + '/plugins/aws/cloudwatchlogs/logGroupsEncrypted.js'), + + 'vpcFlowLogsMetricAlarm' : require(__dirname + '/plugins/aws/cloudwatch/vpcFlowLogsMetricAlarm.js'), + + 'timestreamDatabaseEncrypted' : require(__dirname + '/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js'), + + 'mqAutoMinorVersionUpgrade' : require(__dirname + '/plugins/aws/mq/mqAutoMinorVersionUpgrade.js'), + 'mqLogExports' : require(__dirname + '/plugins/aws/mq/mqLogExports.js'), + 'mqDeploymentMode' : require(__dirname + '/plugins/aws/mq/mqDeploymentMode.js'), + 'mqDesiredInstanceType' : require(__dirname + '/plugins/aws/mq/mqDesiredInstanceType.js'), + 'mqBrokerEncrypted' : require(__dirname + '/plugins/aws/mq/mqBrokerEncrypted.js'), - // 'memorydbClusterEncrypted' : require(__dirname + '/plugins/aws/memorydb/memorydbClusterEncrypted.js'), + 'memorydbClusterEncrypted' : require(__dirname + '/plugins/aws/memorydb/memorydbClusterEncrypted.js'), - // 'mskClusterEncryptionAtRest' : require(__dirname + '/plugins/aws/msk/mskClusterEncryptionAtRest.js'), - // 'mskClusterEncryptionInTransit' : require(__dirname + '/plugins/aws/msk/mskClusterEncryptionInTransit.js'), + 'mskClusterEncryptionAtRest' : require(__dirname + '/plugins/aws/msk/mskClusterEncryptionAtRest.js'), + 'mskClusterEncryptionInTransit' : require(__dirname + '/plugins/aws/msk/mskClusterEncryptionInTransit.js'), - // 'auditLoggingEnabled' : require(__dirname + '/plugins/aws/redshift/auditLoggingEnabled.js'), - // 'redshiftClusterCmkEncrypted' : require(__dirname + '/plugins/aws/redshift/redshiftClusterCmkEncrypted.js'), - // 'redshiftEncryptionEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftEncryptionEnabled.js'), - // 'redshiftPubliclyAccessible' : require(__dirname + '/plugins/aws/redshift/redshiftPubliclyAccessible.js'), - // 'redshiftAllowVersionUpgrade' : require(__dirname + '/plugins/aws/redshift/redshiftAllowVersionUpgrade.js'), - // 'redshiftSSLEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftSSLEnabled.js'), - // 'redshiftClusterInVpc' : require(__dirname + '/plugins/aws/redshift/redshiftClusterInVpc.js'), - // 'redshiftClusterDefaultPort' : require(__dirname + '/plugins/aws/redshift/redshiftClusterDefaultPort.js'), - // 'redshiftClusterMasterUsername' : require(__dirname + '/plugins/aws/redshift/redshiftClusterMasterUsername.js'), - // 'snapshotRetentionPeriod' : require(__dirname + '/plugins/aws/redshift/snapshotRetentionPeriod.js'), - // 'userActivityLoggingEnabled' : require(__dirname + '/plugins/aws/redshift/userActivityLoggingEnabled.js'), - // 'redshiftNodesCount' : require(__dirname + '/plugins/aws/redshift/redshiftNodesCount.js'), - // 'redshiftUnusedReservedNodes' : require(__dirname + '/plugins/aws/redshift/redshiftUnusedReservedNodes.js'), - // 'redshiftDesiredNodeType' : require(__dirname + '/plugins/aws/redshift/redshiftDesiredNodeType.js'), + 'auditLoggingEnabled' : require(__dirname + '/plugins/aws/redshift/auditLoggingEnabled.js'), + 'redshiftClusterCmkEncrypted' : require(__dirname + '/plugins/aws/redshift/redshiftClusterCmkEncrypted.js'), + 'redshiftEncryptionEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftEncryptionEnabled.js'), + 'redshiftPubliclyAccessible' : require(__dirname + '/plugins/aws/redshift/redshiftPubliclyAccessible.js'), + 'redshiftAllowVersionUpgrade' : require(__dirname + '/plugins/aws/redshift/redshiftAllowVersionUpgrade.js'), + 'redshiftSSLEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftSSLEnabled.js'), + 'redshiftClusterInVpc' : require(__dirname + '/plugins/aws/redshift/redshiftClusterInVpc.js'), + 'redshiftClusterDefaultPort' : require(__dirname + '/plugins/aws/redshift/redshiftClusterDefaultPort.js'), + 'redshiftClusterMasterUsername' : require(__dirname + '/plugins/aws/redshift/redshiftClusterMasterUsername.js'), + 'snapshotRetentionPeriod' : require(__dirname + '/plugins/aws/redshift/snapshotRetentionPeriod.js'), + 'userActivityLoggingEnabled' : require(__dirname + '/plugins/aws/redshift/userActivityLoggingEnabled.js'), + 'redshiftNodesCount' : require(__dirname + '/plugins/aws/redshift/redshiftNodesCount.js'), + 'redshiftUnusedReservedNodes' : require(__dirname + '/plugins/aws/redshift/redshiftUnusedReservedNodes.js'), + 'redshiftDesiredNodeType' : require(__dirname + '/plugins/aws/redshift/redshiftDesiredNodeType.js'), - // 'redisClusterEncryptionAtRest' : require(__dirname + '/plugins/aws/elasticache/redisClusterEncryptionAtRest.js'), - // 'reservedNodePaymentPending.js' : require(__dirname + '/plugins/aws/elasticache/reservedNodePaymentPending.js'), - // 'unusedElastiCacheReservedNode' : require(__dirname + '/plugins/aws/elasticache/unusedElastiCacheReservedNode.js'), - // 'reservedNodePaymentFailed' : require(__dirname + '/plugins/aws/elasticache/reservedNodePaymentFailed.js'), - // 'reservedNodeLeaseExpiration' : require(__dirname + '/plugins/aws/elasticache/reservedNodeLeaseExpiration.js'), + 'redisClusterEncryptionAtRest' : require(__dirname + '/plugins/aws/elasticache/redisClusterEncryptionAtRest.js'), + 'reservedNodePaymentPending.js' : require(__dirname + '/plugins/aws/elasticache/reservedNodePaymentPending.js'), + 'unusedElastiCacheReservedNode' : require(__dirname + '/plugins/aws/elasticache/unusedElastiCacheReservedNode.js'), + 'reservedNodePaymentFailed' : require(__dirname + '/plugins/aws/elasticache/reservedNodePaymentFailed.js'), + 'reservedNodeLeaseExpiration' : require(__dirname + '/plugins/aws/elasticache/reservedNodeLeaseExpiration.js'), - // 'transferLoggingEnabled' : require(__dirname + '/plugins/aws/transfer/transferLoggingEnabled.js'), - // 'transferPrivateLinkInUse' : require(__dirname + '/plugins/aws/transfer/transferPrivateLinkInUse.js'), + 'transferLoggingEnabled' : require(__dirname + '/plugins/aws/transfer/transferLoggingEnabled.js'), + 'transferPrivateLinkInUse' : require(__dirname + '/plugins/aws/transfer/transferPrivateLinkInUse.js'), - // 'serviceEncrypted' : require(__dirname + '/plugins/aws/apprunner/serviceEncrypted.js'), + 'serviceEncrypted' : require(__dirname + '/plugins/aws/apprunner/serviceEncrypted.js'), - // 'secretRotationEnabled' : require(__dirname + '/plugins/aws/secretsmanager/secretRotationEnabled.js'), - // 'secretsManagerEncrypted' : require(__dirname + '/plugins/aws/secretsmanager/secretsManagerEncrypted.js'), - // 'secretsManagerInUse' : require(__dirname + '/plugins/aws/secretsmanager/secretsManagerInUse.js'), + 'secretRotationEnabled' : require(__dirname + '/plugins/aws/secretsmanager/secretRotationEnabled.js'), + 'secretsManagerEncrypted' : require(__dirname + '/plugins/aws/secretsmanager/secretsManagerEncrypted.js'), + 'secretsManagerInUse' : require(__dirname + '/plugins/aws/secretsmanager/secretsManagerInUse.js'), - // 'finspaceEnvironmentEncrypted' : require(__dirname + '/plugins/aws/finspace/finspaceEnvironmentEncrypted.js'), + 'finspaceEnvironmentEncrypted' : require(__dirname + '/plugins/aws/finspace/finspaceEnvironmentEncrypted.js'), - // 'shieldAdvancedEnabled' : require(__dirname + '/plugins/aws/shield/shieldAdvancedEnabled.js'), - // 'shieldEmergencyContacts' : require(__dirname + '/plugins/aws/shield/shieldEmergencyContacts.js'), - // 'shieldProtections' : require(__dirname + '/plugins/aws/shield/shieldProtections.js'), + 'shieldAdvancedEnabled' : require(__dirname + '/plugins/aws/shield/shieldAdvancedEnabled.js'), + 'shieldEmergencyContacts' : require(__dirname + '/plugins/aws/shield/shieldEmergencyContacts.js'), + 'shieldProtections' : require(__dirname + '/plugins/aws/shield/shieldProtections.js'), - // 'enableAllFeatures' : require(__dirname + '/plugins/aws/organizations/enableAllFeatures.js'), - // 'organizationInvite' : require(__dirname + '/plugins/aws/organizations/organizationInvite.js'), + 'enableAllFeatures' : require(__dirname + '/plugins/aws/organizations/enableAllFeatures.js'), + 'organizationInvite' : require(__dirname + '/plugins/aws/organizations/organizationInvite.js'), - // 'guardDutyEnabled' : require(__dirname + '/plugins/aws/guardduty/guarddutyEnabled.js'), - // 'guardDutyMaster' : require(__dirname + '/plugins/aws/guardduty/guarddutyMaster.js'), - // 'noActiveFindings' : require(__dirname + '/plugins/aws/guardduty/noActiveFindings'), - // 'exportedFindingsEncrypted' : require(__dirname + '/plugins/aws/guardduty/exportedFindingsEncrypted.js'), + 'guardDutyEnabled' : require(__dirname + '/plugins/aws/guardduty/guarddutyEnabled.js'), + 'guardDutyMaster' : require(__dirname + '/plugins/aws/guardduty/guarddutyMaster.js'), + 'noActiveFindings' : require(__dirname + '/plugins/aws/guardduty/noActiveFindings'), + 'exportedFindingsEncrypted' : require(__dirname + '/plugins/aws/guardduty/exportedFindingsEncrypted.js'), - // 'workspacesVolumeEncryption' : require(__dirname + '/plugins/aws/workspaces/workspacesVolumeEncryption.js'), - // 'workspacesIpAccessControl' : require(__dirname + '/plugins/aws/workspaces/workspacesIpAccessControl.js'), - // 'unusedWorkspaces' : require(__dirname + '/plugins/aws/workspaces/unusedWorkspaces.js'), - // 'workspacesInstanceCount' : require(__dirname + '/plugins/aws/workspaces/workspacesInstanceCount.js'), - // 'workspacesDesiredBundleType' : require(__dirname + '/plugins/aws/workspaces/workspacesDesiredBundleType.js'), + 'workspacesVolumeEncryption' : require(__dirname + '/plugins/aws/workspaces/workspacesVolumeEncryption.js'), + 'workspacesIpAccessControl' : require(__dirname + '/plugins/aws/workspaces/workspacesIpAccessControl.js'), + 'unusedWorkspaces' : require(__dirname + '/plugins/aws/workspaces/unusedWorkspaces.js'), + 'workspacesInstanceCount' : require(__dirname + '/plugins/aws/workspaces/workspacesInstanceCount.js'), + 'workspacesDesiredBundleType' : require(__dirname + '/plugins/aws/workspaces/workspacesDesiredBundleType.js'), - // 'xrayEncryptionEnabled' : require(__dirname + '/plugins/aws/xray/xrayEncryptionEnabled.js'), + 'xrayEncryptionEnabled' : require(__dirname + '/plugins/aws/xray/xrayEncryptionEnabled.js'), - // 'codebuildValidSourceProviders' : require(__dirname + '/plugins/aws/codebuild/codebuildValidSourceProviders.js'), - // 'projectArtifactsEncrypted' : require(__dirname + '/plugins/aws/codebuild/projectArtifactsEncrypted.js'), + 'codebuildValidSourceProviders' : require(__dirname + '/plugins/aws/codebuild/codebuildValidSourceProviders.js'), + 'projectArtifactsEncrypted' : require(__dirname + '/plugins/aws/codebuild/projectArtifactsEncrypted.js'), - // 'codestarValidRepoProviders' : require(__dirname + '/plugins/aws/codestar/codestarValidRepoProviders.js'), + 'codestarValidRepoProviders' : require(__dirname + '/plugins/aws/codestar/codestarValidRepoProviders.js'), - // 'pipelineArtifactsEncrypted' : require(__dirname + '/plugins/aws/codepipeline/pipelineArtifactsEncrypted.js'), + 'pipelineArtifactsEncrypted' : require(__dirname + '/plugins/aws/codepipeline/pipelineArtifactsEncrypted.js'), - // 'dataStoreEncrypted' : require(__dirname + '/plugins/aws/healthlake/dataStoreEncrypted.js'), + 'dataStoreEncrypted' : require(__dirname + '/plugins/aws/healthlake/dataStoreEncrypted.js'), - // 'codeartifactDomainEncrypted' : require(__dirname + '/plugins/aws/codeartifact/codeartifactDomainEncrypted.js'), + 'codeartifactDomainEncrypted' : require(__dirname + '/plugins/aws/codeartifact/codeartifactDomainEncrypted.js'), - // 'auditmanagerDataEncrypted' : require(__dirname + '/plugins/aws/auditmanager/auditmanagerDataEncrypted.js'), + 'auditmanagerDataEncrypted' : require(__dirname + '/plugins/aws/auditmanager/auditmanagerDataEncrypted.js'), - // 'flowEncrypted' : require(__dirname + '/plugins/aws/appflow/flowEncrypted.js'), + 'flowEncrypted' : require(__dirname + '/plugins/aws/appflow/flowEncrypted.js'), - // 'pipelineDataEncrypted' : require(__dirname + '/plugins/aws/elastictranscoder/pipelineDataEncrypted.js'), - // 'jobOutputsEncrypted' : require(__dirname + '/plugins/aws/elastictranscoder/jobOutputsEncrypted.js'), + 'pipelineDataEncrypted' : require(__dirname + '/plugins/aws/elastictranscoder/pipelineDataEncrypted.js'), + 'jobOutputsEncrypted' : require(__dirname + '/plugins/aws/elastictranscoder/jobOutputsEncrypted.js'), - // 'translateJobOutputEncrypted' : require(__dirname + '/plugins/aws/translate/translateJobOutputEncrypted.js'), + 'translateJobOutputEncrypted' : require(__dirname + '/plugins/aws/translate/translateJobOutputEncrypted.js'), - // 'databrewJobOutputEncrypted' : require(__dirname + '/plugins/aws/gluedatabrew/databrewJobOutputEncrypted.js'), + 'databrewJobOutputEncrypted' : require(__dirname + '/plugins/aws/gluedatabrew/databrewJobOutputEncrypted.js'), - // 'networkMemberDataEncrypted' : require(__dirname + '/plugins/aws/managedblockchain/networkMemberDataEncrypted.js'), + 'networkMemberDataEncrypted' : require(__dirname + '/plugins/aws/managedblockchain/networkMemberDataEncrypted.js'), - // 'docdbClusterEncrypted' : require(__dirname + '/plugins/aws/documentDB/docdbClusterEncrypted.js'), - // 'docdbClusterBackupRetention' : require(__dirname + '/plugins/aws/documentDB/docdbClusterBackupRetention.js'), + 'docdbClusterEncrypted' : require(__dirname + '/plugins/aws/documentDB/docdbClusterEncrypted.js'), + 'docdbClusterBackupRetention' : require(__dirname + '/plugins/aws/documentDB/docdbClusterBackupRetention.js'), - // 'instanceMediaStreamsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceMediaStreamsEncrypted.js'), - // 'instanceTranscriptsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceTranscriptsEncrypted.js'), - // 'instanceReportsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceReportsEncrypted.js'), - // 'instanceCallRecordingEncrypted': require(__dirname + '/plugins/aws/connect/instanceCallRecordingEncrypted.js'), - // 'instanceAttachmentsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceAttachmentsEncrypted.js'), + 'instanceMediaStreamsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceMediaStreamsEncrypted.js'), + 'instanceTranscriptsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceTranscriptsEncrypted.js'), + 'instanceReportsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceReportsEncrypted.js'), + 'instanceCallRecordingEncrypted': require(__dirname + '/plugins/aws/connect/instanceCallRecordingEncrypted.js'), + 'instanceAttachmentsEncrypted' : require(__dirname + '/plugins/aws/connect/instanceAttachmentsEncrypted.js'), - // 'backupVaultEncrypted' : require(__dirname + '/plugins/aws/backup/backupVaultEncrypted.js'), - // 'backupResourceProtection' : require(__dirname + '/plugins/aws/backup/backupResourceProtection.js'), - // 'backupInUseForRDSSnapshots' : require(__dirname + '/plugins/aws/backup/backupInUseForRDSSnapshots.js'), - // 'backupNotificationEnabled' : require(__dirname + '/plugins/aws/backup/backupNotificationEnabled.js'), - // 'backupDeletionProtection' : require(__dirname + '/plugins/aws/backup/backupDeletionProtection.js'), - // 'compliantLifecyleConfigured' : require(__dirname + '/plugins/aws/backup/compliantLifecyleConfigured.js'), + 'backupVaultEncrypted' : require(__dirname + '/plugins/aws/backup/backupVaultEncrypted.js'), + 'backupResourceProtection' : require(__dirname + '/plugins/aws/backup/backupResourceProtection.js'), + 'backupInUseForRDSSnapshots' : require(__dirname + '/plugins/aws/backup/backupInUseForRDSSnapshots.js'), + 'backupNotificationEnabled' : require(__dirname + '/plugins/aws/backup/backupNotificationEnabled.js'), + 'backupDeletionProtection' : require(__dirname + '/plugins/aws/backup/backupDeletionProtection.js'), + 'compliantLifecyleConfigured' : require(__dirname + '/plugins/aws/backup/compliantLifecyleConfigured.js'), - // 'equipmentdatasetEncrypted' : require(__dirname + '/plugins/aws/lookout/equipmentdatasetEncrypted.js'), + 'equipmentdatasetEncrypted' : require(__dirname + '/plugins/aws/lookout/equipmentdatasetEncrypted.js'), - // 'iotsitewiseDataEncrypted' : require(__dirname + '/plugins/aws/iotsitewise/iotsitewiseDataEncrypted.js'), + 'iotsitewiseDataEncrypted' : require(__dirname + '/plugins/aws/iotsitewise/iotsitewiseDataEncrypted.js'), - // 'trackerDataEncrypted' : require(__dirname + '/plugins/aws/location/trackerDataEncrypted.js'), - // 'geoCollectionDataEncrypted' : require(__dirname + '/plugins/aws/location/geoCollectionDataEncrypted.js'), + 'trackerDataEncrypted' : require(__dirname + '/plugins/aws/location/trackerDataEncrypted.js'), + 'geoCollectionDataEncrypted' : require(__dirname + '/plugins/aws/location/geoCollectionDataEncrypted.js'), - // 'modelDataEncrypted' : require(__dirname + '/plugins/aws/lookout/modelDataEncrypted.js'), - // 'anomalyDetectorEncrypted' : require(__dirname + '/plugins/aws/lookout/anomalyDetectorEncrypted.js'), + 'modelDataEncrypted' : require(__dirname + '/plugins/aws/lookout/modelDataEncrypted.js'), + 'anomalyDetectorEncrypted' : require(__dirname + '/plugins/aws/lookout/anomalyDetectorEncrypted.js'), - // 'lexAudioLogsEncrypted' : require(__dirname + '/plugins/aws/lex/lexAudioLogsEncrypted.js'), + 'lexAudioLogsEncrypted' : require(__dirname + '/plugins/aws/lex/lexAudioLogsEncrypted.js'), - // 'forecastDatasetEncrypted' : require(__dirname + '/plugins/aws/forecast/forecastDatasetEncrypted.js'), - // 'datasetExportEncrypted' : require(__dirname + '/plugins/aws/forecast/datasetExportEncrypted.js'), + 'forecastDatasetEncrypted' : require(__dirname + '/plugins/aws/forecast/forecastDatasetEncrypted.js'), + 'datasetExportEncrypted' : require(__dirname + '/plugins/aws/forecast/datasetExportEncrypted.js'), - // 'fsxFileSystemEncrypted' : require(__dirname + '/plugins/aws/fsx/fsxFileSystemEncrypted.js'), + 'fsxFileSystemEncrypted' : require(__dirname + '/plugins/aws/fsx/fsxFileSystemEncrypted.js'), - // 'wafv2InUse' : require(__dirname + '/plugins/aws/wafv2/wafv2InUse.js'), + 'wafv2InUse' : require(__dirname + '/plugins/aws/wafv2/wafv2InUse.js'), - // 'wafInUse' : require(__dirname + '/plugins/aws/waf/wafInUse.js'), + 'wafInUse' : require(__dirname + '/plugins/aws/waf/wafInUse.js'), - // 'fraudDetectorDataEncrypted' : require(__dirname + '/plugins/aws/frauddetector/fraudDetectorDataEncrypted.js'), + 'fraudDetectorDataEncrypted' : require(__dirname + '/plugins/aws/frauddetector/fraudDetectorDataEncrypted.js'), }, azure : { 'fileServiceEncryption' : require(__dirname + '/plugins/azure/storageaccounts/fileServiceEncryption.js'), From 0d67a8badab9bbdace27d386c05fbf7c5bd3939f Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 21 Apr 2022 14:43:46 +0500 Subject: [PATCH 082/350] Added Auto Scaling Groups Optimized Plugin --- exports.js | 2 + helpers/aws/api.js | 6 + helpers/aws/regions.js | 3 +- helpers/aws/regions_china.js | 3 +- helpers/aws/regions_gov.js | 3 +- plugins/aws/computeoptimizer/asgOptimized.js | 64 ++++++++++ .../aws/computeoptimizer/asgOptimized.spec.js | 113 ++++++++++++++++++ 7 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 plugins/aws/computeoptimizer/asgOptimized.js create mode 100644 plugins/aws/computeoptimizer/asgOptimized.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..2b50748e36 100644 --- a/exports.js +++ b/exports.js @@ -61,6 +61,8 @@ module.exports = { 'volumeEncryption' : require(__dirname + '/plugins/aws/comprehend/volumeEncryption.js'), 'outputResultEncryption' : require(__dirname + '/plugins/aws/comprehend/outputResultEncryption.js'), + 'asgOptimized' : require(__dirname + '/plugins/aws/computeoptimizer/asgOptimized.js'), + 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), 'stackFailedStatus' : require(__dirname + '/plugins/aws/cloudformation/stackFailedStatus.js'), 'driftDetection' : require(__dirname + '/plugins/aws/cloudformation/driftDetection.js'), diff --git a/helpers/aws/api.js b/helpers/aws/api.js index 27d7904da9..adc6188406 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -181,6 +181,12 @@ var calls = { paginate: 'nextToken' } }, + ComputeOptimizer: { + getRecommendationSummaries : { + property: 'recommendationSummaries', + paginate: 'nextToken' + } + }, Comprehend: { listEntitiesDetectionJobs: { property: 'EntitiesDetectionJobPropertiesList', diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index 52d8f9f211..4de2d08f9f 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -193,5 +193,6 @@ module.exports = { appmesh: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1'], - frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'] + frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'], + computeoptimizer: ['us-east-1'] }; diff --git a/helpers/aws/regions_china.js b/helpers/aws/regions_china.js index 2a2b9af6de..ece0a63f17 100644 --- a/helpers/aws/regions_china.js +++ b/helpers/aws/regions_china.js @@ -116,5 +116,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + computeoptimizer: ['cn-north-1'] }; diff --git a/helpers/aws/regions_gov.js b/helpers/aws/regions_gov.js index 1eaf28407b..088c93f57b 100644 --- a/helpers/aws/regions_gov.js +++ b/helpers/aws/regions_gov.js @@ -115,5 +115,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + computeoptimizer: ['us-gov-west-1'] }; diff --git a/plugins/aws/computeoptimizer/asgOptimized.js b/plugins/aws/computeoptimizer/asgOptimized.js new file mode 100644 index 0000000000..dc8e32b3b6 --- /dev/null +++ b/plugins/aws/computeoptimizer/asgOptimized.js @@ -0,0 +1,64 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'Auto Scaling Group Optimized', + category: 'Compute Optimizer', + domain: 'Management and Governance', + description: 'Ensure that Compute Optimizer ASGs findings are in order to take the actions to optimize Amazon Auto Scaling groups that are under-performing.', + more_info: 'An Auto Scaling group is considered optimized when Compute Optimizer determines that the group is correctly provisioned to run your workload, based on the chosen instance type. For optimized Auto Scaling groups, Compute Optimizer might sometimes recommend a new generation instance type.', + link: 'https://docs.aws.amazon.com/compute-optimizer/latest/ug/view-asg-recommendations.html', + recommended_action: 'Enable Compute Optimizer Opt In options for Auto Scaling Groups recommendations', + apis: ['ComputeOptimizer:getRecommendationSummaries'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + async.each(regions.computeoptimizer, function(region, rcb){ + var getRecommendationSummaries = helpers.addSource(cache, source, + ['computeoptimizer', 'getRecommendationSummaries', region]); + + if (!getRecommendationSummaries) return rcb(); + + if (getRecommendationSummaries && getRecommendationSummaries.err && + getRecommendationSummaries.err.code === 'OptInRequiredException'){ + helpers.addResult(results, 0, + 'Compute Optimizer is not enabled', region); + return rcb(); + } + + if (getRecommendationSummaries.err || !getRecommendationSummaries.data) { + helpers.addResult(results, 3, + 'Unable to get recommendation summaries: ' + helpers.addError(getRecommendationSummaries), region); + return rcb(); + } + + if (!getRecommendationSummaries.data.length) { + helpers.addResult(results, 0, + 'Optimization for summaries is not configured', region); + return rcb(); + } + + let findings = getRecommendationSummaries.data.find(resourceType => resourceType.recommendationResourceType === 'AutoScalingGroup'); + if (findings) { + let notOptimized = findings.summaries.find(summary => summary.name && summary.name.toUpperCase() === 'NOT_OPTIMIZED'); + if (notOptimized.value){ + helpers.addResult(results, 2, + `Auto Scaling Groups are not optimized, NOT_OPTIMIZED: ${notOptimized.value}`, region); + } else { + helpers.addResult(results, 0, + 'All Auto Scaling Groups are optimized', region); + } + } else { + helpers.addResult(results, 2, + 'No Auto Scaling Group configured', region); + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; diff --git a/plugins/aws/computeoptimizer/asgOptimized.spec.js b/plugins/aws/computeoptimizer/asgOptimized.spec.js new file mode 100644 index 0000000000..961ca4ea2b --- /dev/null +++ b/plugins/aws/computeoptimizer/asgOptimized.spec.js @@ -0,0 +1,113 @@ +var expect = require('chai').expect; +var asgOptimized = require('./asgOptimized'); + +const getRecommendationSummaries = [ + { + "summaries": [ + { + "name": "OPTIMIZED", + "value": 0.0 + }, + { + "name": "NOT_OPTIMIZED", + "value": 0.0 + } + ], + "recommendationResourceType": "AutoScalingGroup", + "accountId": "000011112222", + "currentPerformanceRiskRatings": { + "high": 0, + "medium": 0, + "low": 0, + "veryLow": 0 + } + }, + { + "summaries": [ + { + "name": "OPTIMIZED", + "value": 0.0 + }, + { + "name": "NOT_OPTIMIZED", + "value": 1.0 + } + ], + "recommendationResourceType": "AutoScalingGroup", + "accountId": "000011112222", + "currentPerformanceRiskRatings": { + "high": 0, + "medium": 0, + "low": 0, + "veryLow": 0 + } + }, +]; + + +const createCache = (recommendation, recommendationErr) => { + return { + computeoptimizer: { + getRecommendationSummaries: { + 'us-east-1': { + err: recommendationErr, + data: recommendation + }, + }, + }, + }; +}; + +describe('asgOptimized', function () { + describe('run', function () { + it('should PASS if All Auto Scalling Groups are optimized', function (done) { + const cache = createCache([getRecommendationSummaries[0]]); + asgOptimized.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('All Auto Scaling Groups are optimized'); + done(); + }); + }); + + it('should FAIL if Auto Scalling Groups are not optimized', function (done) { + const cache = createCache([getRecommendationSummaries[1]]); + asgOptimized.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('Auto Scaling Groups are not optimized'); + done(); + }); + }); + + it('should PASS if Optimization for summaries is not configured', function (done) { + const cache = createCache([]); + asgOptimized.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('Optimization for summaries is not configured'); + done(); + }); + }); + + it('should UNKNOWN if Unable to get recommendation summaries', function (done) { + const cache = createCache(null, { message: "Unable to get recommendation summaries" }); + asgOptimized.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 recommendation summaries'); + done(); + }); + }); + + it('should not return anything if get recommendation summaries status response is not found', () => { + asgOptimized.run({}, {}, (err, results) => { + expect(results.length).to.equal(0); + }) + }); + }); +}); \ No newline at end of file From ff18ecfd5621eba1aebbf504c6880b9e61d65797 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 21 Apr 2022 16:52:49 +0500 Subject: [PATCH 083/350] Added Lambda Function Findings Optimized Plugin --- exports.js | 2 + helpers/aws/api.js | 6 + helpers/aws/regions.js | 3 +- helpers/aws/regions_china.js | 3 +- helpers/aws/regions_gov.js | 3 +- .../lambdaFunctionsOptimized.js | 64 +++++++++ .../lambdaFunctionsOptimized.spec.js | 133 ++++++++++++++++++ 7 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 plugins/aws/computeoptimizer/lambdaFunctionsOptimized.js create mode 100644 plugins/aws/computeoptimizer/lambdaFunctionsOptimized.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..ad36d737ca 100644 --- a/exports.js +++ b/exports.js @@ -84,6 +84,8 @@ module.exports = { 'globalLoggingDuplicated' : require(__dirname + '/plugins/aws/cloudtrail/globalLoggingDuplicated.js'), 'cloudtrailNotificationsEnabled': require(__dirname + '/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js'), + 'lambdaFunctionsOptimized' : require(__dirname + '/plugins/aws/computeoptimizer/lambdaFunctionsOptimized.js'), + 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), 'configComplaintRules' : require(__dirname + '/plugins/aws/configservice/configComplaintRules.js'), 'configDeliveryFailing' : require(__dirname + '/plugins/aws/configservice/configDeliveryFailing.js'), diff --git a/helpers/aws/api.js b/helpers/aws/api.js index 27d7904da9..adc6188406 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -181,6 +181,12 @@ var calls = { paginate: 'nextToken' } }, + ComputeOptimizer: { + getRecommendationSummaries : { + property: 'recommendationSummaries', + paginate: 'nextToken' + } + }, Comprehend: { listEntitiesDetectionJobs: { property: 'EntitiesDetectionJobPropertiesList', diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index 52d8f9f211..4de2d08f9f 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -193,5 +193,6 @@ module.exports = { appmesh: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1'], - frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'] + frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'], + computeoptimizer: ['us-east-1'] }; diff --git a/helpers/aws/regions_china.js b/helpers/aws/regions_china.js index 2a2b9af6de..ece0a63f17 100644 --- a/helpers/aws/regions_china.js +++ b/helpers/aws/regions_china.js @@ -116,5 +116,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + computeoptimizer: ['cn-north-1'] }; diff --git a/helpers/aws/regions_gov.js b/helpers/aws/regions_gov.js index 1eaf28407b..088c93f57b 100644 --- a/helpers/aws/regions_gov.js +++ b/helpers/aws/regions_gov.js @@ -115,5 +115,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + computeoptimizer: ['us-gov-west-1'] }; diff --git a/plugins/aws/computeoptimizer/lambdaFunctionsOptimized.js b/plugins/aws/computeoptimizer/lambdaFunctionsOptimized.js new file mode 100644 index 0000000000..62c3edf61c --- /dev/null +++ b/plugins/aws/computeoptimizer/lambdaFunctionsOptimized.js @@ -0,0 +1,64 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'Lambda Function Findings Optimized', + category: 'Compute Optimizer', + domain: 'Management and Governance', + description: 'Ensure that Compute Optimizer Lambda Function findings are in order to take actions to optimize Amazon Lambda Function that are under-provisioned and over-provisioned.', + more_info: 'AWS Compute Optimizer generates memory size recommendations for AWS Lambda functions. A Lambda function is considered optimized when Compute Optimizer determines that its configured memory or CPU power (which is proportional to the configured memory) is correctly provisioned to run your workload.', + link: 'https://docs.aws.amazon.com/compute-optimizer/latest/ug/view-lambda-recommendations.html', + recommended_action: 'Enable Compute Optimizer Opt In options for AWS Lambda function findings', + apis: ['ComputeOptimizer:getRecommendationSummaries'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + async.each(regions.computeoptimizer, function(region, rcb){ + var getRecommendationSummaries = helpers.addSource(cache, source, + ['computeoptimizer', 'getRecommendationSummaries', region]); + + if (!getRecommendationSummaries) return rcb(); + + if (getRecommendationSummaries && getRecommendationSummaries.err && + getRecommendationSummaries.err.code === 'OptInRequiredException'){ + helpers.addResult(results, 0, + 'Compute Optimizer is not enabled', region); + return rcb(); + } + + if (getRecommendationSummaries.err || !getRecommendationSummaries.data) { + helpers.addResult(results, 3, + 'Unable to get recommendation summaries: ' + helpers.addError(getRecommendationSummaries), region); + return rcb(); + } + + if (!getRecommendationSummaries.data.length) { + helpers.addResult(results, 0, + 'Optimization for summaries is not configured', region); + return rcb(); + } + + let findings = getRecommendationSummaries.data.find(resourceType => resourceType.recommendationResourceType === 'LambdaFunction'); + if (findings) { + let notOptimized = findings.summaries.find(summary => summary.name === 'NotOptimized'); + if (notOptimized.value){ + helpers.addResult(results, 2, + `Lambda Functions are not optimized, NOT_OPTIMIZED Functions: ${notOptimized.value}`, region); + } else { + helpers.addResult(results, 0, + 'All Lambda Functions are optimized', region); + } + } else { + helpers.addResult(results, 2, + 'No Lambda function findings configured', region); + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/aws/computeoptimizer/lambdaFunctionsOptimized.spec.js b/plugins/aws/computeoptimizer/lambdaFunctionsOptimized.spec.js new file mode 100644 index 0000000000..8aee6ec0b5 --- /dev/null +++ b/plugins/aws/computeoptimizer/lambdaFunctionsOptimized.spec.js @@ -0,0 +1,133 @@ +var expect = require('chai').expect; +var lambdaFunctionsOptimized = require('./lambdaFunctionsOptimized'); + +const getRecommendationSummaries = [ + { + "summaries": [ + { + "name": "Optimized", + "value": 0.0 + }, + { + "name": "NotOptimized", + "value": 0.0, + "reasonCodeSummaries": [ + { + "name": "MemoryOverprovisioned", + "value": 0.0 + }, + { + "name": "MemoryUnderprovisioned", + "value": 0.0 + } + ] + } + ], + "recommendationResourceType": "LambdaFunction", + "accountId": "000011112222", + "currentPerformanceRiskRatings": { + "high": 0, + "medium": 0, + "low": 0, + "veryLow": 0 + } + }, + { + "summaries": [ + { + "name": "Optimized", + "value": 0.0 + }, + { + "name": "NotOptimized", + "value": 1.0, + "reasonCodeSummaries": [ + { + "name": "MemoryOverprovisioned", + "value": 1.0 + }, + { + "name": "MemoryUnderprovisioned", + "value": 0.0 + } + ] + } + ], + "recommendationResourceType": "LambdaFunction", + "accountId": "000011112222", + "currentPerformanceRiskRatings": { + "high": 0, + "medium": 0, + "low": 0, + "veryLow": 0 + } + } +]; + + +const createCache = (recommendation, recommendationErr) => { + return { + computeoptimizer: { + getRecommendationSummaries: { + 'us-east-1': { + err: recommendationErr, + data: recommendation + }, + }, + }, + }; +}; + +describe('lambdaFunctionsOptimized', function () { + describe('run', function () { + it('should PASS if All Lambda Functions are optimized', function (done) { + const cache = createCache([getRecommendationSummaries[0]]); + lambdaFunctionsOptimized.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('All Lambda Functions are optimized'); + done(); + }); + }); + + it('should FAIL if Lambda Functions are not optimized', function (done) { + const cache = createCache([getRecommendationSummaries[1]]); + lambdaFunctionsOptimized.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('Lambda Functions are not optimized'); + done(); + }); + }); + + it('should PASS if Optimization for summaries is not configured', function (done) { + const cache = createCache([]); + lambdaFunctionsOptimized.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('Optimization for summaries is not configured'); + done(); + }); + }); + + it('should UNKNOWN if Unable to get recommendation summaries', function (done) { + const cache = createCache(null, { message: "Unable to get recommendation summaries" }); + lambdaFunctionsOptimized.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 recommendation summaries'); + done(); + }); + }); + + it('should not return anything if get recommendation summaries status response is not found', () => { + lambdaFunctionsOptimized.run({}, {}, (err, results) => { + expect(results.length).to.equal(0); + }) + }); + }); +}); \ No newline at end of file From 7eb87a58d1fc88ba653e87178fba94eecb9020f4 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 21 Apr 2022 19:28:40 +0500 Subject: [PATCH 084/350] Added Modification for Remediation Trigger To Open Plugins --- plugins/aws/ec2/openCIFS.js | 2 +- plugins/aws/ec2/openDNS.js | 2 +- plugins/aws/ec2/openDocker.js | 2 +- plugins/aws/ec2/openElasticsearch.js | 2 +- plugins/aws/ec2/openFTP.js | 2 +- plugins/aws/ec2/openHadoopNameNode.js | 2 +- plugins/aws/ec2/openHadoopNameNodeWebUI.js | 2 +- plugins/aws/ec2/openKibana.js | 2 +- plugins/aws/ec2/openMySQL.js | 2 +- plugins/aws/ec2/openNetBIOS.js | 2 +- plugins/aws/ec2/openOracle.js | 2 +- plugins/aws/ec2/openPostgreSQL.js | 2 +- plugins/aws/ec2/openRDP.js | 2 +- plugins/aws/ec2/openRPC.js | 2 +- plugins/aws/ec2/openSMBoTCP.js | 2 +- plugins/aws/ec2/openSMTP.js | 2 +- plugins/aws/ec2/openSQLServer.js | 2 +- plugins/aws/ec2/openSSH.js | 2 +- plugins/aws/ec2/openSalt.js | 2 +- plugins/aws/ec2/openTelnet.js | 2 +- plugins/aws/ec2/openVNCClient.js | 2 +- plugins/aws/ec2/openVNCServer.js | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) diff --git a/plugins/aws/ec2/openCIFS.js b/plugins/aws/ec2/openCIFS.js index 3ea42ad7df..4d8c8a2c31 100644 --- a/plugins/aws/ec2/openCIFS.js +++ b/plugins/aws/ec2/openCIFS.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress','ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openDNS.js b/plugins/aws/ec2/openDNS.js index 2884e2e727..f06d104eb0 100644 --- a/plugins/aws/ec2/openDNS.js +++ b/plugins/aws/ec2/openDNS.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openDocker.js b/plugins/aws/ec2/openDocker.js index 8fd0138cee..8fe6f048b6 100644 --- a/plugins/aws/ec2/openDocker.js +++ b/plugins/aws/ec2/openDocker.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:RevokeSecurityGroupIngress'], rollback: ['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openElasticsearch.js b/plugins/aws/ec2/openElasticsearch.js index ae0cdd70b4..f005237ede 100644 --- a/plugins/aws/ec2/openElasticsearch.js +++ b/plugins/aws/ec2/openElasticsearch.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openFTP.js b/plugins/aws/ec2/openFTP.js index 6ff5331ff6..48e9091b13 100644 --- a/plugins/aws/ec2/openFTP.js +++ b/plugins/aws/ec2/openFTP.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openHadoopNameNode.js b/plugins/aws/ec2/openHadoopNameNode.js index 38fcc4c277..48570f7d54 100644 --- a/plugins/aws/ec2/openHadoopNameNode.js +++ b/plugins/aws/ec2/openHadoopNameNode.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openHadoopNameNodeWebUI.js b/plugins/aws/ec2/openHadoopNameNodeWebUI.js index 00486be966..24b43819c8 100644 --- a/plugins/aws/ec2/openHadoopNameNodeWebUI.js +++ b/plugins/aws/ec2/openHadoopNameNodeWebUI.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openKibana.js b/plugins/aws/ec2/openKibana.js index 8248e362c8..0ba4372429 100644 --- a/plugins/aws/ec2/openKibana.js +++ b/plugins/aws/ec2/openKibana.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openMySQL.js b/plugins/aws/ec2/openMySQL.js index 902c18c3e9..b87719771c 100644 --- a/plugins/aws/ec2/openMySQL.js +++ b/plugins/aws/ec2/openMySQL.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openNetBIOS.js b/plugins/aws/ec2/openNetBIOS.js index 147c87b080..b0540975a7 100644 --- a/plugins/aws/ec2/openNetBIOS.js +++ b/plugins/aws/ec2/openNetBIOS.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openOracle.js b/plugins/aws/ec2/openOracle.js index 2e575bf01f..724b012a28 100644 --- a/plugins/aws/ec2/openOracle.js +++ b/plugins/aws/ec2/openOracle.js @@ -45,7 +45,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openPostgreSQL.js b/plugins/aws/ec2/openPostgreSQL.js index 4f8cc3bfd3..e246ee067a 100644 --- a/plugins/aws/ec2/openPostgreSQL.js +++ b/plugins/aws/ec2/openPostgreSQL.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openRDP.js b/plugins/aws/ec2/openRDP.js index d9a0097698..5aca05a31b 100644 --- a/plugins/aws/ec2/openRDP.js +++ b/plugins/aws/ec2/openRDP.js @@ -46,7 +46,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openRPC.js b/plugins/aws/ec2/openRPC.js index f9c4f9548b..7ea2907daf 100644 --- a/plugins/aws/ec2/openRPC.js +++ b/plugins/aws/ec2/openRPC.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openSMBoTCP.js b/plugins/aws/ec2/openSMBoTCP.js index 5028ca4af1..f52e4aa7dc 100644 --- a/plugins/aws/ec2/openSMBoTCP.js +++ b/plugins/aws/ec2/openSMBoTCP.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openSMTP.js b/plugins/aws/ec2/openSMTP.js index 8ba72c551c..9e368daf7e 100644 --- a/plugins/aws/ec2/openSMTP.js +++ b/plugins/aws/ec2/openSMTP.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openSQLServer.js b/plugins/aws/ec2/openSQLServer.js index 7f44d74401..93feaa6ae1 100644 --- a/plugins/aws/ec2/openSQLServer.js +++ b/plugins/aws/ec2/openSQLServer.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openSSH.js b/plugins/aws/ec2/openSSH.js index 1d5d7bf5d9..cd96c41696 100644 --- a/plugins/aws/ec2/openSSH.js +++ b/plugins/aws/ec2/openSSH.js @@ -46,7 +46,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openSalt.js b/plugins/aws/ec2/openSalt.js index d1dd2cb097..1a6810a162 100644 --- a/plugins/aws/ec2/openSalt.js +++ b/plugins/aws/ec2/openSalt.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openTelnet.js b/plugins/aws/ec2/openTelnet.js index bb5c152dca..61f6d7e9a0 100644 --- a/plugins/aws/ec2/openTelnet.js +++ b/plugins/aws/ec2/openTelnet.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openVNCClient.js b/plugins/aws/ec2/openVNCClient.js index ef81c32afa..c431187930 100644 --- a/plugins/aws/ec2/openVNCClient.js +++ b/plugins/aws/ec2/openVNCClient.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { diff --git a/plugins/aws/ec2/openVNCServer.js b/plugins/aws/ec2/openVNCServer.js index e0df2f4248..379c870aba 100644 --- a/plugins/aws/ec2/openVNCServer.js +++ b/plugins/aws/ec2/openVNCServer.js @@ -43,7 +43,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress', 'ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { From 34d6d539f137c04534e88223f6a11a72a1692fff Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Fri, 22 Apr 2022 20:23:53 +0500 Subject: [PATCH 085/350] Added Optimized Configuration Error Plugins --- exports.js | 2 + helpers/aws/api.js | 6 ++ helpers/aws/regions.js | 3 +- helpers/aws/regions_china.js | 3 +- helpers/aws/regions_gov.js | 3 +- .../optimizedConfigurationError.js | 43 +++++++++ .../optimizedConfigurationError.spec.js | 93 +++++++++++++++++++ 7 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 plugins/aws/computeoptimizer/optimizedConfigurationError.js create mode 100644 plugins/aws/computeoptimizer/optimizedConfigurationError.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..3dc315d8fe 100644 --- a/exports.js +++ b/exports.js @@ -84,6 +84,8 @@ module.exports = { 'globalLoggingDuplicated' : require(__dirname + '/plugins/aws/cloudtrail/globalLoggingDuplicated.js'), 'cloudtrailNotificationsEnabled': require(__dirname + '/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js'), + 'optimizedConfigurationError' : require(__dirname + '/plugins/aws/computeoptimizer/optimizedConfigurationError.js'), + 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), 'configComplaintRules' : require(__dirname + '/plugins/aws/configservice/configComplaintRules.js'), 'configDeliveryFailing' : require(__dirname + '/plugins/aws/configservice/configDeliveryFailing.js'), diff --git a/helpers/aws/api.js b/helpers/aws/api.js index 27d7904da9..adc6188406 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -181,6 +181,12 @@ var calls = { paginate: 'nextToken' } }, + ComputeOptimizer: { + getRecommendationSummaries : { + property: 'recommendationSummaries', + paginate: 'nextToken' + } + }, Comprehend: { listEntitiesDetectionJobs: { property: 'EntitiesDetectionJobPropertiesList', diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index 52d8f9f211..4de2d08f9f 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -193,5 +193,6 @@ module.exports = { appmesh: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1'], - frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'] + frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'], + computeoptimizer: ['us-east-1'] }; diff --git a/helpers/aws/regions_china.js b/helpers/aws/regions_china.js index 2a2b9af6de..ece0a63f17 100644 --- a/helpers/aws/regions_china.js +++ b/helpers/aws/regions_china.js @@ -116,5 +116,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + computeoptimizer: ['cn-north-1'] }; diff --git a/helpers/aws/regions_gov.js b/helpers/aws/regions_gov.js index 1eaf28407b..088c93f57b 100644 --- a/helpers/aws/regions_gov.js +++ b/helpers/aws/regions_gov.js @@ -115,5 +115,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + computeoptimizer: ['us-gov-west-1'] }; diff --git a/plugins/aws/computeoptimizer/optimizedConfigurationError.js b/plugins/aws/computeoptimizer/optimizedConfigurationError.js new file mode 100644 index 0000000000..421e624033 --- /dev/null +++ b/plugins/aws/computeoptimizer/optimizedConfigurationError.js @@ -0,0 +1,43 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'Optimized Configuration Error', + category: 'Compute Optimizer', + domain: 'Management and Governance', + description: 'Ensure that Compute Optimizer is enabled to avoid any Opt In exception error.', + more_info: 'AWS Compute Optimizer is a service that analyzes the configuration and utilization metrics of your AWS resources. It reports whether your resources are optimal, and generates optimization recommendations to reduce the cost and improve the performance of your workloads.', + link: 'https://docs.aws.amazon.com/compute-optimizer/latest/ug/what-is-compute-optimizer.html', + recommended_action: 'Enable Compute Optimizer Opt In options to avoid Opt In Required exception error', + apis: ['ComputeOptimizer:getRecommendationSummaries'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + async.each(regions.computeoptimizer, function(region, rcb){ + var getRecommendationSummaries = helpers.addSource(cache, source, + ['computeoptimizer', 'getRecommendationSummaries', region]); + + if (!getRecommendationSummaries) return rcb(); + + if (getRecommendationSummaries && getRecommendationSummaries.err && getRecommendationSummaries.err.code && + getRecommendationSummaries.err.code === 'OptInRequiredException'){ + helpers.addResult(results, 2, + 'Compute Optimizer is not enabled', region); + } else if (getRecommendationSummaries.err || !getRecommendationSummaries.data || + !getRecommendationSummaries.data.length) { + helpers.addResult(results, 3, + 'Unable to get recommendation summaries: ' + helpers.addError(getRecommendationSummaries), region); + } else { + helpers.addResult(results, 0, + 'Compute Optimizer is Enabled', region); + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/aws/computeoptimizer/optimizedConfigurationError.spec.js b/plugins/aws/computeoptimizer/optimizedConfigurationError.spec.js new file mode 100644 index 0000000000..66dccb0f79 --- /dev/null +++ b/plugins/aws/computeoptimizer/optimizedConfigurationError.spec.js @@ -0,0 +1,93 @@ +var expect = require('chai').expect; +var optimizedConfigurationError = require('./optimizedConfigurationError'); + +const getRecommendationSummaries = [ + { + "summaries": [ + { + "name": "Optimized", + "value": 0.0 + }, + { + "name": "NotOptimized", + "value": 1.0, + "reasonCodeSummaries": [ + { + "name": "MemoryOverprovisioned", + "value": 1.0 + }, + { + "name": "MemoryUnderprovisioned", + "value": 0.0 + } + ] + } + ], + "recommendationResourceType": "LambdaFunction", + "accountId": "000011112222", + "currentPerformanceRiskRatings": { + "high": 0, + "medium": 0, + "low": 0, + "veryLow": 0 + } + } +]; + + +const createCache = (recommendation, recommendationErr) => { + return { + computeoptimizer: { + getRecommendationSummaries: { + 'us-east-1': { + err: recommendationErr, + data: recommendation + }, + }, + }, + }; +}; + +describe('optimizedConfigurationError', function () { + describe('run', function () { + it('should PASS if Compute Optimizer is Enabled', function (done) { + const cache = createCache([getRecommendationSummaries[0]]); + optimizedConfigurationError.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('Compute Optimizer is Enabled'); + done(); + }); + }); + + it('should FAIL if Compute Optimizer is not enabled', function (done) { + const cache = createCache(null, { message: 'Aws account is not registered for recommendation.', code: 'OptInRequiredException' }); + optimizedConfigurationError.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('Compute Optimizer is not enabled'); + + done(); + }); + }); + + it('should UNKNOWN if Unable to get recommendation summaries', function (done) { + const cache = createCache(null, { message: "Unable to get recommendation summaries" }); + optimizedConfigurationError.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 recommendation summaries'); + done(); + }); + }); + + it('should not return anything if get recommendation summaries status response is not found', () => { + optimizedConfigurationError.run({}, {}, (err, results) => { + expect(results.length).to.equal(0); + }) + }); + }); +}); \ No newline at end of file From 3593fbc41642b3c9a9592703f6f51915a319f5da Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Fri, 22 Apr 2022 20:41:39 +0500 Subject: [PATCH 086/350] Added EBS Volumes Optimized Plugins --- exports.js | 2 + helpers/aws/api.js | 6 + helpers/aws/regions.js | 3 +- helpers/aws/regions_china.js | 3 +- helpers/aws/regions_gov.js | 3 +- .../computeoptimizer/ebsVolumesOptimized.js | 64 ++++++++++ .../ebsVolumesOptimized.spec.js | 113 ++++++++++++++++++ 7 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 plugins/aws/computeoptimizer/ebsVolumesOptimized.js create mode 100644 plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js diff --git a/exports.js b/exports.js index 74d4e68c8a..b879da4966 100644 --- a/exports.js +++ b/exports.js @@ -84,6 +84,8 @@ module.exports = { 'globalLoggingDuplicated' : require(__dirname + '/plugins/aws/cloudtrail/globalLoggingDuplicated.js'), 'cloudtrailNotificationsEnabled': require(__dirname + '/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js'), + 'ebsVolumesOptimized' : require(__dirname + '/plugins/aws/computeoptimizer/ebsVolumesOptimized.js'), + 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), 'configComplaintRules' : require(__dirname + '/plugins/aws/configservice/configComplaintRules.js'), 'configDeliveryFailing' : require(__dirname + '/plugins/aws/configservice/configDeliveryFailing.js'), diff --git a/helpers/aws/api.js b/helpers/aws/api.js index 27d7904da9..adc6188406 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -181,6 +181,12 @@ var calls = { paginate: 'nextToken' } }, + ComputeOptimizer: { + getRecommendationSummaries : { + property: 'recommendationSummaries', + paginate: 'nextToken' + } + }, Comprehend: { listEntitiesDetectionJobs: { property: 'EntitiesDetectionJobPropertiesList', diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index 52d8f9f211..4de2d08f9f 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -193,5 +193,6 @@ module.exports = { appmesh: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1'], - frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'] + frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'], + computeoptimizer: ['us-east-1'] }; diff --git a/helpers/aws/regions_china.js b/helpers/aws/regions_china.js index 2a2b9af6de..ece0a63f17 100644 --- a/helpers/aws/regions_china.js +++ b/helpers/aws/regions_china.js @@ -116,5 +116,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + computeoptimizer: ['cn-north-1'] }; diff --git a/helpers/aws/regions_gov.js b/helpers/aws/regions_gov.js index 1eaf28407b..088c93f57b 100644 --- a/helpers/aws/regions_gov.js +++ b/helpers/aws/regions_gov.js @@ -115,5 +115,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + computeoptimizer: ['us-gov-west-1'] }; diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js new file mode 100644 index 0000000000..a1c141d53f --- /dev/null +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js @@ -0,0 +1,64 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'EBS Volumes Optimized', + category: 'Compute Optimizer', + domain: 'Management and Governance', + description: 'Ensure that Compute Optimizer EBS volume recommendations are in order to take the actions to optimize Amazon EBS volumes that are under-performing.', + more_info: 'An EBS volume is considered optimized when Compute Optimizer determines that the volume is correctly provisioned to run your workload, based on the chosen volume type, volume size, and IOPS specification. For optimized resources, Compute Optimizer might sometimes recommend a new generation volume type.', + link: 'https://docs.aws.amazon.com/compute-optimizer/latest/ug/view-ebs-recommendations.html', + recommended_action: 'Enable Compute Optimizer Opt In options for EBS volume recommendations', + apis: ['ComputeOptimizer:getRecommendationSummaries'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + async.each(regions.computeoptimizer, function(region, rcb){ + var getRecommendationSummaries = helpers.addSource(cache, source, + ['computeoptimizer', 'getRecommendationSummaries', region]); + + if (!getRecommendationSummaries) return rcb(); + + if (getRecommendationSummaries && getRecommendationSummaries.err && + getRecommendationSummaries.err.code === 'OptInRequiredException'){ + helpers.addResult(results, 0, + 'Compute Optimizer is not enabled', region); + return rcb(); + } + + if (getRecommendationSummaries.err || !getRecommendationSummaries.data) { + helpers.addResult(results, 3, + 'Unable to get recommendation summaries: ' + helpers.addError(getRecommendationSummaries), region); + return rcb(); + } + + if (!getRecommendationSummaries.data.length) { + helpers.addResult(results, 0, + 'Optimization for summaries is not configured', region); + return rcb(); + } + + let findings = getRecommendationSummaries.data.find(resourceType => resourceType.recommendationResourceType === 'EbsVolume'); + if (findings) { + let notOptimized = findings.summaries.find(summary => summary.name === 'NotOptimized'); + if (notOptimized.value){ + helpers.addResult(results, 2, + `EBS volumes are not optimized, NOT_OPTIMIZED: ${notOptimized.value}`, region); + } else { + helpers.addResult(results, 0, + 'All EBS volumes are optimized', region); + } + } else { + helpers.addResult(results, 2, + 'No EBS volumes configured', region); + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js new file mode 100644 index 0000000000..846cd66018 --- /dev/null +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js @@ -0,0 +1,113 @@ +var expect = require('chai').expect; +var ebsVolumesOptimized = require('./ebsVolumesOptimized'); + +const getRecommendationSummaries = [ + { + "summaries": [ + { + "name": "Optimized", + "value": 0.0 + }, + { + "name": "NotOptimized", + "value": 0.0 + } + ], + "recommendationResourceType": "EbsVolume", + "accountId": "101363889637", + "currentPerformanceRiskRatings": { + "high": 0, + "medium": 0, + "low": 0, + "veryLow": 0 + } + }, + { + "summaries": [ + { + "name": "Optimized", + "value": 0.0 + }, + { + "name": "NotOptimized", + "value": 1.0 + } + ], + "recommendationResourceType": "EbsVolume", + "accountId": "101363889637", + "currentPerformanceRiskRatings": { + "high": 0, + "medium": 0, + "low": 0, + "veryLow": 0 + } + } +]; + + +const createCache = (recommendation, recommendationErr) => { + return { + computeoptimizer: { + getRecommendationSummaries: { + 'us-east-1': { + err: recommendationErr, + data: recommendation + }, + }, + }, + }; +}; + +describe('ebsVolumesOptimized', function () { + describe('run', function () { + it('should PASS if All EBS volumes are optimized', function (done) { + const cache = createCache([getRecommendationSummaries[0]]); + ebsVolumesOptimized.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('All EBS volumes are optimized'); + done(); + }); + }); + + it('should FAIL if EBS volumes are not optimized', function (done) { + const cache = createCache([getRecommendationSummaries[1]]); + ebsVolumesOptimized.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('EBS volumes are not optimized'); + done(); + }); + }); + + it('should PASS if Optimization for summaries is not configured', function (done) { + const cache = createCache([]); + ebsVolumesOptimized.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('Optimization for summaries is not configured'); + done(); + }); + }); + + it('should UNKNOWN if Unable to get recommendation summaries', function (done) { + const cache = createCache(null, { message: "Unable to get recommendation summaries" }); + ebsVolumesOptimized.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 recommendation summaries'); + done(); + }); + }); + + it('should not return anything if get recommendation summaries status response is not found', () => { + ebsVolumesOptimized.run({}, {}, (err, results) => { + expect(results.length).to.equal(0); + }) + }); + }); +}); \ No newline at end of file From 59ab65b0334dc954f6285cfab3aa98381271ee4a Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Mon, 25 Apr 2022 02:25:29 +0500 Subject: [PATCH 087/350] Oracle - OKE Private Endpoint Plugin --- collectors/oracle/collector.js | 8 + exports.js | 2 + helpers/oracle/regions.js | 3 +- other_modules/oci/services.json | 14 ++ plugins/oracle/oke/okePrivateEndpoint.js | 59 ++++++++ plugins/oracle/oke/okePrivateEndpoint.spec.js | 140 ++++++++++++++++++ 6 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 plugins/oracle/oke/okePrivateEndpoint.js create mode 100644 plugins/oracle/oke/okePrivateEndpoint.spec.js diff --git a/collectors/oracle/collector.js b/collectors/oracle/collector.js index 59441f94ab..a268483d60 100644 --- a/collectors/oracle/collector.js +++ b/collectors/oracle/collector.js @@ -67,6 +67,14 @@ var calls = { filterValue: ['compartmentId'] } }, + cluster: { + list: { + api: 'oke', + restVersion: '/20180222', + filterKey: ['compartmentId'], + filterValue: ['compartmentId'] + } + }, user: { list: { api: 'iam', diff --git a/exports.js b/exports.js index 74d4e68c8a..62430e9bc4 100644 --- a/exports.js +++ b/exports.js @@ -852,6 +852,8 @@ module.exports = { 'blockPolicyProtection' : require(__dirname + '/plugins/oracle/blockstorage/blockPolicyProtection.js'), 'logRetentionPeriod' : require(__dirname + '/plugins/oracle/audit/logRetentionPeriod.js'), + + 'okePrivateEndpoint' : require(__dirname + '/plugins/oracle/oke/okePrivateEndpoint.js'), }, google: { 'excessiveFirewallRules' : require(__dirname + '/plugins/google/vpcnetwork/excessiveFirewallRules.js'), diff --git a/helpers/oracle/regions.js b/helpers/oracle/regions.js index 88fbc9e1ed..db04409479 100644 --- a/helpers/oracle/regions.js +++ b/helpers/oracle/regions.js @@ -76,5 +76,6 @@ module.exports = { namespace: regions, apiKey: ['default'], authToken: ['default'], - customerSecretKey: ['default'] + customerSecretKey: ['default'], + cluster: regions, }; \ No newline at end of file diff --git a/other_modules/oci/services.json b/other_modules/oci/services.json index 5e8f6d7606..f2ea92c1b9 100644 --- a/other_modules/oci/services.json +++ b/other_modules/oci/services.json @@ -23,6 +23,20 @@ } } }, + "oke": { + "cluster": { + "list": { + "allowedQueryStrings": [ + "compartmentId", + "page", + "limit" + ], + "method": "GET", + "path": "clusters", + "endpoint": "containerengine.{{region}}.oci.oraclecloud.com" + } + } + }, "core": { "instance": { "list": { diff --git a/plugins/oracle/oke/okePrivateEndpoint.js b/plugins/oracle/oke/okePrivateEndpoint.js new file mode 100644 index 0000000000..86d72d5e79 --- /dev/null +++ b/plugins/oracle/oke/okePrivateEndpoint.js @@ -0,0 +1,59 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'OKE Private Endpoint', + category: 'OKE', + domain: 'Containers', + description: 'Ensures the private endpoint setting is enabled for OKE clusters', + more_info: 'OKE private endpoints can be used to route all traffic between the Kubernetes worker and control plane nodes over a private VCN endpoint rather than across the public internet.', + recommended_action: 'Enable the private endpoint setting for all OKE clusters.', + link: 'https://docs.oracle.com/en-us/iaas/Content/ContEng/Concepts/contengclustersnodes.htm#processes', + apis: ['cluster:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.cluster, function(region, rcb){ + + if (helpers.checkRegionSubscription(cache, source, results, region)) { + + var clusters = helpers.addSource(cache, source, + ['cluster', 'list', region]); + + if (!clusters) return rcb(); + + if (clusters.err || !clusters.data) { + helpers.addResult(results, 3, + 'Unable to query for OKE clusters: ' + helpers.addError(clusters), region); + return rcb(); + } + + if (!clusters.data.length) { + helpers.addResult(results, 0, 'No OKE clusters found', region); + return rcb(); + } + + clusters.data.forEach(cluster => { + if (cluster.lifecycleState && cluster.lifecycleState === 'DELETED') return; + + if (cluster.endpointConfig && cluster.endpointConfig.isPublicIpEnabled) { + helpers.addResult(results, 2, 'OKE cluster does not have private endpoint enabled', region, cluster.name); + } else { + helpers.addResult(results, 0, 'OKE cluster has private endpoint enabled', region, cluster.name); + } + }); + } + + rcb(); + }, function(){ + // Global checking goes here + callback(null, results, source); + }); + } +}; + + + \ No newline at end of file diff --git a/plugins/oracle/oke/okePrivateEndpoint.spec.js b/plugins/oracle/oke/okePrivateEndpoint.spec.js new file mode 100644 index 0000000000..8627618c08 --- /dev/null +++ b/plugins/oracle/oke/okePrivateEndpoint.spec.js @@ -0,0 +1,140 @@ +var expect = require('chai').expect; +var plugin = require('./okePrivateEndpoint'); + +const createCache = (err, data) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + cluster: { + list: { + 'us-ashburn-1': { + err: err, + data: data + } + } + } + } +}; + +describe('okePrivateEndpoint', function () { + describe('run', function () { + it('should give unknown result if a cluster error occurs', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for OKE clusters') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['error'], + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if no oke clusters are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No OKE clusters found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if OKE cluster does not have private endpoint enabled', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('does not have private endpoint enabled') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [ + { + "id": "cluster1", + "name": "cluster1", + "endpointConfig": { + "isPublicIpEnabled": true + }, + "endpoints": { + "kubernetes": null, + "publicEndpoint": "10.0.0.0:8080", + "privateEndpoint": null, + }, + } + ] + + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if oke cluster has private endpoint enabled', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('has private endpoint enabled') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [ + { + "id": "cluster1", + "name": "cluster1", + "endpoints": { + "kubernetes": null, + "publicEndpoint": null, + "privateEndpoint": "10.0.0.0:8080", + }, + "endpointConfig": { + "isPublicIpEnabled": false + }, + } + ] + ); + + plugin.run(cache, {}, callback); + }); + }); +}); \ No newline at end of file From 8c42cfa5eff4cc6f599825ffb1a1657bd9bb5890 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 26 Apr 2022 16:01:30 +0500 Subject: [PATCH 088/350] Added some changes to Plugin --- .../computeoptimizer/ebsVolumesOptimized.js | 10 ++++-- .../ebsVolumesOptimized.spec.js | 35 +++++++++++++++++-- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js index a1c141d53f..66dbe6b1ed 100644 --- a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js @@ -43,8 +43,14 @@ module.exports = { let findings = getRecommendationSummaries.data.find(resourceType => resourceType.recommendationResourceType === 'EbsVolume'); if (findings) { - let notOptimized = findings.summaries.find(summary => summary.name === 'NotOptimized'); - if (notOptimized.value){ + + let notOptimized = findings.summaries.find(notOpt => notOpt.name === 'NotOptimized'); + let optimized = findings.summaries.find(opt => opt.name === 'Optimized'); + + if (!notOptimized.value && !optimized.value){ + helpers.addResult(results, 0, + 'EBS volumes have no recommendations enabled', region); + } else if (notOptimized.value){ helpers.addResult(results, 2, `EBS volumes are not optimized, NOT_OPTIMIZED: ${notOptimized.value}`, region); } else { diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js index 846cd66018..a321553e21 100644 --- a/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js @@ -6,7 +6,7 @@ const getRecommendationSummaries = [ "summaries": [ { "name": "Optimized", - "value": 0.0 + "value": 1.0 }, { "name": "NotOptimized", @@ -41,7 +41,27 @@ const getRecommendationSummaries = [ "low": 0, "veryLow": 0 } - } + }, + { + "summaries": [ + { + "name": "Optimized", + "value": 0.0 + }, + { + "name": "NotOptimized", + "value": 0.0 + } + ], + "recommendationResourceType": "EbsVolume", + "accountId": "101363889637", + "currentPerformanceRiskRatings": { + "high": 0, + "medium": 0, + "low": 0, + "veryLow": 0 + } + }, ]; @@ -82,6 +102,17 @@ describe('ebsVolumesOptimized', function () { }); }); + it('should PASS if EBS volumes have no recommendations enabled', function (done) { + const cache = createCache([getRecommendationSummaries[2]]); + ebsVolumesOptimized.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('EBS volumes have no recommendations enabled'); + done(); + }); + }); + it('should PASS if Optimization for summaries is not configured', function (done) { const cache = createCache([]); ebsVolumesOptimized.run(cache, {}, (err, results) => { From 4362543570dd8c62ae59ac0007ca6754b047b520 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 26 Apr 2022 16:12:11 +0500 Subject: [PATCH 089/350] Added some changes to Plugin --- .../lambdaFunctionsOptimized.js | 8 +++- .../lambdaFunctionsOptimized.spec.js | 45 ++++++++++++++++++- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/plugins/aws/computeoptimizer/lambdaFunctionsOptimized.js b/plugins/aws/computeoptimizer/lambdaFunctionsOptimized.js index 62c3edf61c..8653f2f885 100644 --- a/plugins/aws/computeoptimizer/lambdaFunctionsOptimized.js +++ b/plugins/aws/computeoptimizer/lambdaFunctionsOptimized.js @@ -43,8 +43,12 @@ module.exports = { let findings = getRecommendationSummaries.data.find(resourceType => resourceType.recommendationResourceType === 'LambdaFunction'); if (findings) { - let notOptimized = findings.summaries.find(summary => summary.name === 'NotOptimized'); - if (notOptimized.value){ + let notOptimized = findings.summaries.find(notOpt => notOpt.name === 'NotOptimized'); + let Optimized = findings.summaries.find(Opt => Opt.name === 'Optimized'); + if (!notOptimized.value && !Optimized.value){ + helpers.addResult(results, 0, + 'Lambda Functions have no recommendations enabled', region); + } else if (notOptimized.value){ helpers.addResult(results, 2, `Lambda Functions are not optimized, NOT_OPTIMIZED Functions: ${notOptimized.value}`, region); } else { diff --git a/plugins/aws/computeoptimizer/lambdaFunctionsOptimized.spec.js b/plugins/aws/computeoptimizer/lambdaFunctionsOptimized.spec.js index 8aee6ec0b5..998602ec3d 100644 --- a/plugins/aws/computeoptimizer/lambdaFunctionsOptimized.spec.js +++ b/plugins/aws/computeoptimizer/lambdaFunctionsOptimized.spec.js @@ -6,7 +6,7 @@ const getRecommendationSummaries = [ "summaries": [ { "name": "Optimized", - "value": 0.0 + "value": 1.0 }, { "name": "NotOptimized", @@ -61,7 +61,37 @@ const getRecommendationSummaries = [ "low": 0, "veryLow": 0 } - } + }, + { + "summaries": [ + { + "name": "Optimized", + "value": 0.0 + }, + { + "name": "NotOptimized", + "value": 0.0, + "reasonCodeSummaries": [ + { + "name": "MemoryOverprovisioned", + "value": 0.0 + }, + { + "name": "MemoryUnderprovisioned", + "value": 0.0 + } + ] + } + ], + "recommendationResourceType": "LambdaFunction", + "accountId": "000011112222", + "currentPerformanceRiskRatings": { + "high": 0, + "medium": 0, + "low": 0, + "veryLow": 0 + } + }, ]; @@ -102,6 +132,17 @@ describe('lambdaFunctionsOptimized', function () { }); }); + it('should PASS if Lambda Functions have no recommendations enabled', function (done) { + const cache = createCache([getRecommendationSummaries[2]]); + lambdaFunctionsOptimized.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('Lambda Functions have no recommendations enabled'); + done(); + }); + }); + it('should PASS if Optimization for summaries is not configured', function (done) { const cache = createCache([]); lambdaFunctionsOptimized.run(cache, {}, (err, results) => { From 15eeaa3dbaca6213fdc3be2709836e8f920d8bb9 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 26 Apr 2022 16:55:02 +0500 Subject: [PATCH 090/350] Added some changes to Plugin --- plugins/aws/computeoptimizer/asgOptimized.js | 10 ++++-- .../aws/computeoptimizer/asgOptimized.spec.js | 33 ++++++++++++++++++- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/plugins/aws/computeoptimizer/asgOptimized.js b/plugins/aws/computeoptimizer/asgOptimized.js index dc8e32b3b6..00eafec348 100644 --- a/plugins/aws/computeoptimizer/asgOptimized.js +++ b/plugins/aws/computeoptimizer/asgOptimized.js @@ -43,8 +43,14 @@ module.exports = { let findings = getRecommendationSummaries.data.find(resourceType => resourceType.recommendationResourceType === 'AutoScalingGroup'); if (findings) { - let notOptimized = findings.summaries.find(summary => summary.name && summary.name.toUpperCase() === 'NOT_OPTIMIZED'); - if (notOptimized.value){ + + let notOptimized = findings.summaries.find(notOpt => notOpt.name && notOpt.name.toUpperCase() === 'NOT_OPTIMIZED'); + let Optimized = findings.summaries.find(opt => opt.name && opt.name.toUpperCase() === 'OPTIMIZED'); + + if (!notOptimized.value && !Optimized.value){ + helpers.addResult(results, 0, + 'Auto Scaling Groups have no recommendations enabled', region); + } else if (notOptimized.value){ helpers.addResult(results, 2, `Auto Scaling Groups are not optimized, NOT_OPTIMIZED: ${notOptimized.value}`, region); } else { diff --git a/plugins/aws/computeoptimizer/asgOptimized.spec.js b/plugins/aws/computeoptimizer/asgOptimized.spec.js index 961ca4ea2b..71ed154cd8 100644 --- a/plugins/aws/computeoptimizer/asgOptimized.spec.js +++ b/plugins/aws/computeoptimizer/asgOptimized.spec.js @@ -6,7 +6,7 @@ const getRecommendationSummaries = [ "summaries": [ { "name": "OPTIMIZED", - "value": 0.0 + "value": 1.0 }, { "name": "NOT_OPTIMIZED", @@ -42,6 +42,26 @@ const getRecommendationSummaries = [ "veryLow": 0 } }, + { + "summaries": [ + { + "name": "OPTIMIZED", + "value": 0.0 + }, + { + "name": "NOT_OPTIMIZED", + "value": 0.0 + } + ], + "recommendationResourceType": "AutoScalingGroup", + "accountId": "000011112222", + "currentPerformanceRiskRatings": { + "high": 0, + "medium": 0, + "low": 0, + "veryLow": 0 + } + }, ]; @@ -82,6 +102,17 @@ describe('asgOptimized', function () { }); }); + it('should PASS if Auto Scaling Groups have no recommendations enabled', function (done) { + const cache = createCache([getRecommendationSummaries[2]]); + asgOptimized.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('Auto Scaling Groups have no recommendations enabled'); + done(); + }); + }); + it('should PASS if Optimization for summaries is not configured', function (done) { const cache = createCache([]); asgOptimized.run(cache, {}, (err, results) => { From e9aebc6edd386e1f7f93f23c218c6ef7cb6ddbc2 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 26 Apr 2022 17:05:35 +0500 Subject: [PATCH 091/350] Added some changes to Plugin --- .../computeoptimizer/ec2InstancesOptimized.js | 10 +++-- .../ec2InstancesOptimized.spec.js | 39 ++++++++++++++++++- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/plugins/aws/computeoptimizer/ec2InstancesOptimized.js b/plugins/aws/computeoptimizer/ec2InstancesOptimized.js index 9e36cdb754..1e8f8aa2a3 100644 --- a/plugins/aws/computeoptimizer/ec2InstancesOptimized.js +++ b/plugins/aws/computeoptimizer/ec2InstancesOptimized.js @@ -43,9 +43,13 @@ module.exports = { let findings = getRecommendationSummaries.data.find(resourceType => resourceType.recommendationResourceType === 'Ec2Instance'); if (findings) { - let underProvisioned = findings.summaries.find(summary => summary.name === 'UNDER_PROVISIONED' ); - let overProvisioned = findings.summaries.find(summary => summary.name === 'OVER_PROVISIONED' ); - if (underProvisioned.value || overProvisioned.value){ + let underProvisioned = findings.summaries.find(underProv => underProv.name === 'UNDER_PROVISIONED' ); + let optimized = findings.summaries.find(opt => opt.name === 'OPTIMIZED' ); + let overProvisioned = findings.summaries.find(overProv => overProv.name === 'OVER_PROVISIONED' ); + if (!underProvisioned.value && !overProvisioned.value && !optimized.value){ + helpers.addResult(results, 0, + 'EC2 instances have no recommendations enabled', region); + } else if (underProvisioned.value || overProvisioned.value){ helpers.addResult(results, 2, `EC2 instances are not optimized, under provisioned: ${underProvisioned.value}, over provisioned: ${underProvisioned.value} `, region); } else { diff --git a/plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js b/plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js index dfe5196510..c569e933d0 100644 --- a/plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js +++ b/plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js @@ -6,7 +6,7 @@ const getRecommendationSummaries = [ "summaries": [ { "name": "OPTIMIZED", - "value": 0.0 + "value": 1.0 }, { "name": "UNDER_PROVISIONED", @@ -49,7 +49,31 @@ const getRecommendationSummaries = [ "low": 0, "veryLow": 0 } - } + }, + { + "summaries": [ + { + "name": "OPTIMIZED", + "value": 0.0 + }, + { + "name": "UNDER_PROVISIONED", + "value": 0.0 + }, + { + "name": "OVER_PROVISIONED", + "value": 0.0 + } + ], + "recommendationResourceType": "Ec2Instance", + "accountId": "000011112222", + "currentPerformanceRiskRatings": { + "high": 0, + "medium": 0, + "low": 0, + "veryLow": 0 + } + }, ]; @@ -90,6 +114,17 @@ describe('ec2InstancesOptimized', function () { }); }); + it('should PASS if EC2 instances have no recommendations enabled', function (done) { + const cache = createCache([getRecommendationSummaries[2]]); + ec2InstancesOptimized.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('EC2 instances have no recommendations enabled'); + done(); + }); + }); + it('should PASS if Optimization for summaries is not configured', function (done) { const cache = createCache([]); ec2InstancesOptimized.run(cache, {}, (err, results) => { From 06ad2e0582f0f4354a61297c1ea168f353d8d006 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Thu, 28 Apr 2022 15:52:28 +0500 Subject: [PATCH 092/350] Update plugin --- .../azure/keyvaults/cmkCreationForAppTier.js | 27 +++++++++++---- .../keyvaults/cmkCreationForAppTier.spec.js | 33 +++++++------------ 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/plugins/azure/keyvaults/cmkCreationForAppTier.js b/plugins/azure/keyvaults/cmkCreationForAppTier.js index 09d53f8cdf..778640a478 100644 --- a/plugins/azure/keyvaults/cmkCreationForAppTier.js +++ b/plugins/azure/keyvaults/cmkCreationForAppTier.js @@ -1,5 +1,6 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); +var _ = require('underscore'); module.exports = { title: 'CMK Creation for App Tier Enabled', @@ -10,11 +11,22 @@ module.exports = { recommended_action: 'Ensure each Key Vault has a CMK created and configured.', link: 'https://docs.microsoft.com/en-us/azure/azure-app-configuration/concept-customer-managed-keys', apis: ['vaults:list', 'vaults:getKeys'], + settings: { + app_tier_tag_sets: { + name: 'App Tier Tag Sets', + description: 'A string of allowed tag set objects to use for the CMKs creation for App Tier', + regex: '^.*$s', + default: '' + } + }, run: function(cache, settings, callback) { var results = []; var source = {}; var locations = helpers.locations(settings.govcloud); + var config = { + app_tier_tag_sets: settings.app_tier_tag_sets || this.settings.app_tier_tag_sets.default + }; async.each(locations.vaults, function(location, rcb) { var vaults = helpers.addSource(cache, source, @@ -45,18 +57,21 @@ module.exports = { var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); var keyId = `${vault.id}/keys/${keyName}`; - if (key.attributes) { - let attributes = key.attributes; - if ((attributes.expires && attributes.expires !== null && attributes.expires !== '') || (attributes.exp && attributes.exp !== null && attributes.exp !== '')) { + if (key.tags) { + const tags = key.tags; + const allowedTagSets = config.app_tier_tag_sets.length ? JSON.parse(config.app_tier_tag_sets) : {}; + const result = _.pick(tags, (v, k) => _.isEqual(allowedTagSets[k], v)); + + if (Object.entries(result).length) { helpers.addResult(results, 0, - 'Expiry date is set for the key', location, keyId); + 'CMK Creation for App Tier is enabled', location, keyId); } else { helpers.addResult(results, 2, - 'Expiry date is not set for the key', location, keyId); + 'CMK Creation for App Tier is not enabled', location, keyId); } } else { helpers.addResult(results, 2, - 'Expiry date is not set for the key', location, keyId); + 'CMK Creation for App Tier is not enabled', location, keyId); } }); } diff --git a/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js b/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js index 7d048cb2f5..d35c5bdb23 100644 --- a/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js +++ b/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js @@ -1,5 +1,5 @@ var expect = require('chai').expect; -var auth = require('./secretExpirationEnabled'); +var auth = require('./cmkCreationForAppTier'); const listVaults = [ { @@ -18,18 +18,7 @@ const listVaults = [ "name": "testvault", "type": "Microsoft.KeyVault/vaults", "location": "eastus", - "tags": {}, - "sku": { - "family": "A", - "name": "Standard" - } - }, - { - "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", - "name": "testvault", - "type": "Microsoft.KeyVault/vaults", - "location": "eastus", - "tags": {}, + "tags": { hello: 'world' }, "sku": { "family": "A", "name": "Standard" @@ -91,7 +80,7 @@ const getKeys = [ } ]; -const createCache = (err, list, get) => { +const createCache = (err, list, keys) => { return { vaults: { list: { @@ -100,16 +89,16 @@ const createCache = (err, list, get) => { data: list } }, - getSecrets: { - 'eastus': get + getKeys: { + 'eastus': keys } } } }; -describe('secretExpirationEnabled', function() { +describe('cmkCreationForAppTier', function() { describe('run', function() { - it('should give passing result if no secrets found', function(done) { + it('should give passing result if no key vaults found', function(done) { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); @@ -121,16 +110,16 @@ describe('secretExpirationEnabled', function() { auth.run(createCache(null, [], {}), {}, callback); }); - it('should give failing result if expiration is not set on secrets', function(done) { + it('should give unkown result if Unable to query for Key Vaults', 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('Expiry date is not set for the secret'); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('Unable to query for Key Vaults'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listVaults[0]], getKeys[0]), {}, callback); + auth.run(createCache(null, null, {}), {}, callback); }); it('should give passing result if expiration is set on keys', function(done) { From 2e1fac5d6e6a8396dec1392bac748904d3eec7d4 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sun, 1 May 2022 05:10:48 +0500 Subject: [PATCH 093/350] Oracle - OKE Secrets Encrypted --- collectors/oracle/collector.js | 31 ++- exports.js | 1 + helpers/oracle/functions.js | 21 ++- helpers/oracle/index.js | 3 +- helpers/oracle/regions.js | 2 + other_modules/oci/index.js | 6 + other_modules/oci/services.json | 36 ++++ plugins/oracle/oke/okeSecretsEncrypted.js | 97 ++++++++++ .../oracle/oke/okeSecretsEncrypted.spec.js | 178 ++++++++++++++++++ 9 files changed, 372 insertions(+), 3 deletions(-) create mode 100644 plugins/oracle/oke/okeSecretsEncrypted.js create mode 100644 plugins/oracle/oke/okeSecretsEncrypted.spec.js diff --git a/collectors/oracle/collector.js b/collectors/oracle/collector.js index a268483d60..7160ae0f6f 100644 --- a/collectors/oracle/collector.js +++ b/collectors/oracle/collector.js @@ -253,7 +253,15 @@ var calls = { filterKey: ['compartmentId'], filterValue: ['compartmentId'], } - } + }, + vault: { + list: { + api: 'kms', + filterKey: ['compartmentId'], + filterValue: ['compartmentId'], + restVersion: '/20180608', + } + }, }; // Important Note: All relies must be passed in an array format [] @@ -389,6 +397,27 @@ var postcalls = { filterConfig: [true, false], } }, + keys: { + list: { + api: 'kms', + reliesOnService: ['vault'], + reliesOnCall: ['list'], + filterKey: ['compartmentId', 'managementEndpoint'], + filterValue: ['compartmentId', 'managementEndpoint'], + restVersion: '/20180608' + } + }, + cluster: { + get: { + api: 'oke', + reliesOnService: ['cluster'], + reliesOnCall: ['list'], + restVersion: '/20180222', + filterKey: ['id'], + filterValue: ['id'], + filterConfig: [false] + }, + }, }; // Important Note: All relies must be passed in an array format [] diff --git a/exports.js b/exports.js index a287c1942e..89f4d6e1c2 100644 --- a/exports.js +++ b/exports.js @@ -855,6 +855,7 @@ module.exports = { 'logRetentionPeriod' : require(__dirname + '/plugins/oracle/audit/logRetentionPeriod.js'), 'okePrivateEndpoint' : require(__dirname + '/plugins/oracle/oke/okePrivateEndpoint.js'), + 'okeSecretsEncrypted' : require(__dirname + '/plugins/oracle/oke/okeSecretsEncrypted.js'), }, google: { 'excessiveFirewallRules' : require(__dirname + '/plugins/google/vpcnetwork/excessiveFirewallRules.js'), diff --git a/helpers/oracle/functions.js b/helpers/oracle/functions.js index feaff068ad..5ca4ff35f5 100644 --- a/helpers/oracle/functions.js +++ b/helpers/oracle/functions.js @@ -1,4 +1,5 @@ var shared = require(__dirname + '/../shared.js'); +var async = require('async'); var ipProtocol = { "tcp" : { @@ -341,6 +342,22 @@ function normalizePolicyStatement(policyStatement) { return statementObj; } +function getProtectionLevel(cryptographickey, encryptionLevels) { + if (cryptographickey && cryptographickey.protectionMode) { + if (cryptographickey.protectionMode.toUpperCase() == 'SOFTWARE') return encryptionLevels.indexOf('cloudcmek'); + else if (cryptographickey.protectionMode.toUpperCase() == 'HSM') return encryptionLevels.indexOf('cloudhsm'); + } + + return encryptionLevels.indexOf('unspecified'); +} + +function listToObj(resultObj, listData, onKey) { + async.each(listData, function (entry, cb) { + if (entry[onKey]) resultObj[entry[onKey]] = entry; + cb(); + }); +} + function testStatement(statementObj, resourceTypes, policyAdmins, verbs) { let whereNames = ['request.user.id', 'request.user.name', 'request.groups.id', 'request.group.name', 'request.networkSource.name', 'target.user.name', 'request.instance.compartment.id', 'request.ad']; @@ -378,5 +395,7 @@ module.exports = { findOpenPortsAll: findOpenPortsAll, checkRegionSubscription: checkRegionSubscription, normalizePolicyStatement: normalizePolicyStatement, - testStatement: testStatement + testStatement: testStatement, + getProtectionLevel: getProtectionLevel, + listToObj: listToObj }; diff --git a/helpers/oracle/index.js b/helpers/oracle/index.js index b6b67a2971..32ef6788df 100644 --- a/helpers/oracle/index.js +++ b/helpers/oracle/index.js @@ -134,7 +134,8 @@ function OracleExecutor(OracleConfig) { var helpers = { regions: regions, OracleExecutor: OracleExecutor, - MAX_REGIONS_AT_A_TIME: 6 + MAX_REGIONS_AT_A_TIME: 6, + PROTECTION_LEVELS: ['unspecified', 'default', 'cloudcmek', 'cloudhsm'], }; for (var s in shared) helpers[s] = shared[s]; diff --git a/helpers/oracle/regions.js b/helpers/oracle/regions.js index db04409479..2b9c9f0978 100644 --- a/helpers/oracle/regions.js +++ b/helpers/oracle/regions.js @@ -78,4 +78,6 @@ module.exports = { authToken: ['default'], customerSecretKey: ['default'], cluster: regions, + vault: regions, + keys: regions }; \ No newline at end of file diff --git a/other_modules/oci/index.js b/other_modules/oci/index.js index 3571db3aa0..6a174bc668 100644 --- a/other_modules/oci/index.js +++ b/other_modules/oci/index.js @@ -8,6 +8,12 @@ module.exports = function(api, service, key, OracleConfig, parameters, callback) var localService = services[api][service][key]; + //replacing endpoint with managementRndpoint value from vault for keys api + if (api === 'kms' && localService.path === 'keys') { + localService.endpoint = parameters.managementEndpoint.replace('https://', ''); + delete parameters['managementEndpoint']; + } + var suffix = ''; if (localService.encodedGet) { suffix += ('/' + encodeURIComponent(parameters[localService.encodedGet])); diff --git a/other_modules/oci/services.json b/other_modules/oci/services.json index f2ea92c1b9..0091a31ba2 100644 --- a/other_modules/oci/services.json +++ b/other_modules/oci/services.json @@ -34,6 +34,18 @@ "method": "GET", "path": "clusters", "endpoint": "containerengine.{{region}}.oci.oraclecloud.com" + }, + "get": { + "encodedGet": "id", + "allowedQueryStrings": [ + "compartmentId", + "page", + "limit" + ], + "method": "GET", + "path": "clusters", + "endpoint": "containerengine.{{region}}.oci.oraclecloud.com" + } } }, @@ -394,6 +406,30 @@ } } }, + "kms": { + "vault": { + "list": { + "allowedQueryStrings": [ + "compartmentId", "page", "limit" + ], + "method": "GET", + "path": "vaults", + "endpoint": "kms.{{region}}.oraclecloud.com" + } + }, + + "keys": { + "list": { + "allowedQueryStrings": [ + "compartmentId", "page", "limit" + ], + "method": "GET", + "path": "keys", + "endpoint": "{{managementEndpoint}}" + } + } + }, + "loadBalance": { "loadBalancer": { "list": { diff --git a/plugins/oracle/oke/okeSecretsEncrypted.js b/plugins/oracle/oke/okeSecretsEncrypted.js new file mode 100644 index 0000000000..19f504b144 --- /dev/null +++ b/plugins/oracle/oke/okeSecretsEncrypted.js @@ -0,0 +1,97 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'OKE Secrets Encrypted', + category: 'OKE', + domain: 'Containers', + description: 'Ensures the OKE secret objects have encryption enabled using desired protection level.', + more_info: 'By default, Kubernetes secret objects are encrypted using an Oracle-managed master encryption key. To have better control over the encryption process, you can use Customer-Managed Keys (CMKs).', + recommended_action: 'Ensure all OKE clusters have desired encryption level for secret objects.', + link: 'https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengencryptingdata.htm', + apis: ['vault:list', 'keys:list', 'cluster:list', 'cluster:get'], + settings: { + oke_encryption_level: { + name: 'OKE Encryption Level', + description: 'Desired protection level for OKE Secrets. default: oracle-managed, cloudcmek: customer managed encryption keys, ' + + 'cloudhsm: customer managed HSM encryption key, external: imported or externally managed key', + regex: '^(default|cloudcmek|cloudhsm)$', + default: 'cloudcmek' + } + }, + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + var keysObj = {}; + + let desiredEncryptionLevelStr = settings.oke_encryption_level || this.settings.oke_encryption_level.default; + var desiredEncryptionLevel = helpers.PROTECTION_LEVELS.indexOf(desiredEncryptionLevelStr); + + async.series([ + function(cb) { + async.each(regions.keys, function(region, rcb) { + let keys = helpers.addSource( + cache, source, ['keys', 'list', region]); + if (keys && keys.data && keys.data.length) helpers.listToObj(keysObj, keys.data, 'id'); + rcb(); + }, function() { + cb(); + }); + }, + function(cb) { + async.each(regions.cluster, function(region, rcb) { + + if (helpers.checkRegionSubscription(cache, source, results, region)) { + + var clusters = helpers.addSource(cache, source, + ['cluster', 'get', region]); + + if (!clusters) return rcb(); + + if (clusters.err || !clusters.data) { + helpers.addResult(results, 3, + 'Unable to query for OKE clusters: ' + helpers.addError(clusters), region); + return rcb(); + } + + if (!clusters.data.length) { + helpers.addResult(results, 0, 'No OKE clusters found', region); + return rcb(); + } + + clusters.data.forEach(cluster => { + if (cluster.lifecycleState && cluster.lifecycleState === 'DELETED') return; + + let currentEncryptionLevel =1; //default + + if (cluster.kmsKeyId) { + currentEncryptionLevel = helpers.getProtectionLevel(keysObj[cluster.kmsKeyId], helpers.PROTECTION_LEVELS); + } + + let currentEncryptionLevelStr = helpers.PROTECTION_LEVELS[currentEncryptionLevel]; + + if (currentEncryptionLevel >= desiredEncryptionLevel) { + helpers.addResult(results, 0, + `OKE cluster (${cluster.name}) has secret encryption level ${currentEncryptionLevelStr} which is greater than or equal to ${desiredEncryptionLevelStr}`, region, cluster.id); + } else { + helpers.addResult(results, 2, + `OKE cluster (${cluster.name}) has secret encryption level ${currentEncryptionLevelStr} which is less than ${desiredEncryptionLevelStr}`, region, cluster.id); + } + }); + } + + rcb(); + }, function() { + cb(); + }); + } + ], function() { + // Global checking goes here + callback(null, results, source); + }); + } +}; + + diff --git a/plugins/oracle/oke/okeSecretsEncrypted.spec.js b/plugins/oracle/oke/okeSecretsEncrypted.spec.js new file mode 100644 index 0000000000..2dbefe3b29 --- /dev/null +++ b/plugins/oracle/oke/okeSecretsEncrypted.spec.js @@ -0,0 +1,178 @@ +var expect = require('chai').expect; +var plugin = require('./okeSecretsEncrypted'); + +const getCluster = [ + { + "id": "cluster1", + "name": "cluster1", + "endpointConfig": { + "isPublicIpEnabled": true + }, + "endpoints": { + "kubernetes": null, + "publicEndpoint": "10.0.0.0:8080", + "privateEndpoint": null, + }, + }, + { + "id": "cluster1", + "name": "cluster1", + "endpointConfig": { + "isPublicIpEnabled": true + }, + "endpoints": { + "kubernetes": null, + "publicEndpoint": "10.0.0.0:8080", + "privateEndpoint": null, + }, + "kmsKeyId": 'key-1' + } +]; + +const createCache = (err, data) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + cluster: { + get: { + 'us-ashburn-1': { + err: err, + data: data + } + } + }, + vault: { + list: { + 'us-ashburn-1': { + data: [ + { + "compartmentId": "compartment-1", + "displayName": "vault-1", + "freeformTags": {}, + "id": "vault-1", + "lifecycleState": "ACTIVE", + }, + ] + } + } + }, + keys: { + list: { + 'us-ashburn-1': { + data: [ + { + "compartmentId": "compartment-1", + "definedTags": {}, + "displayName": "key-1", + "freeformTags": {}, + "id": "key-1", + "lifecycleState": "ENABLED", + "timeCreated": "2022-04-30T19:49:12.841Z", + "vaultId": "vault-1", + "protectionMode": "SOFTWARE", + "algorithm": "AES" + } + ], + + } + } + } + } +}; + +describe('okeSecretsEncrypted', function () { + describe('run', function () { + it('should give unknown result if a cluster error occurs', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for OKE clusters') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['error'], + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if no oke clusters are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No OKE clusters found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + + it('should give failing result if oke cluster does not have desired encryption level', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('which is less') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [getCluster[0]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if oke cluster has desired encryption level', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('which is greater than or equal to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [getCluster[1]] + ); + + plugin.run(cache, {}, callback); + }); + }); +}); \ No newline at end of file From ffc0846b245f53f8c548d9b4855a34451984a9d6 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sun, 1 May 2022 02:27:48 +0500 Subject: [PATCH 094/350] Oracle - Bucket CMK Encryption Plugin --- collectors/oracle/collector.js | 20 +- exports.js | 1 + helpers/oracle/functions.js | 21 ++- helpers/oracle/index.js | 3 +- helpers/oracle/regions.js | 4 +- other_modules/oci/index.js | 6 + other_modules/oci/services.json | 24 +++ .../oracle/objectstore/bucketCMKEncryption.js | 89 +++++++++ .../objectstore/bucketCMKEncryption.spec.js | 172 ++++++++++++++++++ 9 files changed, 336 insertions(+), 4 deletions(-) create mode 100644 plugins/oracle/objectstore/bucketCMKEncryption.js create mode 100644 plugins/oracle/objectstore/bucketCMKEncryption.spec.js diff --git a/collectors/oracle/collector.js b/collectors/oracle/collector.js index 59441f94ab..58d1ec419c 100644 --- a/collectors/oracle/collector.js +++ b/collectors/oracle/collector.js @@ -245,7 +245,15 @@ var calls = { filterKey: ['compartmentId'], filterValue: ['compartmentId'], } - } + }, + vault: { + list: { + api: 'kms', + filterKey: ['compartmentId'], + filterValue: ['compartmentId'], + restVersion: '/20180608', + } + }, }; // Important Note: All relies must be passed in an array format [] @@ -381,6 +389,16 @@ var postcalls = { filterConfig: [true, false], } }, + keys: { + list: { + api: 'kms', + reliesOnService: ['vault'], + reliesOnCall: ['list'], + filterKey: ['compartmentId', 'managementEndpoint'], + filterValue: ['compartmentId', 'managementEndpoint'], + restVersion: '/20180608' + } + }, }; // Important Note: All relies must be passed in an array format [] diff --git a/exports.js b/exports.js index 1c49f708a1..8daa1fa12d 100644 --- a/exports.js +++ b/exports.js @@ -838,6 +838,7 @@ module.exports = { 'preAuthRequestsExpiry' : require(__dirname + '/plugins/oracle/objectstore/preAuthRequestsExpiry.js'), 'preAuthRequestsAccess' : require(__dirname + '/plugins/oracle/objectstore/preAuthRequestsAccess.js'), 'objectPolicyProtection' : require(__dirname + '/plugins/oracle/objectstore/objectPolicyProtection.js'), + 'bucketCMKEncryption' : require(__dirname + '/plugins/oracle/objectstore/bucketCMKEncryption.js'), 'nfsPublicAccess' : require(__dirname + '/plugins/oracle/filestorage/nfsPublicAccess.js'), 'nfsPolicyProtection' : require(__dirname + '/plugins/oracle/filestorage/nfsPolicyProtection.js'), diff --git a/helpers/oracle/functions.js b/helpers/oracle/functions.js index feaff068ad..5ca4ff35f5 100644 --- a/helpers/oracle/functions.js +++ b/helpers/oracle/functions.js @@ -1,4 +1,5 @@ var shared = require(__dirname + '/../shared.js'); +var async = require('async'); var ipProtocol = { "tcp" : { @@ -341,6 +342,22 @@ function normalizePolicyStatement(policyStatement) { return statementObj; } +function getProtectionLevel(cryptographickey, encryptionLevels) { + if (cryptographickey && cryptographickey.protectionMode) { + if (cryptographickey.protectionMode.toUpperCase() == 'SOFTWARE') return encryptionLevels.indexOf('cloudcmek'); + else if (cryptographickey.protectionMode.toUpperCase() == 'HSM') return encryptionLevels.indexOf('cloudhsm'); + } + + return encryptionLevels.indexOf('unspecified'); +} + +function listToObj(resultObj, listData, onKey) { + async.each(listData, function (entry, cb) { + if (entry[onKey]) resultObj[entry[onKey]] = entry; + cb(); + }); +} + function testStatement(statementObj, resourceTypes, policyAdmins, verbs) { let whereNames = ['request.user.id', 'request.user.name', 'request.groups.id', 'request.group.name', 'request.networkSource.name', 'target.user.name', 'request.instance.compartment.id', 'request.ad']; @@ -378,5 +395,7 @@ module.exports = { findOpenPortsAll: findOpenPortsAll, checkRegionSubscription: checkRegionSubscription, normalizePolicyStatement: normalizePolicyStatement, - testStatement: testStatement + testStatement: testStatement, + getProtectionLevel: getProtectionLevel, + listToObj: listToObj }; diff --git a/helpers/oracle/index.js b/helpers/oracle/index.js index b6b67a2971..32ef6788df 100644 --- a/helpers/oracle/index.js +++ b/helpers/oracle/index.js @@ -134,7 +134,8 @@ function OracleExecutor(OracleConfig) { var helpers = { regions: regions, OracleExecutor: OracleExecutor, - MAX_REGIONS_AT_A_TIME: 6 + MAX_REGIONS_AT_A_TIME: 6, + PROTECTION_LEVELS: ['unspecified', 'default', 'cloudcmek', 'cloudhsm'], }; for (var s in shared) helpers[s] = shared[s]; diff --git a/helpers/oracle/regions.js b/helpers/oracle/regions.js index 88fbc9e1ed..a38be45109 100644 --- a/helpers/oracle/regions.js +++ b/helpers/oracle/regions.js @@ -76,5 +76,7 @@ module.exports = { namespace: regions, apiKey: ['default'], authToken: ['default'], - customerSecretKey: ['default'] + customerSecretKey: ['default'], + vault: regions, + keys: regions }; \ No newline at end of file diff --git a/other_modules/oci/index.js b/other_modules/oci/index.js index 3571db3aa0..6a174bc668 100644 --- a/other_modules/oci/index.js +++ b/other_modules/oci/index.js @@ -8,6 +8,12 @@ module.exports = function(api, service, key, OracleConfig, parameters, callback) var localService = services[api][service][key]; + //replacing endpoint with managementRndpoint value from vault for keys api + if (api === 'kms' && localService.path === 'keys') { + localService.endpoint = parameters.managementEndpoint.replace('https://', ''); + delete parameters['managementEndpoint']; + } + var suffix = ''; if (localService.encodedGet) { suffix += ('/' + encodeURIComponent(parameters[localService.encodedGet])); diff --git a/other_modules/oci/services.json b/other_modules/oci/services.json index 5e8f6d7606..8faa9b55a2 100644 --- a/other_modules/oci/services.json +++ b/other_modules/oci/services.json @@ -380,6 +380,30 @@ } } }, + "kms": { + "vault": { + "list": { + "allowedQueryStrings": [ + "compartmentId", "page", "limit" + ], + "method": "GET", + "path": "vaults", + "endpoint": "kms.{{region}}.oraclecloud.com" + } + }, + + "keys": { + "list": { + "allowedQueryStrings": [ + "compartmentId", "page", "limit" + ], + "method": "GET", + "path": "keys", + "endpoint": "{{managementEndpoint}}" + } + } + }, + "loadBalance": { "loadBalancer": { "list": { diff --git a/plugins/oracle/objectstore/bucketCMKEncryption.js b/plugins/oracle/objectstore/bucketCMKEncryption.js new file mode 100644 index 0000000000..daa486bf49 --- /dev/null +++ b/plugins/oracle/objectstore/bucketCMKEncryption.js @@ -0,0 +1,89 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Bucket CMK Encryption', + category: 'Object Store', + domain: 'Storage', + description: 'Ensure that Oracle Object Store buckets have encryption enabled using desired protection level.', + more_info: 'By default, all object store buckets are encrypted using an Oracle-managed master encryption key. To have better control over how your object store buckets are encrypted, you can use Customer-Managed Keys (CMKs).', + recommended_action: 'Ensure that all object store buckets have desired encryption level.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Object/Tasks/encryption.htm', + apis: ['namespace:get', 'bucket:list', 'bucket:get', 'vault:list', 'keys:list'], + settings: { + bucket_encryption_level: { + name: 'Bucket Encryption Level', + description: 'Desired protection level for Object store buckets. default: oracle-managed, cloudcmek: customer managed encryption keys, ' + + 'cloudhsm: customer managed HSM encryption key, external: imported or externally managed key', + regex: '^(default|cloudcmek|cloudhsm)$', + default: 'cloudcmek' + } + }, + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + var keysObj = {}; + + let desiredEncryptionLevelStr = settings.bucket_encryption_level || this.settings.bucket_encryption_level.default; + var desiredEncryptionLevel = helpers.PROTECTION_LEVELS.indexOf(desiredEncryptionLevelStr); + + async.series([ + function(cb) { + async.each(regions.keys, function(region, rcb) { + let keys = helpers.addSource( + cache, source, ['keys', 'list', region]); + if (keys && keys.data && keys.data.length) helpers.listToObj(keysObj, keys.data, 'id'); + rcb(); + }, function() { + cb(); + }); + }, + function(cb) { + async.each(regions.bucket, function(region, rcb) { + if (helpers.checkRegionSubscription(cache, source, results, region)) { + var getBucket = helpers.addSource(cache, source, + ['bucket', 'get', region]); + + if (!getBucket) return rcb(); + + if (getBucket.err || !getBucket.data) { + helpers.addResult(results, 3, + 'Unable to query for object store bucket details: ' + helpers.addError(getBucket), region); + } else if (!getBucket.data.length) { + helpers.addResult(results, 0, 'No object store bucket details to check', region); + } else { + + getBucket.data.forEach(function(bucket) { + + let currentEncryptionLevel =1; //default + + if (bucket.kmsKeyId) { + currentEncryptionLevel = helpers.getProtectionLevel(keysObj[bucket.kmsKeyId], helpers.PROTECTION_LEVELS); + } + + let currentEncryptionLevelStr = helpers.PROTECTION_LEVELS[currentEncryptionLevel]; + + if (currentEncryptionLevel >= desiredEncryptionLevel) { + helpers.addResult(results, 0, + `Object store bucket (${bucket.name}) has encryption level ${currentEncryptionLevelStr} which is greater than or equal to ${desiredEncryptionLevelStr}`, region, bucket.id); + } else { + helpers.addResult(results, 2, + `Object store bucket (${bucket.name}) has encryption level ${currentEncryptionLevelStr} which is less than ${desiredEncryptionLevelStr}`, region, bucket.id); + } + }); + } + } + rcb(); + }, function() { + cb(); + }); + } + ], function() { + // Global checking goes here + callback(null, results, source); + }); + } +}; + diff --git a/plugins/oracle/objectstore/bucketCMKEncryption.spec.js b/plugins/oracle/objectstore/bucketCMKEncryption.spec.js new file mode 100644 index 0000000000..c96a14bd8d --- /dev/null +++ b/plugins/oracle/objectstore/bucketCMKEncryption.spec.js @@ -0,0 +1,172 @@ +var expect = require('chai').expect; +var plugin = require('./bucketCMKEncryption'); + +const getBucket = [ + { + "namespace": 'ns-1', + "name": 'my-bucket', + "id": 'ocid1.bucket.oc1.iad.111111111111111122222222222222222233333333333333333', + "compartmentId": 'ocid1.tenancy.oc1..11111111111111111222222222222222222333333333333333', + "createdBy": 'ocid1.user.oc1..11111111111111112222222222222223333333333333333', + "timeCreated": '2021-04-28T13:26:51.917Z', + "publicAccessType": 'NoPublicAccess', + }, + { + "namespace": 'ns-1', + "name": 'akhtar-bucket', + "id": 'ocid1.bucket.oc1.iad.111111111111111122222222222222222233333333333333333', + "compartmentId": 'ocid1.tenancy.oc1..11111111111111111222222222222222222333333333333333', + "createdBy": 'ocid1.user.oc1..11111111111111112222222222222223333333333333333', + "timeCreated": '2021-04-28T13:26:51.917Z', + "publicAccessType": 'ObjectRead', + "kmsKeyId": 'key-1' + } +]; + +const createCache = (err, data) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + bucket: { + get: { + 'us-ashburn-1': { + err: err, + data: data + } + } + }, + vault: { + list: { + 'us-ashburn-1': { + data: [ + { + "compartmentId": "compartment-1", + "displayName": "vault-1", + "freeformTags": {}, + "id": "vault-1", + "lifecycleState": "ACTIVE", + }, + ] + } + } + }, + keys: { + list: { + 'us-ashburn-1': { + data: [ + { + "compartmentId": "compartment-1", + "definedTags": {}, + "displayName": "key-1", + "freeformTags": {}, + "id": "key-1", + "lifecycleState": "ENABLED", + "timeCreated": "2022-04-30T19:49:12.841Z", + "vaultId": "vault-1", + "protectionMode": "SOFTWARE", + "algorithm": "AES" + } + ], + + } + } + } + } +}; + +describe('bucketCMKEncryption', function () { + describe('run', function () { + it('should give unknown result if unable to query for object store bucket details', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for object store bucket details') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['error'], + undefined + + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if no object store buckets', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No object store bucket details to check') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if bucket does not have desired encryption level', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('which is less') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [getBucket[0]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if bucket has desired encryption level', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('which is greater than or equal to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [getBucket[1]] + ); + + plugin.run(cache, {}, callback); + }); + }); +}); \ No newline at end of file From 26188f694644841f9855136de648f52d26122e10 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Mon, 2 May 2022 00:55:15 +0500 Subject: [PATCH 095/350] Updated test cases --- .../azure/keyvaults/cmkCreationForAppTier.js | 11 +- .../keyvaults/cmkCreationForAppTier.spec.js | 107 +++++++++--------- 2 files changed, 59 insertions(+), 59 deletions(-) diff --git a/plugins/azure/keyvaults/cmkCreationForAppTier.js b/plugins/azure/keyvaults/cmkCreationForAppTier.js index 778640a478..e51e0b4972 100644 --- a/plugins/azure/keyvaults/cmkCreationForAppTier.js +++ b/plugins/azure/keyvaults/cmkCreationForAppTier.js @@ -14,9 +14,8 @@ module.exports = { settings: { app_tier_tag_sets: { name: 'App Tier Tag Sets', - description: 'A string of allowed tag set objects to use for the CMKs creation for App Tier', - regex: '^.*$s', - default: '' + description: 'An object of allowed tag set objects to use for the CMKs creation for App Tier', + default: {} } }, @@ -59,7 +58,7 @@ module.exports = { if (key.tags) { const tags = key.tags; - const allowedTagSets = config.app_tier_tag_sets.length ? JSON.parse(config.app_tier_tag_sets) : {}; + const allowedTagSets = config.app_tier_tag_sets; const result = _.pick(tags, (v, k) => _.isEqual(allowedTagSets[k], v)); if (Object.entries(result).length) { @@ -67,11 +66,11 @@ module.exports = { 'CMK Creation for App Tier is enabled', location, keyId); } else { helpers.addResult(results, 2, - 'CMK Creation for App Tier is not enabled', location, keyId); + 'CMK Creation for App Tier is disabled', location, keyId); } } else { helpers.addResult(results, 2, - 'CMK Creation for App Tier is not enabled', location, keyId); + 'CMK Creation for App Tier is disabled', location, keyId); } }); } diff --git a/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js b/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js index d35c5bdb23..941bde2d62 100644 --- a/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js +++ b/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js @@ -28,55 +28,28 @@ const listVaults = [ const getKeys = [ { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": true, - "exp": null, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] + "kid": "https://testvault.vault.azure.net/keys/test", + "attributes": { + "enabled": true, + "exp": null, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": { + "hello": "world" } }, { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": true, - "exp": 1635448252, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] - } - }, - { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": false, - "exp": 1635448252, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] - } + "kid": "https://testvault.vault.azure.net/keys/test", + "attributes": { + "enabled": true, + "exp": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} } ]; @@ -90,7 +63,11 @@ const createCache = (err, list, keys) => { } }, getKeys: { - 'eastus': keys + 'eastus': { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: keys + } + } } } } @@ -122,28 +99,52 @@ describe('cmkCreationForAppTier', function() { auth.run(createCache(null, null, {}), {}, callback); }); - it('should give passing result if expiration is set on keys', function(done) { + it('should give passing result if no key vault keys 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('Expiry date is set for the secret'); + expect(results[0].message).to.include('No Key Vault keys found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], []), {}, callback); + }); + + it('should give unkown result if Unable to query for Key Vaults keys', 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 Key Vault keys'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listVaults[1]], getKeys[1]), {}, callback); + auth.run(createCache(null, [listVaults[0]], null), {}, callback); }); - it('should give passing result if key is disabled', function(done) { + it('should give passing result if CMK Creation for App Tier is enabled', 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('The secret is disabled'); + expect(results[0].message).to.include('CMK Creation for App Tier is enabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[1]], [getKeys[0]]), { app_tier_tag_sets: { hello: 'world' } }, callback); + }); + + it('should give failing result if CMK Creation for App Tier is disabled', 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('CMK Creation for App Tier is disabled'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listVaults[2]], getKeys[2]), {}, callback); + auth.run(createCache(null, [listVaults[1]], [getKeys[0]]), {}, callback); }) }) }); From 34c4cf42654db44f53a3482154f5734d504b9b77 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Mon, 2 May 2022 00:57:51 +0500 Subject: [PATCH 096/350] Updated description --- plugins/azure/keyvaults/cmkCreationForAppTier.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/keyvaults/cmkCreationForAppTier.js b/plugins/azure/keyvaults/cmkCreationForAppTier.js index e51e0b4972..c6e23d44ae 100644 --- a/plugins/azure/keyvaults/cmkCreationForAppTier.js +++ b/plugins/azure/keyvaults/cmkCreationForAppTier.js @@ -14,7 +14,7 @@ module.exports = { settings: { app_tier_tag_sets: { name: 'App Tier Tag Sets', - description: 'An object of allowed tag set objects to use for the CMKs creation for App Tier', + description: 'An object of allowed tag set key value pairs to use for the CMKs creation for App Tier', default: {} } }, From 1080c934e6d30d29c949bbcf49d2fe7466ac9858 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Mon, 2 May 2022 01:22:04 +0500 Subject: [PATCH 097/350] Updated plugin and tests --- exports.js | 2 +- .../checkEncryptionKeysExpiry.spec.js | 154 ------------------ ...xpiry.js => cmkCreationForDatabaseTier.js} | 43 +++-- .../cmkCreationForDatabaseTier.spec.js | 150 +++++++++++++++++ 4 files changed, 180 insertions(+), 169 deletions(-) delete mode 100644 plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js rename plugins/azure/keyvaults/{checkEncryptionKeysExpiry.js => cmkCreationForDatabaseTier.js} (52%) create mode 100644 plugins/azure/keyvaults/cmkCreationForDatabaseTier.spec.js diff --git a/exports.js b/exports.js index 2ff7942db0..6b7621f385 100644 --- a/exports.js +++ b/exports.js @@ -755,7 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), - 'checkEncryptionKeysExpiry' : require(__dirname + '/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js'), + 'cmkCreationForDatabaseTier' : require(__dirname + '/plugins/azure/keyvaults/cmkCreationForDatabaseTier.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js b/plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js deleted file mode 100644 index a174d19bd8..0000000000 --- a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js +++ /dev/null @@ -1,154 +0,0 @@ -var expect = require('chai').expect; -var auth = require('./checkEncryptionKeysExpiry'); - -const listKeyVaults = [ - { - id: '/subscriptions/dce7d7as-ebf6-437f-a3b0-28fc0d22111e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/nauman-test', - name: 'nauman-test', - type: 'Microsoft.KeyVault/vaults', - location: 'eastus', - tags: { owner: 'kubernetes' }, - sku: { family: 'A', name: 'Standard' }, - tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', - accessPolicies: [ - { - tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', - objectId: 'b4062000-c33b-448b-817e-fa0f17bef4b9', - permissions: { - keys: ['Get', 'List'], - secrets: ['Get', 'List'], - certificates: ['Get', 'List'] - } - } - ], - enableSoftDelete: true, - softDeleteRetentionInDays: 7, - enableRbacAuthorization: false, - vaultUri: 'https://nauman-test.vault.azure.net/', - provisioningState: 'Succeeded' - } - ]; - - const getKeys = [ - { - "attributes": { - "created": "2022-04-10T17:57:43+00:00", - "enabled": true, - "expires": null, - "notBefore": null, - "recoveryLevel": "CustomizedRecoverable+Purgeable", - "updated": "2022-04-10T17:57:43+00:00" - }, - "kid": "https://nauman-test.vault.azure.net/keys/nauman-test", - "managed": null, - "name": "nauman-test", - "tags": { - "hello": "world" - } - }, - { - "attributes": { - "created": "2022-04-10T17:57:43+00:00", - "enabled": true, - "expires": "2022-08-31T17:52:06+00:00", - "notBefore": null, - "recoveryLevel": "CustomizedRecoverable+Purgeable", - "updated": "2022-04-10T17:57:43+00:00" - }, - "kid": "https://nauman-test.vault.azure.net/keys/nauman-test", - "managed": null, - "name": "nauman-test", - "tags": { - "hello": "world" - } - }, - { - "attributes": { - "created": "2022-04-10T17:57:43+00:00", - "enabled": true, - "expires": "2022-04-01T17:52:06+00:00", - "notBefore": null, - "recoveryLevel": "CustomizedRecoverable+Purgeable", - "updated": "2022-04-10T17:57:43+00:00" - }, - "kid": "https://nauman-test.vault.azure.net/keys/nauman-test", - "managed": null, - "name": "nauman-test", - "tags": { - "hello": "world" - } - } -]; - -const createCache = (err, list, keys) => { - return { - vaults: { - list: { - 'eastus': { - err: err, - data: list - } - }, - getKeys: { - 'eastus': { - '/subscriptions/dce7d7as-ebf6-437f-a3b0-28fc0d22111e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/nauman-test': { - err: err, - data: keys - } - } - } - } - } -}; - -describe('checkEncryptionKeysExpiry', function() { - describe('run', function() { - it('should give passing result if no keys 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 Key Vaults found'); - expect(results[0].region).to.equal('eastus'); - done() - }; - - auth.run(createCache(null, [], {}), {}, callback); - }); - - it('should give failing result if expiration is not set on keys', 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('Key expiration is not enabled'); - expect(results[0].region).to.equal('eastus'); - done() - }; - - auth.run(createCache(null, [listKeyVaults[0]], [getKeys[0]]), {}, callback); - }); - - it('should give passing result if expiry date is not yet reached', 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('Key expiry date is not yet reached'); - expect(results[0].region).to.equal('eastus'); - done() - }; - - auth.run(createCache(null, listKeyVaults, [getKeys[1]]), {}, callback); - }); - - it('should give failing results if the key has reached its expiry date', 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('Key has reached its expiry date'); - expect(results[0].region).to.equal('eastus'); - done() - }; - - auth.run(createCache(null, listKeyVaults, [getKeys[2]]), {}, callback); - }); - }); -}); diff --git a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js b/plugins/azure/keyvaults/cmkCreationForDatabaseTier.js similarity index 52% rename from plugins/azure/keyvaults/checkEncryptionKeysExpiry.js rename to plugins/azure/keyvaults/cmkCreationForDatabaseTier.js index 326b1a2ed4..7932bd3807 100644 --- a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js +++ b/plugins/azure/keyvaults/cmkCreationForDatabaseTier.js @@ -1,23 +1,34 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); +var _ = require('underscore'); module.exports = { - title: 'Key Expiration Enabled', + title: 'CMK Creation for Database Tier Enabled', category: 'Key Vaults', domain: 'Identity and Access Management', - description: 'Ensure that all Keys in Azure Key Vault have an expiry time set.', - more_info: 'Setting an expiry time on all keys forces key rotation and removes unused and forgotten keys from being used.', - recommended_action: 'Ensure each Key Vault has an expiry time set that provides for sufficient rotation.', - link: 'https://docs.microsoft.com/en-us/azure/key-vault/about-keys-secrets-and-certificates', + description: 'Ensures that a Customer-Managed Key (CMK) is created and configured for your Microsoft Azure database tier.', + more_info: 'Setting a CMK for database tier, you gain full control over who can use this key to access the database tier data, implementing the principle of least privilege on the encryption key ownership and usage.', + recommended_action: 'Ensure each Key Vault has a CMK created and configured for database tier.', + link: 'https://docs.microsoft.com/en-us/azure/azure-sql/database/transparent-data-encryption-byok-overview?view=azuresql', apis: ['vaults:list', 'vaults:getKeys'], + settings: { + database_tier_tag_sets: { + name: 'Database Tier Tag Sets', + description: 'An object of allowed tag set key value pairs to use for the CMKs creation for Database Tier', + default: {} + } + }, run: function(cache, settings, callback) { var results = []; var source = {}; var locations = helpers.locations(settings.govcloud); + var config = { + database_tier_tag_sets: settings.database_tier_tag_sets || this.settings.database_tier_tag_sets.default + }; async.each(locations.vaults, function(location, rcb) { - var vaults = helpers.addSource(cache, source, + var vaults = helpers.addSource(cache, source, ['vaults', 'list', location]); if (!vaults) return rcb(); @@ -32,7 +43,7 @@ module.exports = { return rcb(); } - vaults.data.forEach(function(vault){ + vaults.data.forEach((vault) => { var keys = helpers.addSource(cache, source, ['vaults', 'getKeys', location, vault.id]); @@ -41,21 +52,25 @@ module.exports = { } else if (!keys.data.length) { helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); } else { - keys.data.forEach(function(key) { + keys.data.forEach((key) => { var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); var keyId = `${vault.id}/keys/${keyName}`; - - if (key.attributes && key.attributes.expires) { - if (new Date(Date.now()) < new Date(key.attributes.expires)) { + + if (key.tags) { + const tags = key.tags; + const allowedTagSets = config.database_tier_tag_sets; + const result = _.pick(tags, (v, k) => _.isEqual(allowedTagSets[k], v)); + + if (Object.entries(result).length) { helpers.addResult(results, 0, - 'Key expiry date is not yet reached', location, keyId); + 'CMK Creation for Database Tier is enabled', location, keyId); } else { helpers.addResult(results, 2, - 'Key has reached its expiry date', location, keyId); + 'CMK Creation for Database Tier is disabled', location, keyId); } } else { helpers.addResult(results, 2, - 'Key expiration is not enabled', location, keyId); + 'CMK Creation for Database Tier is disabled', location, keyId); } }); } diff --git a/plugins/azure/keyvaults/cmkCreationForDatabaseTier.spec.js b/plugins/azure/keyvaults/cmkCreationForDatabaseTier.spec.js new file mode 100644 index 0000000000..117688be92 --- /dev/null +++ b/plugins/azure/keyvaults/cmkCreationForDatabaseTier.spec.js @@ -0,0 +1,150 @@ +var expect = require('chai').expect; +var auth = require('./cmkCreationForDatabaseTier'); + +const listVaults = [ + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + }, + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": { hello: 'world' }, + "sku": { + "family": "A", + "name": "Standard" + } + } +]; + +const getKeys = [ + { + "kid": "https://testvault.vault.azure.net/keys/test", + "attributes": { + "enabled": true, + "exp": null, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": { + "Owner": "AzSQLManager" + } + }, + { + "kid": "https://testvault.vault.azure.net/keys/test", + "attributes": { + "enabled": true, + "exp": 1635448252, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } +]; + +const createCache = (err, list, keys) => { + return { + vaults: { + list: { + 'eastus': { + err: err, + data: list + } + }, + getKeys: { + 'eastus': { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: keys + } + } + } + } + } +}; + +describe('cmkCreationForDatabaseTier', function() { + describe('run', function() { + it('should give passing result if no key vaults 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 Key Vaults found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [], {}), {}, callback); + }); + + it('should give unkown result if Unable to query for Key Vaults', 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 Key Vaults'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, null, {}), {}, callback); + }); + + it('should give passing result if no key vault keys 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 Key Vault keys found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], []), {}, callback); + }); + + it('should give unkown result if Unable to query for Key Vaults keys', 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 Key Vault keys'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], null), {}, callback); + }); + + it('should give passing result if CMK Creation for Database Tier is enabled', 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('CMK Creation for Database Tier is enabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[1]], [getKeys[0]]), { database_tier_tag_sets: { Owner: 'AzSQLManager' } }, callback); + }); + + it('should give failing result if CMK Creation for Database Tier is disabled', 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('CMK Creation for Database Tier is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[1]], [getKeys[0]]), {}, callback); + }) + }) +}); From ca20adeb3bd6554a708e2c470a98824601ecede4 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Mon, 2 May 2022 11:40:50 +0500 Subject: [PATCH 098/350] Updated plugin and specs --- collectors/azure/collector.js | 14 ++ exports.js | 2 +- .../keyvaults/allowedCertificateKeyTypes.js | 70 ------- .../allowedCertificateKeyTypes.spec.js | 160 -------------- .../rsaCertificateAllowedKeySizes.js | 85 ++++++++ .../rsaCertificateAllowedKeySizes.spec.js | 197 ++++++++++++++++++ 6 files changed, 297 insertions(+), 231 deletions(-) delete mode 100644 plugins/azure/keyvaults/allowedCertificateKeyTypes.js delete mode 100644 plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js create mode 100644 plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.js create mode 100644 plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.spec.js diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index c7fc096367..9b02413f7c 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -409,6 +409,12 @@ var postcalls = { properties: ['vaultUri'], url: '{vaultUri}secrets?api-version=7.0', vault: true + }, + getCertificates: { + reliesOnPath: 'vaults.list', + properties: ['vaultUri'], + url: '{vaultUri}certificates?api-version=7.3', + vault: true } }, databases: { @@ -484,6 +490,14 @@ var tertiarycalls = { properties: ['id'], url: 'https://management.azure.com/{id}/backupShortTermRetentionPolicies?api-version=2017-10-01-preview' } + }, + getCertificatePolicy: { + get: { + reliesOnPath: 'vaults.getCertificates', + properties: ['id'], + url: '{id}/policy?api-version=7.3', + vault: true + } } }; diff --git a/exports.js b/exports.js index 06dfdf7124..1ee2d64d8d 100644 --- a/exports.js +++ b/exports.js @@ -755,7 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), - 'allowedCertificateKeyTypes' : require(__dirname + '/plugins/azure/keyvaults/allowedCertificateKeyTypes.js'), + 'rsaCertificateAllowedKeySizes' : require(__dirname + '/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js deleted file mode 100644 index 6c6b294e60..0000000000 --- a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js +++ /dev/null @@ -1,70 +0,0 @@ -var async = require('async'); -var helpers = require('../../../helpers/azure'); - -module.exports = { - title: 'Allowed Certificates Key Types', - category: 'Key Vaults', - domain: 'Identity and Access Management', - description: 'Ensures that Microsoft Azure Key Vault SSL certificates are using the allowed key types.', - more_info: 'Having the right key type set for your Azure Key Vault SSL certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', - recommended_action: 'Ensure that Key Vault SSL certificates are using the allowed key types.', - link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/certificate-access-control', - apis: ['vaults:list', 'vaults:getKeys'], - - run: function(cache, settings, callback) { - var results = []; - var source = {}; - var locations = helpers.locations(settings.govcloud); - - async.each(locations.vaults, function(location, rcb) { - var vaults = helpers.addSource(cache, source, - ['vaults', 'list', location]); - - if (!vaults) return rcb(); - - if (vaults.err || !vaults.data) { - helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); - return rcb(); - } - - if (!vaults.data.length) { - helpers.addResult(results, 0, 'No Key Vaults found', location); - return rcb(); - } - - vaults.data.forEach((vault) => { - var keys = helpers.addSource(cache, source, - ['vaults', 'getKeys', location, vault.id]); - - if (!keys || keys.err || !keys.data) { - helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); - } else if (!keys.data.length) { - helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); - } else { - keys.data.forEach((key) => { - var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); - var keyId = `${vault.id}/keys/${keyName}`; - - if (key.attributes) { - let attributes = key.attributes; - if ((attributes.expires && attributes.expires !== null && attributes.expires !== '') || (attributes.exp && attributes.exp !== null && attributes.exp !== '')) { - helpers.addResult(results, 0, - 'Expiry date is set for the key', location, keyId); - } else { - helpers.addResult(results, 2, - 'Expiry date is not set for the key', location, keyId); - } - } else { - helpers.addResult(results, 2, - 'Expiry date is not set for the key', location, keyId); - } - }); - } - }); - - rcb(); - }, function() { - callback(null, results, source); - }); - } -}; diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js deleted file mode 100644 index 7d048cb2f5..0000000000 --- a/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js +++ /dev/null @@ -1,160 +0,0 @@ -var expect = require('chai').expect; -var auth = require('./secretExpirationEnabled'); - -const listVaults = [ - { - "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", - "name": "testvault", - "type": "Microsoft.KeyVault/vaults", - "location": "eastus", - "tags": {}, - "sku": { - "family": "A", - "name": "Standard" - } - }, - { - "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", - "name": "testvault", - "type": "Microsoft.KeyVault/vaults", - "location": "eastus", - "tags": {}, - "sku": { - "family": "A", - "name": "Standard" - } - }, - { - "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", - "name": "testvault", - "type": "Microsoft.KeyVault/vaults", - "location": "eastus", - "tags": {}, - "sku": { - "family": "A", - "name": "Standard" - } - } -]; - -const getKeys = [ - { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": true, - "exp": null, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] - } - }, - { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": true, - "exp": 1635448252, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] - } - }, - { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": false, - "exp": 1635448252, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] - } - } -]; - -const createCache = (err, list, get) => { - return { - vaults: { - list: { - 'eastus': { - err: err, - data: list - } - }, - getSecrets: { - 'eastus': get - } - } - } -}; - -describe('secretExpirationEnabled', function() { - describe('run', function() { - it('should give passing result if no secrets 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 Key Vaults found'); - expect(results[0].region).to.equal('eastus'); - done() - }; - - auth.run(createCache(null, [], {}), {}, callback); - }); - - it('should give failing result if expiration is not set on secrets', 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('Expiry date is not set for the secret'); - expect(results[0].region).to.equal('eastus'); - done() - }; - - auth.run(createCache(null, [listVaults[0]], getKeys[0]), {}, callback); - }); - - it('should give passing result if expiration is set on keys', 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('Expiry date is set for the secret'); - expect(results[0].region).to.equal('eastus'); - done() - }; - - auth.run(createCache(null, [listVaults[1]], getKeys[1]), {}, callback); - }); - - it('should give passing result if key is disabled', 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('The secret is disabled'); - expect(results[0].region).to.equal('eastus'); - done() - }; - - auth.run(createCache(null, [listVaults[2]], getKeys[2]), {}, callback); - }) - }) -}); diff --git a/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.js b/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.js new file mode 100644 index 0000000000..bef2c10000 --- /dev/null +++ b/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.js @@ -0,0 +1,85 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'RSA Certificate Allowed Key Size', + category: 'Key Vaults', + domain: 'Identity and Access Management', + description: 'Ensures that Microsoft Azure Key Vault RSA certificates are using the allowed key size.', + more_info: 'Having the right key type size for your Azure Key Vault RSA certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', + recommended_action: 'Ensure that Key Vault RSA certificates are using the allowed key types.', + link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/about-certificates', + apis: ['vaults:list', 'vaults:getCertificates', 'getCertificatePolicy:get'], + settings: { + rsa_certificate_key_size: { + name: 'RSA Certificate Allowed Key Size', + description: 'Key sizes supported for rsa certificates in Azure Key Vault', + regex: '^(2048|3072|4096)$', + default: '2048' + } + }, + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + var config = { + rsa_certificate_key_size: settings.rsa_certificate_key_size || this.settings.rsa_certificate_key_size, + }; + + async.each(locations.vaults, function(location, rcb) { + var vaults = helpers.addSource(cache, source, + ['vaults', 'list', location]); + + if (!vaults) return rcb(); + + if (vaults.err || !vaults.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); + return rcb(); + } + + if (!vaults.data.length) { + helpers.addResult(results, 0, 'No Key Vaults found', location); + return rcb(); + } + + vaults.data.forEach((vault) => { + var certificates = helpers.addSource(cache, source, + ['vaults', 'getCertificates', location, vault.id]); + + if (!certificates || certificates.err || !certificates.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault certificates: ' + helpers.addError(certificates), location, vault.id); + } else if (!certificates.data.length) { + helpers.addResult(results, 0, 'No Key Vault Certificates found', location, vault.id); + } else { + certificates.data.forEach((certificate) => { + var certificatePolicy = helpers.addSource(cache, source, + ['getCertificatePolicy', 'get', location, certificate.id]); + + if (!certificatePolicy || certificatePolicy.err || !certificatePolicy.data) { + helpers.addResult(results, 3, 'Unable to query for Certificate Policy: ' + helpers.addError(certificatePolicy), location, certificate.id); + } else { + const certificateKeys = certificatePolicy.data.key_props; + + if (certificateKeys && certificateKeys.kty) { + const allowedKeySize = new RegExp(config.rsa_certificate_key_size.regex); + + if (allowedKeySize.test(certificateKeys.key_size)) { + helpers.addResult(results, 0, 'RSA Certificate key size is within the Allowed Key Sizes: ' + certificateKeys.key_size, location, certificate.id); + } else { + helpers.addResult(results, 2, 'RSA Certificate key size is not within the Allowed Key Sizes: ' + certificateKeys.key_size, location, certificate.id); + } + } else { + helpers.addResult(results, 3, 'Unable to list key type for Key Vault Certificate: ' + helpers.addError(certificatePolicy), location, certificate.id); + } + } + }); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.spec.js b/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.spec.js new file mode 100644 index 0000000000..2567cb60ef --- /dev/null +++ b/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.spec.js @@ -0,0 +1,197 @@ +var expect = require('chai').expect; +var auth = require('./rsaCertificateAllowedKeySizes'); + +const listVaults = [ + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + } +]; + +const certificates = [ + { + id: 'https://testvault.vault.azure.net/certificates/test-cert', + x5t: 'wi16heNOLNuStvVprwu6rzs0_is', + attributes: [Object], + tags: {}, + subject: '' + } +]; + +const certificatePolicy = [ + { + id: 'https://testvault.vault.azure.net/certificates/test-cert/policy', + key_props: { exportable: true, kty: 'RSA', key_size: 2048, reuse_key: false }, + secret_props: { contentType: 'application/x-pkcs12' }, + x509_props: { + subject: 'CN=test.com', + sans: [Object], + ekus: [Array], + key_usage: [Array], + validity_months: 12, + basic_constraints: [Object] + }, + lifetime_actions: [ [Object] ], + issuer: { name: 'Self' }, + attributes: { enabled: true, created: 1649758944, updated: 1649758944 } + }, + { + id: 'https://testvault.vault.azure.net/certificates/test-cert/policy', + secret_props: { contentType: 'application/x-pkcs12' }, + x509_props: { + subject: 'CN=test.com', + sans: [Object], + ekus: [Array], + key_usage: [Array], + validity_months: 12, + basic_constraints: [Object] + }, + lifetime_actions: [ [Object] ], + issuer: { name: 'Self' }, + attributes: { enabled: true, created: 1649758944, updated: 1649758944 } + }, + { + id: 'https://testvault.vault.azure.net/certificates/test-cert/policy', + secret_props: { contentType: 'application/x-pkcs12' }, + key_props: { exportable: true, kty: 'ECC', key_size: 1098, reuse_key: false }, + x509_props: { + subject: 'CN=test.com', + sans: [Object], + ekus: [Array], + key_usage: [Array], + validity_months: 12, + basic_constraints: [Object] + }, + lifetime_actions: [ [Object] ], + issuer: { name: 'Self' }, + attributes: { enabled: true, created: 1649758944, updated: 1649758944 } + } +]; + +const createCache = (err, list, certs, getCertificatePolicy) => { + return { + vaults: { + list: { + 'eastus': { + err: err, + data: list + } + }, + getCertificates: { + 'eastus': certs + } + }, + getCertificatePolicy: { + get: { + 'eastus': getCertificatePolicy + } + } + } +}; + +describe('rsaCertificateKeySize', function() { + describe('run', function() { + it('should give passing result if no key vaults 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 Key Vaults found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [], {}, {}), {}, callback); + }); + + it('should give unkown result if Unable to query for Key Vaults', 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 Key Vaults'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, null, {}, {}), {}, callback); + }); + + it('should give passing result if no key vault certificates 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 Key Vault Certificates found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [] } }, {}), {}, callback); + }); + + it('should give unkown result if unable to query for Key Vault Certificates', 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 Key Vault certificates'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], null, {}), {}, callback); + }); + + it('should give unknown results if unable to query for certificate policy', 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 Certificate Policy'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [certificates] } }, {}), {}, callback); + }); + + it('should give unknown results if Unable to list key type for Key Vault Certificate', 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 list key type for Key Vault Certificate'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [certificates] } }, { data: [certificatePolicy[1]] } ), {}, callback); + }); + + it('should give passing result if certificate has allowed key type', 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('RSA Certificate key size is within the Allowed Key Sizes'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [certificates] } }, { data: { ...certificatePolicy[0] } } ), {}, callback); + }); + + it('should give failing result if certificate does not have allowed key type', 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('RSA Certificate key size is not within the Allowed Key Sizes'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [certificates] } }, { data: { ...certificatePolicy[2] } } ), {}, callback); + }); + }) +}); From e87e64e78b49cfde9c4baff1fd28ff6b645671e8 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Mon, 2 May 2022 21:41:03 +0500 Subject: [PATCH 099/350] Updated plugin and specs --- exports.js | 2 +- .../keyvaults/allowedCertificateKeyTypes.js | 70 ----------- .../keyvaults/manageAccessAndPermissions.js | 111 ++++++++++++++++++ ....js => manageAccessAndPermissions.spec.js} | 0 4 files changed, 112 insertions(+), 71 deletions(-) delete mode 100644 plugins/azure/keyvaults/allowedCertificateKeyTypes.js create mode 100644 plugins/azure/keyvaults/manageAccessAndPermissions.js rename plugins/azure/keyvaults/{allowedCertificateKeyTypes.spec.js => manageAccessAndPermissions.spec.js} (100%) diff --git a/exports.js b/exports.js index 06dfdf7124..fe2acb7335 100644 --- a/exports.js +++ b/exports.js @@ -755,7 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), - 'allowedCertificateKeyTypes' : require(__dirname + '/plugins/azure/keyvaults/allowedCertificateKeyTypes.js'), + 'manageAccessAndPermissions' : require(__dirname + '/plugins/azure/keyvaults/manageAccessAndPermissions.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js deleted file mode 100644 index 6c6b294e60..0000000000 --- a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js +++ /dev/null @@ -1,70 +0,0 @@ -var async = require('async'); -var helpers = require('../../../helpers/azure'); - -module.exports = { - title: 'Allowed Certificates Key Types', - category: 'Key Vaults', - domain: 'Identity and Access Management', - description: 'Ensures that Microsoft Azure Key Vault SSL certificates are using the allowed key types.', - more_info: 'Having the right key type set for your Azure Key Vault SSL certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', - recommended_action: 'Ensure that Key Vault SSL certificates are using the allowed key types.', - link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/certificate-access-control', - apis: ['vaults:list', 'vaults:getKeys'], - - run: function(cache, settings, callback) { - var results = []; - var source = {}; - var locations = helpers.locations(settings.govcloud); - - async.each(locations.vaults, function(location, rcb) { - var vaults = helpers.addSource(cache, source, - ['vaults', 'list', location]); - - if (!vaults) return rcb(); - - if (vaults.err || !vaults.data) { - helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); - return rcb(); - } - - if (!vaults.data.length) { - helpers.addResult(results, 0, 'No Key Vaults found', location); - return rcb(); - } - - vaults.data.forEach((vault) => { - var keys = helpers.addSource(cache, source, - ['vaults', 'getKeys', location, vault.id]); - - if (!keys || keys.err || !keys.data) { - helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); - } else if (!keys.data.length) { - helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); - } else { - keys.data.forEach((key) => { - var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); - var keyId = `${vault.id}/keys/${keyName}`; - - if (key.attributes) { - let attributes = key.attributes; - if ((attributes.expires && attributes.expires !== null && attributes.expires !== '') || (attributes.exp && attributes.exp !== null && attributes.exp !== '')) { - helpers.addResult(results, 0, - 'Expiry date is set for the key', location, keyId); - } else { - helpers.addResult(results, 2, - 'Expiry date is not set for the key', location, keyId); - } - } else { - helpers.addResult(results, 2, - 'Expiry date is not set for the key', location, keyId); - } - }); - } - }); - - rcb(); - }, function() { - callback(null, results, source); - }); - } -}; diff --git a/plugins/azure/keyvaults/manageAccessAndPermissions.js b/plugins/azure/keyvaults/manageAccessAndPermissions.js new file mode 100644 index 0000000000..0b79f6ab7c --- /dev/null +++ b/plugins/azure/keyvaults/manageAccessAndPermissions.js @@ -0,0 +1,111 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); +var _ = require('underscore'); + +module.exports = { + title: 'Manage Access and Permissions', + category: 'Key Vaults', + domain: 'Identity and Access Management', + description: 'Ensures that there is no Microsoft Azure user, group or application with full administrator privileges.', + more_info: 'Having the right key type set for your Azure Key Vault SSL certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', + recommended_action: 'Ensure that Key Vault SSL certificates are using the allowed key types.', + link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/certificate-access-control', + apis: ['vaults:list', 'vaults:getKeys'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.vaults, function(location, rcb) { + var vaults = helpers.addSource(cache, source, + ['vaults', 'list', location]); + + if (!vaults) return rcb(); + + if (vaults.err || !vaults.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); + return rcb(); + } + + if (!vaults.data.length) { + helpers.addResult(results, 0, 'No Key Vaults found', location); + return rcb(); + } + + const fullPermissions = { + 'certificates': [ + 'Get', + 'List', + 'Update', + 'Create', + 'Import', + 'Delete', + 'Recover', + 'Backup', + 'Restore', + 'ManageContacts', + 'ManageIssuers', + 'GetIssuers', + 'ListIssuers', + 'SetIssuers', + 'DeleteIssuers', + 'Purge' + ], + 'keys': [ + 'Get', + 'List', + 'Update', + 'Create', + 'Import', + 'Delete', + 'Recover', + 'Backup', + 'Restore', + 'Decrypt', + 'Encrypt', + 'UnwrapKey', + 'WrapKey', + 'Verify', + 'Sign', + 'Purge' + ], + 'secrets': [ + 'Get', + 'List', + 'Set', + 'Delete', + 'Recover', + 'Backup', + 'Restore', + 'Purge' + ] + }; + + vaults.data.forEach((vault) => { + let certPermissions, keysPermissions, secretsPermissions; + + vault.accessPolicies.forEach((policy) => { + certPermissions = _.difference(policy.certificates, fullPermissions.certificates); + keysPermissions = _.difference(policy.keys, fullPermissions.keys); + secretsPermissions = _.difference(policy.certificates, fullPermissions.certificates); + }); + console.log('certPermissions', certPermissions); + console.log('keysPermissions', keysPermissions); + console.log('secretsPermissions', secretsPermissions); + if (certPermissions.length === fullPermissions.certificates.length || keysPermissions.length === fullPermissions.keys.length + || secretsPermissions.length === fullPermissions.secrets.length) { + helpers.addResult(results, 2, + 'User/Group or Application has full access to the specified vault', location, vault.id); + } else { + helpers.addResult(results, 0, + 'No User/Group or Application has full access to the specified vault', location, vault.id); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js b/plugins/azure/keyvaults/manageAccessAndPermissions.spec.js similarity index 100% rename from plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js rename to plugins/azure/keyvaults/manageAccessAndPermissions.spec.js From d54f3ee43866c0fc1c0602b00d0f9819c7230f63 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Tue, 10 May 2022 05:34:20 +0500 Subject: [PATCH 100/350] Updated plugin and specs --- .../keyvaults/manageAccessAndPermissions.js | 33 ++- .../manageAccessAndPermissions.spec.js | 226 ++++++++++-------- 2 files changed, 149 insertions(+), 110 deletions(-) diff --git a/plugins/azure/keyvaults/manageAccessAndPermissions.js b/plugins/azure/keyvaults/manageAccessAndPermissions.js index 0b79f6ab7c..72ca856c1d 100644 --- a/plugins/azure/keyvaults/manageAccessAndPermissions.js +++ b/plugins/azure/keyvaults/manageAccessAndPermissions.js @@ -8,9 +8,9 @@ module.exports = { domain: 'Identity and Access Management', description: 'Ensures that there is no Microsoft Azure user, group or application with full administrator privileges.', more_info: 'Having the right key type set for your Azure Key Vault SSL certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', - recommended_action: 'Ensure that Key Vault SSL certificates are using the allowed key types.', - link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/certificate-access-control', - apis: ['vaults:list', 'vaults:getKeys'], + recommended_action: 'Ensure that no Microsoft Azure user, group or application is using administrator privileges.', + link: 'https://docs.microsoft.com/en-us/azure/key-vault/general/rbac-guide?tabs=azure-cli', + apis: ['vaults:list'], run: function(cache, settings, callback) { var results = []; @@ -79,22 +79,31 @@ module.exports = { 'Backup', 'Restore', 'Purge' + ], + 'storage': [ + 'get', + 'list', + 'delete', + 'set', + 'update', + 'regeneratekey', + 'setsas', + 'listsas', + 'getsas', + 'deletesas' ] }; vaults.data.forEach((vault) => { - let certPermissions, keysPermissions, secretsPermissions; + let policyFound = false; vault.accessPolicies.forEach((policy) => { - certPermissions = _.difference(policy.certificates, fullPermissions.certificates); - keysPermissions = _.difference(policy.keys, fullPermissions.keys); - secretsPermissions = _.difference(policy.certificates, fullPermissions.certificates); + if (_.isEqual(fullPermissions, policy.permissions)) { + policyFound = true; + } }); - console.log('certPermissions', certPermissions); - console.log('keysPermissions', keysPermissions); - console.log('secretsPermissions', secretsPermissions); - if (certPermissions.length === fullPermissions.certificates.length || keysPermissions.length === fullPermissions.keys.length - || secretsPermissions.length === fullPermissions.secrets.length) { + + if (policyFound) { helpers.addResult(results, 2, 'User/Group or Application has full access to the specified vault', location, vault.id); } else { diff --git a/plugins/azure/keyvaults/manageAccessAndPermissions.spec.js b/plugins/azure/keyvaults/manageAccessAndPermissions.spec.js index 7d048cb2f5..62f2af3ea8 100644 --- a/plugins/azure/keyvaults/manageAccessAndPermissions.spec.js +++ b/plugins/azure/keyvaults/manageAccessAndPermissions.spec.js @@ -1,93 +1,123 @@ var expect = require('chai').expect; -var auth = require('./secretExpirationEnabled'); +var auth = require('./manageAccessAndPermissions'); const listVaults = [ { - "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", - "name": "testvault", - "type": "Microsoft.KeyVault/vaults", - "location": "eastus", - "tags": {}, - "sku": { - "family": "A", - "name": "Standard" - } - }, - { - "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", - "name": "testvault", - "type": "Microsoft.KeyVault/vaults", - "location": "eastus", - "tags": {}, - "sku": { - "family": "A", - "name": "Standard" - } + id: '/subscriptions/dcsqwwww-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/test', + name: 'test', + type: 'Microsoft.KeyVault/vaults', + location: 'eastus', + tags: { owner: 'kubernetes' }, + sku: { family: 'A', name: 'Standard' }, + tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', + accessPolicies: [ + { + tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', + objectId: '123d1b11-52f8-4dfc-bf08-1b66fa2de1d5', + permissions: [Object] + }, + { + tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', + objectId: 'b4062000-c33b-448b-817e-fa0f17bef4b9', + permissions: [Object] + }, + { + tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', + objectId: '0ef24dfb-2712-44f2-98d2-2df7f946b338', + permissions: [Object] + } + ], + enabledForDeployment: true, + enabledForDiskEncryption: true, + enabledForTemplateDeployment: true, + enableSoftDelete: true, + softDeleteRetentionInDays: 7, + enableRbacAuthorization: false, + vaultUri: 'https://test.vault.azure.net/', + provisioningState: 'Succeeded' }, { - "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", - "name": "testvault", - "type": "Microsoft.KeyVault/vaults", - "location": "eastus", - "tags": {}, - "sku": { - "family": "A", - "name": "Standard" - } - } -]; - -const getKeys = [ - { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": true, - "exp": null, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] - } - }, - { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": true, - "exp": 1635448252, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] - } - }, - { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": false, - "exp": 1635448252, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] - } + id: '/subscriptions/dcsqwwww-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/test', + name: 'test', + type: 'Microsoft.KeyVault/vaults', + location: 'eastus', + tags: { owner: 'kubernetes' }, + sku: { family: 'A', name: 'Standard' }, + tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', + accessPolicies: [ + { + tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', + objectId: '123d1b11-52f8-4dfc-bf08-1b66fa2de1d5', + permissions: { + 'certificates': [ + 'Get', + 'List', + 'Update', + 'Create', + 'Import', + 'Delete', + 'Recover', + 'Backup', + 'Restore', + 'ManageContacts', + 'ManageIssuers', + 'GetIssuers', + 'ListIssuers', + 'SetIssuers', + 'DeleteIssuers', + 'Purge' + ], + 'keys': [ + 'Get', + 'List', + 'Update', + 'Create', + 'Import', + 'Delete', + 'Recover', + 'Backup', + 'Restore', + 'Decrypt', + 'Encrypt', + 'UnwrapKey', + 'WrapKey', + 'Verify', + 'Sign', + 'Purge' + ], + 'secrets': [ + 'Get', + 'List', + 'Set', + 'Delete', + 'Recover', + 'Backup', + 'Restore', + 'Purge' + ], + 'storage': [ + 'get', + 'list', + 'delete', + 'set', + 'update', + 'regeneratekey', + 'setsas', + 'listsas', + 'getsas', + 'deletesas' + ] + } + }, + ], + enabledForDeployment: true, + enabledForDiskEncryption: true, + enabledForTemplateDeployment: true, + enableSoftDelete: true, + softDeleteRetentionInDays: 7, + enableRbacAuthorization: false, + vaultUri: 'https://test.vault.azure.net/', + provisioningState: 'Succeeded' } ]; @@ -107,9 +137,9 @@ const createCache = (err, list, get) => { } }; -describe('secretExpirationEnabled', function() { +describe('manageAccessAndPermissions', function() { describe('run', function() { - it('should give passing result if no secrets found', function(done) { + it('should give passing result if no key vaults found', function(done) { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); @@ -118,43 +148,43 @@ describe('secretExpirationEnabled', function() { done() }; - auth.run(createCache(null, [], {}), {}, callback); + auth.run(createCache(null, [], {}, {}), {}, callback); }); - it('should give failing result if expiration is not set on secrets', function(done) { + it('should give unkown result if Unable to query for Key Vaults', 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('Expiry date is not set for the secret'); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('Unable to query for Key Vaults'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listVaults[0]], getKeys[0]), {}, callback); + auth.run(createCache(null, null, {}, {}), {}, callback); }); - it('should give passing result if expiration is set on keys', function(done) { + it('should give passing result if No User/Group or Application has full access to the vault', 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('Expiry date is set for the secret'); + expect(results[0].message).to.include('No User/Group or Application has full access to the specified vault'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listVaults[1]], getKeys[1]), {}, callback); + auth.run(createCache(null, [listVaults[0]]), {}, callback); }); - it('should give passing result if key is disabled', function(done) { + it('should give failing result if a User/Group or Application has full access to the specified vault', 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('The secret is disabled'); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('User/Group or Application has full access to the specified vault'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listVaults[2]], getKeys[2]), {}, callback); + auth.run(createCache(null, [listVaults[1]]), {}, callback); }) }) }); From 93b6c39fe3ab8c000cfbe8049c3818168badc74b Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Tue, 10 May 2022 07:06:32 +0500 Subject: [PATCH 101/350] Updated plugin and specs --- collectors/azure/collector.js | 32 +++- exports.js | 2 +- .../keyvaults/allowedCertificateKeyTypes.js | 70 ------- .../allowedCertificateKeyTypes.spec.js | 160 ---------------- .../keyvaults/sslCertificateAutoRenewal.js | 75 ++++++++ .../sslCertificateAutoRenewal.spec.js | 175 ++++++++++++++++++ 6 files changed, 274 insertions(+), 240 deletions(-) delete mode 100644 plugins/azure/keyvaults/allowedCertificateKeyTypes.js delete mode 100644 plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js create mode 100644 plugins/azure/keyvaults/sslCertificateAutoRenewal.js create mode 100644 plugins/azure/keyvaults/sslCertificateAutoRenewal.spec.js diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index c7fc096367..634dabec48 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -409,6 +409,12 @@ var postcalls = { properties: ['vaultUri'], url: '{vaultUri}secrets?api-version=7.0', vault: true + }, + getCertificates: { + reliesOnPath: 'vaults.list', + properties: ['vaultUri'], + url: '{vaultUri}certificates?api-version=7.3', + vault: true } }, databases: { @@ -484,6 +490,14 @@ var tertiarycalls = { properties: ['id'], url: 'https://management.azure.com/{id}/backupShortTermRetentionPolicies?api-version=2017-10-01-preview' } + }, + getCertificatePolicy: { + get: { + reliesOnPath: 'vaults.getCertificates', + properties: ['id'], + url: '{id}/policy?api-version=7.3', + vault: true + } } }; @@ -529,9 +543,9 @@ var collect = function(AzureConfig, settings, callback) { if (settings.gather) { return callback(null, calls, postcalls, tertiarycalls, specialcalls); } - + var helpers = require(__dirname + '/../../helpers/azure/auth.js'); - + // Login using the Azure config helpers.login(AzureConfig, function(loginErr, loginData) { if (loginErr) return callback(loginErr); @@ -556,7 +570,7 @@ var collect = function(AzureConfig, settings, callback) { subCallCb(); }); } - + async.eachOfLimit(calls, 10, function(callObj, service, callCb) { if (!collection[service]) collection[service] = {}; // Loop through sub-calls @@ -565,7 +579,7 @@ var collect = function(AzureConfig, settings, callback) { if (settings && settings.api_calls && settings.api_calls.indexOf([service, one].join(':')) === -1) return subCallCb(); - + if (!collection[service][one]) collection[service][one] = {}; processTopCall(collection[service][one], service, subCallObj, subCallCb); }, function() { @@ -633,7 +647,7 @@ var collect = function(AzureConfig, settings, callback) { subCallCb(); } } - + async.eachOfLimit(postcalls, 10, function(callObj, service, callCb) { if (!collection[service]) collection[service] = {}; // Loop through sub-calls @@ -641,7 +655,7 @@ var collect = function(AzureConfig, settings, callback) { if (settings && settings.api_calls && settings.api_calls.indexOf([service, one].join(':')) === -1) return subCallCb(); - + if (!collection[service][one]) collection[service][one] = {}; processTopCall(collection[service][one], service, subCallObj, subCallCb); }, function() { @@ -698,7 +712,7 @@ var collect = function(AzureConfig, settings, callback) { resourceDataCb(); }); } - + if (Array.isArray(resourceObj)) { async.eachLimit(resourceObj, 10, function(resourceData, resourceDataCb) { processResource(resourceData, resourceDataCb); @@ -734,7 +748,7 @@ var collect = function(AzureConfig, settings, callback) { if (settings && settings.api_calls && settings.api_calls.indexOf([service, one].join(':')) === -1) return subCallCb(); - + if (!collection[service][one]) collection[service][one] = {}; if (subCallObj.url) { processTopCall(collection[service][one], service, subCallObj, subCallCb); @@ -744,7 +758,7 @@ var collect = function(AzureConfig, settings, callback) { if (settings && settings.api_calls && settings.api_calls.indexOf([service, one, two].join(':')) === -1) return subCallCb(); - + if (!collection[service][one][two]) collection[service][one][two] = {}; processTopCall(collection[service][one][two], service, innerCallObj, innerCb); }, function() { diff --git a/exports.js b/exports.js index 06dfdf7124..3984b7b75f 100644 --- a/exports.js +++ b/exports.js @@ -755,7 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), - 'allowedCertificateKeyTypes' : require(__dirname + '/plugins/azure/keyvaults/allowedCertificateKeyTypes.js'), + 'sslCertificateAutoRenewal' : require(__dirname + '/plugins/azure/keyvaults/sslCertificateAutoRenewal.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js deleted file mode 100644 index 6c6b294e60..0000000000 --- a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js +++ /dev/null @@ -1,70 +0,0 @@ -var async = require('async'); -var helpers = require('../../../helpers/azure'); - -module.exports = { - title: 'Allowed Certificates Key Types', - category: 'Key Vaults', - domain: 'Identity and Access Management', - description: 'Ensures that Microsoft Azure Key Vault SSL certificates are using the allowed key types.', - more_info: 'Having the right key type set for your Azure Key Vault SSL certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', - recommended_action: 'Ensure that Key Vault SSL certificates are using the allowed key types.', - link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/certificate-access-control', - apis: ['vaults:list', 'vaults:getKeys'], - - run: function(cache, settings, callback) { - var results = []; - var source = {}; - var locations = helpers.locations(settings.govcloud); - - async.each(locations.vaults, function(location, rcb) { - var vaults = helpers.addSource(cache, source, - ['vaults', 'list', location]); - - if (!vaults) return rcb(); - - if (vaults.err || !vaults.data) { - helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); - return rcb(); - } - - if (!vaults.data.length) { - helpers.addResult(results, 0, 'No Key Vaults found', location); - return rcb(); - } - - vaults.data.forEach((vault) => { - var keys = helpers.addSource(cache, source, - ['vaults', 'getKeys', location, vault.id]); - - if (!keys || keys.err || !keys.data) { - helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); - } else if (!keys.data.length) { - helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); - } else { - keys.data.forEach((key) => { - var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); - var keyId = `${vault.id}/keys/${keyName}`; - - if (key.attributes) { - let attributes = key.attributes; - if ((attributes.expires && attributes.expires !== null && attributes.expires !== '') || (attributes.exp && attributes.exp !== null && attributes.exp !== '')) { - helpers.addResult(results, 0, - 'Expiry date is set for the key', location, keyId); - } else { - helpers.addResult(results, 2, - 'Expiry date is not set for the key', location, keyId); - } - } else { - helpers.addResult(results, 2, - 'Expiry date is not set for the key', location, keyId); - } - }); - } - }); - - rcb(); - }, function() { - callback(null, results, source); - }); - } -}; diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js deleted file mode 100644 index 7d048cb2f5..0000000000 --- a/plugins/azure/keyvaults/allowedCertificateKeyTypes.spec.js +++ /dev/null @@ -1,160 +0,0 @@ -var expect = require('chai').expect; -var auth = require('./secretExpirationEnabled'); - -const listVaults = [ - { - "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", - "name": "testvault", - "type": "Microsoft.KeyVault/vaults", - "location": "eastus", - "tags": {}, - "sku": { - "family": "A", - "name": "Standard" - } - }, - { - "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", - "name": "testvault", - "type": "Microsoft.KeyVault/vaults", - "location": "eastus", - "tags": {}, - "sku": { - "family": "A", - "name": "Standard" - } - }, - { - "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", - "name": "testvault", - "type": "Microsoft.KeyVault/vaults", - "location": "eastus", - "tags": {}, - "sku": { - "family": "A", - "name": "Standard" - } - } -]; - -const getKeys = [ - { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": true, - "exp": null, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] - } - }, - { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": true, - "exp": 1635448252, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] - } - }, - { - '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { - data: [ - { - "id": "https://testvault.vault.azure.net/secrets/mysecret", - "attributes": { - "enabled": false, - "exp": 1635448252, - "created": 1572289869, - "updated": 1572290380, - "recoveryLevel": "Recoverable+Purgeable" - }, - "tags": {} - } - ] - } - } -]; - -const createCache = (err, list, get) => { - return { - vaults: { - list: { - 'eastus': { - err: err, - data: list - } - }, - getSecrets: { - 'eastus': get - } - } - } -}; - -describe('secretExpirationEnabled', function() { - describe('run', function() { - it('should give passing result if no secrets 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 Key Vaults found'); - expect(results[0].region).to.equal('eastus'); - done() - }; - - auth.run(createCache(null, [], {}), {}, callback); - }); - - it('should give failing result if expiration is not set on secrets', 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('Expiry date is not set for the secret'); - expect(results[0].region).to.equal('eastus'); - done() - }; - - auth.run(createCache(null, [listVaults[0]], getKeys[0]), {}, callback); - }); - - it('should give passing result if expiration is set on keys', 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('Expiry date is set for the secret'); - expect(results[0].region).to.equal('eastus'); - done() - }; - - auth.run(createCache(null, [listVaults[1]], getKeys[1]), {}, callback); - }); - - it('should give passing result if key is disabled', 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('The secret is disabled'); - expect(results[0].region).to.equal('eastus'); - done() - }; - - auth.run(createCache(null, [listVaults[2]], getKeys[2]), {}, callback); - }) - }) -}); diff --git a/plugins/azure/keyvaults/sslCertificateAutoRenewal.js b/plugins/azure/keyvaults/sslCertificateAutoRenewal.js new file mode 100644 index 0000000000..f25f35409b --- /dev/null +++ b/plugins/azure/keyvaults/sslCertificateAutoRenewal.js @@ -0,0 +1,75 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'SSL Certificate Auto Renewal', + category: 'Key Vaults', + domain: 'Identity and Access Management', + description: 'Ensures that Microsoft Azure Key Vault SSL certificates auto renewal is enabled.', + more_info: 'Configure SSL certificates for auto renewal in order to prevent any application or service outage, credential leak, or process violation that can disrupt your business.', + recommended_action: 'Ensure that Key Vault SSL certificates are configured to have auto renewal enabled.', + link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/overview-renew-certificate', + apis: ['vaults:list', 'vaults:getCertificates', 'getCertificatePolicy:get'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.vaults, function(location, rcb) { + var vaults = helpers.addSource(cache, source, + ['vaults', 'list', location]); + + if (!vaults) return rcb(); + + if (vaults.err || !vaults.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); + return rcb(); + } + + if (!vaults.data.length) { + helpers.addResult(results, 0, 'No Key Vaults found', location); + return rcb(); + } + + vaults.data.forEach((vault) => { + var certificates = helpers.addSource(cache, source, + ['vaults', 'getCertificates', location, vault.id]); + + if (!certificates || certificates.err || !certificates.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault certificates: ' + helpers.addError(certificates), location, vault.id); + } else if (!certificates.data.length) { + helpers.addResult(results, 0, 'No Key Vault Certificates found', location, vault.id); + } else { + certificates.data.forEach((certificate) => { + var certificatePolicy = helpers.addSource(cache, source, + ['getCertificatePolicy', 'get', location, certificate.id]); + + if (!certificatePolicy || certificatePolicy.err || !certificatePolicy.data) { + helpers.addResult(results, 3, 'Unable to query for Certificate Policy: ' + helpers.addError(certificatePolicy), location, certificate.id); + } else { + let autoRenew = false; + const lifetimeActions = certificatePolicy.data.lifetime_actions; + + lifetimeActions.forEach(({ action }) => { + if (action.action_type.toLowerCase() === 'autorenew') { + autoRenew = true; + } + }); + + if (autoRenew) { + helpers.addResult(results, 0, 'SSL Certificate auto renewal is enabled', location, certificate.id); + } else { + helpers.addResult(results, 2, 'SSL Certificate auto renewal is not enabled', location, certificate.id); + } + } + }); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/keyvaults/sslCertificateAutoRenewal.spec.js b/plugins/azure/keyvaults/sslCertificateAutoRenewal.spec.js new file mode 100644 index 0000000000..c2f711636d --- /dev/null +++ b/plugins/azure/keyvaults/sslCertificateAutoRenewal.spec.js @@ -0,0 +1,175 @@ +var expect = require('chai').expect; +var auth = require('./sslCertificateAutoRenewal'); + +const listVaults = [ + { + "id": "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault", + "name": "testvault", + "type": "Microsoft.KeyVault/vaults", + "location": "eastus", + "tags": {}, + "sku": { + "family": "A", + "name": "Standard" + } + } +]; + +const certificates = [ + { + id: 'https://testvault.vault.azure.net/certificates/test-cert', + x5t: 'wi16heNOLNuStvVprwu6rzs0_is', + attributes: [Object], + tags: {}, + subject: '' + } +]; + +const certificatePolicy = [ + { + id: 'https://testvault.vault.azure.net/certificates/test-cert/policy', + secret_props: { contentType: 'application/x-pkcs12' }, + x509_props: { + subject: 'CN=test.com', + sans: [Object], + ekus: [Array], + key_usage: [Array], + validity_months: 12, + basic_constraints: [Object] + }, + lifetime_actions: [ { + trigger: { lifetime_percentage: 80 }, + action: { action_type: 'AutoRenew' } + } ], + issuer: { name: 'Self' }, + attributes: { enabled: true, created: 1649758944, updated: 1649758944 } + }, + { + id: 'https://testvault.vault.azure.net/certificates/test-cert/policy', + secret_props: { contentType: 'application/x-pkcs12' }, + key_props: { exportable: true, kty: 'ECC', key_size: 1098, reuse_key: false }, + x509_props: { + subject: 'CN=test.com', + sans: [Object], + ekus: [Array], + key_usage: [Array], + validity_months: 12, + basic_constraints: [Object] + }, + lifetime_actions: [ { + trigger: { lifetime_percentage: 80 }, + action: { action_type: 'EmailContacts' } + } ], + issuer: { name: 'Self' }, + attributes: { enabled: true, created: 1649758944, updated: 1649758944 } + } +]; + +const createCache = (err, list, certs, getCertificatePolicy) => { + return { + vaults: { + list: { + 'eastus': { + err: err, + data: list + } + }, + getCertificates: { + 'eastus': certs + } + }, + getCertificatePolicy: { + get: { + 'eastus': getCertificatePolicy + } + } + } +}; + +describe('sslCertificateAutoRenewal', function() { + describe('run', function() { + it('should give passing result if no key vaults 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 Key Vaults found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [], {}, {}), {}, callback); + }); + + it('should give unkown result if Unable to query for Key Vaults', 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 Key Vaults'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, null, {}, {}), {}, callback); + }); + + it('should give passing result if no key vault certificates 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 Key Vault Certificates found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [] } }, {}), {}, callback); + }); + + it('should give unkown result if unable to query for Key Vault Certificates', 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 Key Vault certificates'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], null, {}), {}, callback); + }); + + it('should give unknown results if unable to query for certificate policy', 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 Certificate Policy'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [certificates] } }, {}), {}, callback); + }); + + it('should give passing result if SSL Certificate auto renewal is enabled', 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('SSL Certificate auto renewal is enabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [certificates] } }, { data: { ...certificatePolicy[0] } } ), {}, callback); + }); + + it('should give failing result if SSL Certificate auto renewal is not enabled', 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('SSL Certificate auto renewal is not enabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [certificates] } }, { data: { ...certificatePolicy[1] } } ), {}, callback); + }); + }) +}); From 3033e130711215d482db5346987d8893ca22d658 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Tue, 10 May 2022 07:07:12 +0500 Subject: [PATCH 102/350] Updated spec --- plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.spec.js b/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.spec.js index 2567cb60ef..89bbec5e26 100644 --- a/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.spec.js +++ b/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.spec.js @@ -96,7 +96,7 @@ const createCache = (err, list, certs, getCertificatePolicy) => { } }; -describe('rsaCertificateKeySize', function() { +describe('rsaCertificateAllowedKeySizes', function() { describe('run', function() { it('should give passing result if no key vaults found', function(done) { const callback = (err, results) => { From dfb244249962cb1b1bf3c5cbf5f4399423894289 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Tue, 10 May 2022 07:18:05 +0500 Subject: [PATCH 103/350] Updated settings --- plugins/azure/keyvaults/cmkCreationForDatabaseTier.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/azure/keyvaults/cmkCreationForDatabaseTier.js b/plugins/azure/keyvaults/cmkCreationForDatabaseTier.js index 7932bd3807..b4e3849559 100644 --- a/plugins/azure/keyvaults/cmkCreationForDatabaseTier.js +++ b/plugins/azure/keyvaults/cmkCreationForDatabaseTier.js @@ -15,6 +15,8 @@ module.exports = { database_tier_tag_sets: { name: 'Database Tier Tag Sets', description: 'An object of allowed tag set key value pairs to use for the CMKs creation for Database Tier', + // eslint-disable-next-line no-useless-escape + regex: '/("?)\b(\w+)\1\s*:\s*("?)((?:\w+[-+*%])*?\w+)\b\3/g', default: {} } }, From 708d852405658e9d7bab27deb6020bc090e9ebc4 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Tue, 10 May 2022 07:18:54 +0500 Subject: [PATCH 104/350] Updated settings --- plugins/azure/keyvaults/cmkCreationForAppTier.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/azure/keyvaults/cmkCreationForAppTier.js b/plugins/azure/keyvaults/cmkCreationForAppTier.js index c6e23d44ae..4b831eed44 100644 --- a/plugins/azure/keyvaults/cmkCreationForAppTier.js +++ b/plugins/azure/keyvaults/cmkCreationForAppTier.js @@ -15,6 +15,8 @@ module.exports = { app_tier_tag_sets: { name: 'App Tier Tag Sets', description: 'An object of allowed tag set key value pairs to use for the CMKs creation for App Tier', + // eslint-disable-next-line no-useless-escape + regex: '/("?)\b(\w+)\1\s*:\s*("?)((?:\w+[-+*%])*?\w+)\b\3/g', default: {} } }, From e2571d0aa046a459ec65296b5dbc999ae5b0aa5e Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Thu, 12 May 2022 07:06:57 +0500 Subject: [PATCH 105/350] Added checkAllUsedServicesPlugin --- exports.js | 1 + helpers/aws/api.js | 4 + plugins/aws/iam/checkAllUsedServices.js | 267 +++++++++++++++++++ plugins/aws/iam/checkAllUsedServices.spec.js | 0 4 files changed, 272 insertions(+) create mode 100644 plugins/aws/iam/checkAllUsedServices.js create mode 100644 plugins/aws/iam/checkAllUsedServices.spec.js diff --git a/exports.js b/exports.js index 1c49f708a1..86898c2587 100644 --- a/exports.js +++ b/exports.js @@ -296,6 +296,7 @@ module.exports = { 'iamDbAuthenticationEnabled' : require(__dirname + '/plugins/aws/rds/iamDbAuthenticationEnabled.js'), 'iamSupportPolicy' : require(__dirname + '/plugins/aws/iam/iamSupportPolicy.js'), 'iamUserPresent' : require(__dirname + '/plugins/aws/iam/iamUserPresent.js'), + 'checkAllUsedServices' : require(__dirname + '/plugins/aws/iam/checkAllUsedServices.js'), 'iamUserInUse' : require(__dirname + '/plugins/aws/iam/iamUserInUse.js'), 'kinesisEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisEncrypted.js'), diff --git a/helpers/aws/api.js b/helpers/aws/api.js index 27d7904da9..80f12be4e7 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -244,6 +244,10 @@ var calls = { }, describeDeliveryChannels: { property: 'DeliveryChannels' + }, + getDiscoveredResourceCounts: { + property: 'DiscoveredResources', + paginate: 'NextToken' } }, CustomerProfiles: { diff --git a/plugins/aws/iam/checkAllUsedServices.js b/plugins/aws/iam/checkAllUsedServices.js new file mode 100644 index 0000000000..b835563e8a --- /dev/null +++ b/plugins/aws/iam/checkAllUsedServices.js @@ -0,0 +1,267 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +var managedAdminPolicy = 'arn:aws:iam::aws:policy/AdministratorAccess'; + +module.exports = { + title: 'IAM Role Policies', + category: 'IAM', + domain: 'Identity and Access management', + description: 'Ensures IAM role policies are properly scoped with specific permissions', + more_info: 'Policies attached to IAM roles should be scoped to least-privileged access and avoid the use of wildcards.', + link: 'https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html', + recommended_action: 'Ensure that all IAM roles are scoped to specific services and API calls.', + apis: ['IAM:listRoles', 'IAM:listRolePolicies', 'IAM:listAttachedRolePolicies', 'IAM:listPolicies', + 'IAM:getPolicy', 'IAM:getPolicyVersion', 'IAM:getRolePolicy', 'ConfigService:describeConfigurationRecorderStatus', 'ConfigService:getDiscoveredResourceCounts'], + settings: { + iam_role_policies_ignore_path: { + name: 'IAM Role Policies Ignore Path', + description: 'A comma-separated list indicating role paths which should PASS without checking', + regex: '^[0-9A-Za-z/._-]{3,512}$', + default: '' + }, + ignore_service_specific_wildcards: { + name: 'Ignore Service Specific Wildcards', + description: 'This allows enables you to allow attached policies (inline and managed) to use service specific wildcards in Action. ' + + 'Example: Consider a role has following inline policy' + + `{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "cognito-sync:*", + "cognito-identity:*" + ], + "Resource": [ + "*" + ] + } + ] + }` + + 'If ignore_service_specific_wildcards is true, a PASS result will be generated. ' + + 'If ignore_service_specific_wildcards is false, a FAIL result will be generated.', + regex: '^(true|false)$', + default: 'false' + }, + ignore_identity_federation_roles: { + name: 'Ignore Identity Federation Roles', + description: 'This setting allows you to skip IdP/SAML based roles ' + + 'i.e. if for a role, all trust relationship statements have "Action" either "sts:AssumeRoleWithWebIdentity" or "sts:AssumeRoleWithSAML" '+ + 'and value for this setting is set to true, a PASS results will be generated.', + regex: '^(true|false)$', + default: 'false' + }, + ignore_aws_managed_iam_policies: { + name: 'Ignore AWS-Managed IAM Policies', + description: 'If set to true, skip AWS-managed policies attached to the role with the exception of AWS-managed AdministratorAccess policy', + regex: '^(true|false)$', + default: 'false' + }, + ignore_customer_managed_iam_policies: { + name: 'Ignore Customer-Managed IAM Policies', + description: 'If set to true, skip customer-managed policies attached to the role', + regex: '^(true|false)$', + default: 'false' + } + }, + + run: function(cache, settings, callback) { + var config = { + iam_role_policies_ignore_path: settings.iam_role_policies_ignore_path || this.settings.iam_role_policies_ignore_path.default, + ignore_service_specific_wildcards: settings.ignore_service_specific_wildcards || this.settings.ignore_service_specific_wildcards.default, + ignore_identity_federation_roles: settings.ignore_identity_federation_roles || this.settings.ignore_identity_federation_roles.default, + ignore_aws_managed_iam_policies: settings.ignore_aws_managed_iam_policies || this.settings.ignore_aws_managed_iam_policies.default, + ignore_customer_managed_iam_policies: settings.ignore_customer_managed_iam_policies || this.settings.ignore_customer_managed_iam_policies.default + }; + + config.ignore_service_specific_wildcards = (config.ignore_service_specific_wildcards === 'true'); + config.ignore_identity_federation_roles = (config.ignore_identity_federation_roles === 'true'); + config.ignore_aws_managed_iam_policies = (config.ignore_aws_managed_iam_policies === 'true'); + config.ignore_customer_managed_iam_policies = (config.ignore_customer_managed_iam_policies === 'true'); + + var custom = helpers.isCustom(settings, this.settings); + + var results = []; + var source = {}; + + var region = helpers.defaultRegion(settings); + + var configSRecorderStatus = helpers.addSource(cache, source, + ['configservice', 'describeConfigurationRecorderStatus', region]); + + if (configSRecorderStatus.data[0].recording) { + helpers.addResult(results, 2, + 'Config Service Recording is not enabled' + helpers.addError(configSRecorderStatus)); + return callback(null, results, source); + } + + var discoveredResources = helpers.addSource(cache, source, + ['configservice', 'getDiscoveredResourceCounts', region]); + + if (discoveredResources.err || !discoveredResources.data) { + helpers.addResult(results, 3, + 'Unable to query for Config Resources: ' + helpers.addError(discoveredResources)); + return callback(null, results, source); + } + + var listRoles = helpers.addSource(cache, source, + ['iam', 'listRoles', region]); + + if (!listRoles) return callback(null, results, source); + + if (listRoles.err || !listRoles.data) { + helpers.addResult(results, 3, + 'Unable to query for IAM roles: ' + helpers.addError(listRoles)); + return callback(null, results, source); + } + + if (!listRoles.data.length) { + helpers.addResult(results, 0, 'No IAM roles found'); + return callback(null, results, source); + } + + async.each(listRoles.data, function(role, cb){ + if (!role.RoleName) return cb(); + + // Skip roles with user-defined paths + if (config.iam_role_policies_ignore_path && + config.iam_role_policies_ignore_path.length && + role.Path && + role.Path.indexOf(config.iam_role_policies_ignore_path) > -1) { + return cb(); + } + + if (config.ignore_identity_federation_roles && + helpers.hasFederatedUserRole(helpers.normalizePolicyDocument(role.AssumeRolePolicyDocument))) { + helpers.addResult(results, 0, + 'Role is federated user role', + 'global', role.Arn, custom); + return cb(); + } + + // Get managed policies attached to role + var listAttachedRolePolicies = helpers.addSource(cache, source, + ['iam', 'listAttachedRolePolicies', region, role.RoleName]); + + // Get inline policies attached to role + var listRolePolicies = helpers.addSource(cache, source, + ['iam', 'listRolePolicies', region, role.RoleName]); + + var getRolePolicy = helpers.addSource(cache, source, + ['iam', 'getRolePolicy', region, role.RoleName]); + + if (!listAttachedRolePolicies || listAttachedRolePolicies.err) { + helpers.addResult(results, 3, + 'Unable to query for IAM attached policy for role: ' + role.RoleName + ': ' + helpers.addError(listAttachedRolePolicies), 'global', role.Arn); + return cb(); + } + + if (!listRolePolicies || listRolePolicies.err) { + helpers.addResult(results, 3, + 'Unable to query for IAM role policy for role: ' + role.RoleName + ': ' + helpers.addError(listRolePolicies), 'global', role.Arn); + return cb(); + } + + var roleFailures = []; + + // See if role has admin managed policy + if (listAttachedRolePolicies.data && + listAttachedRolePolicies.data.AttachedPolicies) { + + for (var policy of listAttachedRolePolicies.data.AttachedPolicies) { + if (policy.PolicyArn === managedAdminPolicy) { + roleFailures.push('Role has managed AdministratorAccess policy'); + break; + } + + if (config.ignore_aws_managed_iam_policies && /^arn:aws:iam::aws:.*/.test(policy.PolicyArn)) continue; + + if (config.ignore_customer_managed_iam_policies && /^arn:aws:iam::[0-9]{12}:.*/.test(policy.PolicyArn)) continue; + + var getPolicy = helpers.addSource(cache, source, + ['iam', 'getPolicy', region, policy.PolicyArn]); + + if (getPolicy && + getPolicy.data && + getPolicy.data.Policy && + getPolicy.data.Policy.DefaultVersionId) { + var getPolicyVersion = helpers.addSource(cache, source, + ['iam', 'getPolicyVersion', region, policy.PolicyArn]); + + if (getPolicyVersion && + getPolicyVersion.data && + getPolicyVersion.data.PolicyVersion && + getPolicyVersion.data.PolicyVersion.Document) { + let statements = helpers.normalizePolicyDocument( + getPolicyVersion.data.PolicyVersion.Document); + if (!statements) break; + + addRoleFailures(roleFailures, statements, 'managed', config.ignore_service_specific_wildcards); + } + } + } + } + + if (listRolePolicies.data && + listRolePolicies.data.PolicyNames) { + + for (var p in listRolePolicies.data.PolicyNames) { + var policyName = listRolePolicies.data.PolicyNames[p]; + + if (getRolePolicy && + getRolePolicy[policyName] && + getRolePolicy[policyName].data && + getRolePolicy[policyName].data.PolicyDocument) { + var statements = helpers.normalizePolicyDocument( + getRolePolicy[policyName].data.PolicyDocument); + if (!statements) break; + addRoleFailures(roleFailures, statements, 'inline', config.ignore_service_specific_wildcards); + } + } + } + + if (roleFailures.length) { + helpers.addResult(results, 2, + roleFailures.join(', '), + 'global', role.Arn, custom); + } else { + helpers.addResult(results, 0, + 'Role does not have overly-permissive policy', + 'global', role.Arn, custom); + } + + cb(); + }, function(){ + callback(null, results, source); + }); + } +}; + +function addRoleFailures(roleFailures, statements, policyType, ignoreServiceSpecific) { + for (var statement of statements) { + if (statement.Effect === 'Allow' && + !statement.Condition) { + let failMsg; + if (statement.Action && + statement.Action.indexOf('*') > -1 && + statement.Resource && + statement.Resource.indexOf('*') > -1) { + failMsg = `Role ${policyType} policy allows all actions on all resources`; + } else if (statement.Action.indexOf('*') > -1) { + failMsg = `Role ${policyType} policy allows all actions on selected resources`; + } else if (!ignoreServiceSpecific && statement.Action && statement.Action.length) { + // Check each action for wildcards + let wildcards = []; + for (var a in statement.Action) { + if (/^.+:[a-zA-Z]?\*.?$/.test(statement.Action[a])) { + wildcards.push(statement.Action[a]); + } + } + if (wildcards.length) failMsg = `Role ${policyType} policy allows wildcard actions: ${wildcards.join(', ')}`; + } + + if (failMsg && roleFailures.indexOf(failMsg) === -1) roleFailures.push(failMsg); + } + } +} diff --git a/plugins/aws/iam/checkAllUsedServices.spec.js b/plugins/aws/iam/checkAllUsedServices.spec.js new file mode 100644 index 0000000000..e69de29bb2 From f9b998f901f869ddf670bfe5e264c238e4de649d Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Fri, 13 May 2022 05:35:20 +0500 Subject: [PATCH 106/350] Updated plugin --- helpers/aws/api.js | 2 +- plugins/aws/iam/checkAllUsedServices.js | 38 +++++++++++++++++++++---- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/helpers/aws/api.js b/helpers/aws/api.js index 80f12be4e7..bc52b796be 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -246,7 +246,7 @@ var calls = { property: 'DeliveryChannels' }, getDiscoveredResourceCounts: { - property: 'DiscoveredResources', + property: 'resourceCounts', paginate: 'NextToken' } }, diff --git a/plugins/aws/iam/checkAllUsedServices.js b/plugins/aws/iam/checkAllUsedServices.js index b835563e8a..1f52d7e5c8 100644 --- a/plugins/aws/iam/checkAllUsedServices.js +++ b/plugins/aws/iam/checkAllUsedServices.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/aws'); var managedAdminPolicy = 'arn:aws:iam::aws:policy/AdministratorAccess'; module.exports = { - title: 'IAM Role Policies', + title: 'Check All Used Services', category: 'IAM', domain: 'Identity and Access management', description: 'Ensures IAM role policies are properly scoped with specific permissions', @@ -105,6 +105,8 @@ module.exports = { return callback(null, results, source); } + discoveredResources = discoveredResources.data.map((res) => { return { resource: res.resourceType.slice(res.resourceType.lastIndexOf(':') + 1, res.resourceType.length), count: res.count }; }); + var listRoles = helpers.addSource(cache, source, ['iam', 'listRoles', region]); @@ -163,6 +165,7 @@ module.exports = { return cb(); } + var policyFailures = []; var roleFailures = []; // See if role has admin managed policy @@ -195,7 +198,18 @@ module.exports = { getPolicyVersion.data.PolicyVersion.Document) { let statements = helpers.normalizePolicyDocument( getPolicyVersion.data.PolicyVersion.Document); + if (!statements) break; + + let resource = statements.find((doc) => doc.Resource[0].includes('arn:')); + if (resource) { + let resourceName = resource && resource.Resource[0].split(':')[2]; + let service = discoveredResources.find((res) => res.resource.toLowerCase() === resourceName.toLowerCase()); + if (!service || service.count < 1) { + let failMsg = `Role has policy with resource ${resourceName} which is not being used in this account`; + if (failMsg && roleFailures.indexOf(failMsg) === -1) policyFailures.push(failMsg); + } + } addRoleFailures(roleFailures, statements, 'managed', config.ignore_service_specific_wildcards); } @@ -215,16 +229,30 @@ module.exports = { getRolePolicy[policyName].data.PolicyDocument) { var statements = helpers.normalizePolicyDocument( getRolePolicy[policyName].data.PolicyDocument); + if (!statements) break; + + for (let statement of statements) { + let resources = [... new Set(statement.Action.map((action) => action.split(':')[0].toLowerCase()))]; + resources.forEach((resource) => { + let service = discoveredResources.find((res) => res.resource.toLowerCase() === resource.toLowerCase()); + if (!service || service.count < 1) { + let failMsg = `Role has policy with resource ${resource} which is not being used in this account`; + if (failMsg && roleFailures.indexOf(failMsg) === -1) policyFailures.push(failMsg); + } + }); + } + addRoleFailures(roleFailures, statements, 'inline', config.ignore_service_specific_wildcards); } } } - if (roleFailures.length) { - helpers.addResult(results, 2, - roleFailures.join(', '), - 'global', role.Arn, custom); + + if (policyFailures.length) { + helpers.addResult(results, 2, policyFailures.join(', '), 'global', role.Arn, custom); + } else if (roleFailures.length) { + helpers.addResult(results, 2, roleFailures.join(', '), 'global', role.Arn, custom); } else { helpers.addResult(results, 0, 'Role does not have overly-permissive policy', From f3b76973125255c0f662e603e8c0a58f99ca6a32 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 13 May 2022 17:11:20 +0500 Subject: [PATCH 107/350] Apply suggestions from code review --- plugins/google/compute/instanceGroupAutoHealing.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/google/compute/instanceGroupAutoHealing.js b/plugins/google/compute/instanceGroupAutoHealing.js index 0b530bb5d9..84656d899c 100644 --- a/plugins/google/compute/instanceGroupAutoHealing.js +++ b/plugins/google/compute/instanceGroupAutoHealing.js @@ -5,7 +5,7 @@ module.exports = { title: 'Instance Group Auto Healing Enabled', category: 'Compute', domain: 'Compute', - description: 'Ensures instance groups have auto-healing enabled for high availability.', + description: 'Ensure that instance groups have auto-healing enabled for high availability.', more_info: 'To improve the availability of your application, configure a health check to verify that the application is responding as expected.', link: 'https://cloud.google.com/compute/docs/instance-groups/autohealing-instances-in-migs', recommended_action: 'Ensure autohealing is enabled for all instance groups.', From 21c1823e2ec118f70e7fb53340cb50ee2d655bfc Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 13 May 2022 18:03:16 +0500 Subject: [PATCH 108/350] Apply suggestions from code review --- plugins/azure/appservice/backupRetentionPeriod.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/appservice/backupRetentionPeriod.js b/plugins/azure/appservice/backupRetentionPeriod.js index 4ee6335f16..a4db53305a 100644 --- a/plugins/azure/appservice/backupRetentionPeriod.js +++ b/plugins/azure/appservice/backupRetentionPeriod.js @@ -6,7 +6,7 @@ module.exports = { category: 'App Service', domain: 'Application Integration', description: 'Ensures that Azure Web Apps have recommended backup retention period.', - more_info: 'Retaining application backups for a longer period of time will allow you to handle more efficiently your app data restoration process..', + more_info: 'Retaining application backups for a longer period of time will allow you to handle your app data restoration process more efficiently.', recommended_action: 'Configure backup retention period for Azure Web Apps', link: 'https://docs.microsoft.com/en-us/azure/app-service/manage-backup', apis: ['webApps:list', 'webApps:getBackupConfiguration'], From 208492f7e48976e32f420d2313e0f79cf5a9d4cc Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 13 May 2022 18:18:09 +0500 Subject: [PATCH 109/350] Apply suggestions from code review --- plugins/azure/appservice/appInsightsEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/appservice/appInsightsEnabled.js b/plugins/azure/appservice/appInsightsEnabled.js index 9cde9c166d..b4cfb2e538 100644 --- a/plugins/azure/appservice/appInsightsEnabled.js +++ b/plugins/azure/appservice/appInsightsEnabled.js @@ -5,7 +5,7 @@ module.exports = { title: 'Web Apps Insights Enabled', category: 'App Service', domain: 'Application Integration', - description: 'Ensures that Application Insights feature is enabled.', + description: 'Ensures that Application Insights feature is enabled for Azure web apps.', more_info: 'Application insights provide advanced application monitoring. Application Insights is an extensible Application Performance Management (APM) service for developers and DevOps professionals available as monitoring feature within Azure cloud.', recommended_action: 'Enable Application insights for Azure Web Apps', link: 'https://docs.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview', From a2cbac87eb2a67655ae778910f6ec8439e905c90 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 13 May 2022 18:20:57 +0500 Subject: [PATCH 110/350] Apply suggestions from code review --- plugins/azure/appservice/automatedBackupsEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/appservice/automatedBackupsEnabled.js b/plugins/azure/appservice/automatedBackupsEnabled.js index ad5fe789a8..08a3627945 100644 --- a/plugins/azure/appservice/automatedBackupsEnabled.js +++ b/plugins/azure/appservice/automatedBackupsEnabled.js @@ -5,7 +5,7 @@ module.exports = { title: 'Web Apps Backup Enabled', category: 'App Service', domain: 'Application Integration', - description: 'Ensures that Azure Web Apps have automated backupsenabled.', + description: 'Ensures that Azure Web Apps have automated backups enabled.', more_info: 'Protect your Azure App Services web applications against accidental deletion and/or corruption, you can configure application backups to create restorable copies of your app content.', recommended_action: 'Configure backup for Azure Web Apps', link: 'https://docs.microsoft.com/en-us/azure/app-service/manage-backup', From 10276331151dcb1bd441d66faf67fd2dd1b9de8b Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Fri, 13 May 2022 18:48:01 +0500 Subject: [PATCH 111/350] Added New AWS Regions --- helpers/aws/regions.js | 43 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index 52d8f9f211..846491bf5b 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -53,7 +53,7 @@ module.exports = { configservice: [...regions, ...newRegions], dax: [...regions, ...newRegions], devopsguru: ['us-east-1', 'us-east-2', 'eu-west-1', 'us-west-2', 'ap-northeast-1', 'eu-central-1', - 'ap-southeast-1', 'ap-southeast-2'], + 'ap-southeast-1', 'ap-southeast-2', 'eu-north-1'], dynamodb: [...regions, ...newRegions], docdb: ['us-east-1', 'us-east-2', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', @@ -63,7 +63,7 @@ module.exports = { dms: [...regions, ...newRegions], ec2: [...regions, ...newRegions], ecr: [...regions, ...newRegions], - eks: regions, + eks: [...regions, ...newRegions], elasticbeanstalk: regions, elastictranscoder: ['us-east-1', 'us-west-2', 'us-west-1', 'eu-west-1', 'ap-southeast-1', 'ap-northeast-1', 'ap-southeast-2', 'ap-south-1'], @@ -77,10 +77,10 @@ module.exports = { kinesisvideo: ['us-east-1', 'us-east-2', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'ap-northeast-1','ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'ap-east-1','sa-east-1'], - firehose: regions, - kms: regions, + firehose: [...regions, ...newRegions], + kms: [...regions, ...newRegions], vpc: [...regions, ...newRegions], - flowlogs: regions, + flowlogs: [...regions, ...newRegions], rds: [...regions, ...newRegions], redshift: [...regions, ...newRegions], cloudwatch: [...regions, ...newRegions], @@ -94,14 +94,11 @@ module.exports = { 'sa-east-1', 'me-south-1', 'af-south-1'], sns: [...regions, ...newRegions], sqs: [...regions, ...newRegions], - ssm: regions, + ssm: [...regions, ...newRegions], shield: ['us-east-1'], sqs_encrypted: [...regions, ...newRegions], sts: ['us-east-1'], - transfer: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', - 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'eu-south-1', 'ap-northeast-1', - 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'ap-east-1', - 'sa-east-1', 'me-south-1', 'af-south-1'], + transfer: regions, lambda: [...regions, ...newRegions], mwaa: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'ap-south-1', 'eu-north-1', 'eu-central-1', 'ap-southeast-2', 'ap-southeast-1', 'ap-northeast-2', 'ap-northeast-1', 'ca-central-1', 'sa-east-1'], @@ -113,19 +110,19 @@ module.exports = { wafv2: regions, waf: ['us-east-1'], organizations: ['us-east-1'], - guardduty: regions, + guardduty: [...regions, ...newRegions], workspaces: ['us-east-1', 'us-west-2', 'ca-central-1', 'sa-east-1', 'ap-south-1', 'eu-west-1', 'eu-central-1', 'eu-west-2', 'ap-southeast-1', 'ap-northeast-1', 'ap-southeast-2', 'ap-northeast-2'], servicequotas: [...regions, ...newRegions], - xray: regions, + xray: [...regions, ...newRegions], codestar: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-north-1'], codebuild: regions, - mq: regions, + mq: [...regions, ...newRegions], glacier: regions, - backup: regions, + backup: [...regions, ...newRegions], elasticache: [...regions, ...newRegions], timestreamwrite: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-central-1', 'eu-west-1'], neptune: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', @@ -137,7 +134,7 @@ module.exports = { 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1'], kafka: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'eu-south-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', - 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1'], + 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1', 'af-south-1'], kendra: ['us-east-1', 'us-east-2', 'us-west-2', 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'eu-west-1'], proton: ['us-east-1', 'us-east-2', 'us-west-2', 'ap-northeast-1', 'eu-west-1'], customerprofiles: ['us-east-1', 'us-west-2', 'eu-west-2', 'ca-central-1', 'eu-central-1', @@ -146,7 +143,7 @@ module.exports = { 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2'], finspace: ['us-east-1', 'us-east-2', 'us-west-2', 'ca-central-1','eu-west-1'], - codepipeline: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ap-east-1', 'ap-south-1', 'ca-central-1', 'eu-central-1', + codepipeline: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'eu-south-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'ap-east-1', 'sa-east-1'], @@ -162,7 +159,9 @@ module.exports = { 'eu-west-3', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'af-south-1' ], translate: [ - 'us-east-1', 'us-east-2', 'us-west-2', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'ap-northeast-2' + 'us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'ap-northeast-2', + 'ap-east-1', 'ap-south-1', 'ap-northeast-1', 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'eu-west-3', + 'eu-north-1' ], databrew: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'eu-south-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', @@ -170,7 +169,7 @@ module.exports = { ], managedblockchain: ['us-east-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-northeast-1', 'eu-west-1', 'eu-west-2'], connect: ['us-east-1', 'us-west-2', 'eu-west-2', 'ca-central-1', 'eu-central-1', - 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'ap-northeast-2'], + 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'ap-northeast-2', 'af-south-1'], apprunner: ['us-east-1', 'us-west-2', 'us-west-2', 'eu-west-1','ap-northeast-1'], healthlake: ['us-east-1', 'us-east-2', 'eu-west-2'], lookoutequipment: ['us-east-1', 'eu-west-1', 'ap-northeast-2'], @@ -180,9 +179,9 @@ module.exports = { 'us-east-1', 'us-east-2', 'us-west-2', 'eu-central-1', 'eu-west-1', 'eu-north-1', 'ap-northeast-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1' ], - lookoutvision: ['us-east-1', 'us-east-2', 'ap-northeast-1', 'ap-northeast-2', 'eu-central-1', 'eu-west-1'], + lookoutvision: ['us-east-1', 'us-east-2', 'ap-northeast-1', 'ap-northeast-2', 'eu-central-1', 'eu-west-1', 'us-west-2'], lookoutmetrics: ['us-east-1', 'us-east-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'eu-central-1', - 'eu-west-1', 'eu-north-1'], + 'eu-west-1', 'eu-north-1', 'us-west-2'], forecastservice: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-central-1', 'eu-west-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1'], lexmodelsv2: [ 'us-east-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', @@ -191,7 +190,7 @@ module.exports = { wisdom: ['us-east-1', 'us-west-2', 'eu-west-2', 'eu-central-1', 'ap-northeast-1', 'ap-southeast-2'], voiceid: ['us-east-1', 'us-west-2', 'eu-west-2', 'eu-central-1', 'ap-southeast-1', 'ap-northeast-1', 'ap-southeast-2'], appmesh: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', - 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', - 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1'], + 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', 'eu-south-1', + 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1', 'af-south-1'], frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'] }; From bffbee0d1b45ac254e74665d57631b75551108f8 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 15 May 2022 00:38:31 +0500 Subject: [PATCH 112/350] Updated plugin --- plugins/aws/iam/checkAllUsedServices.js | 82 ++++++++++++++++++------- 1 file changed, 60 insertions(+), 22 deletions(-) diff --git a/plugins/aws/iam/checkAllUsedServices.js b/plugins/aws/iam/checkAllUsedServices.js index 1f52d7e5c8..ae51f9fd25 100644 --- a/plugins/aws/iam/checkAllUsedServices.js +++ b/plugins/aws/iam/checkAllUsedServices.js @@ -85,30 +85,68 @@ module.exports = { var results = []; var source = {}; - var region = helpers.defaultRegion(settings); + var regions = helpers.regions(settings); + var iamRegion = helpers.defaultRegion(settings); - var configSRecorderStatus = helpers.addSource(cache, source, - ['configservice', 'describeConfigurationRecorderStatus', region]); + var allResources = []; - if (configSRecorderStatus.data[0].recording) { - helpers.addResult(results, 2, - 'Config Service Recording is not enabled' + helpers.addError(configSRecorderStatus)); - return callback(null, results, source); - } + async.each(regions.configservice, function(region, rcb) { + var configSRecorderStatus = helpers.addSource(cache, source, + ['configservice', 'describeConfigurationRecorderStatus', region]); + + if (!configSRecorderStatus) { + return rcb(); + } - var discoveredResources = helpers.addSource(cache, source, - ['configservice', 'getDiscoveredResourceCounts', region]); + if (configSRecorderStatus.err || !configSRecorderStatus.data) { + helpers.addResult(results, 0, + 'Unable to query config service: ' + helpers.addError(configSRecorderStatus)); + return rcb(null, results, source); + } + + if (!configSRecorderStatus.data.length) { + helpers.addResult(results, 0, + 'Config service is not configured: ' + helpers.addError(configSRecorderStatus)); + return rcb(null, results, source); + } - if (discoveredResources.err || !discoveredResources.data) { - helpers.addResult(results, 3, - 'Unable to query for Config Resources: ' + helpers.addError(discoveredResources)); + if (!configSRecorderStatus.data[0].recording) { + helpers.addResult(results, 0, + 'Config service is not configured: ' + helpers.addError(configSRecorderStatus)); + return rcb(null, results, source); + } + + if (!configSRecorderStatus.data[0].lastStatus && + (configSRecorderStatus.data[0].lastStatus.toUpperCase() !== 'SUCCESS' || + configSRecorderStatus.data[0].lastStatus.toUpperCase() !== 'PENDING')) { + helpers.addResult(results, 0, + 'Config Service is configured, and recording, but not delivering properly', region); + return rcb(null, results, source); + } + + var discoveredResources = helpers.addSource(cache, source, + ['configservice', 'getDiscoveredResourceCounts', region]); + + if (discoveredResources.err || !discoveredResources.data) { + helpers.addResult(results, 3, + 'Unable to query for Config Resources: ' + helpers.addError(discoveredResources)); + return rcb(null, results, source); + } + + allResources.push(discoveredResources.data); + + rcb(); + }); + + if (allResources.length === 0) { + helpers.addResult(results, 2, 'No Config Resources found.'); return callback(null, results, source); } - discoveredResources = discoveredResources.data.map((res) => { return { resource: res.resourceType.slice(res.resourceType.lastIndexOf(':') + 1, res.resourceType.length), count: res.count }; }); + allResources = allResources.map((res) => { return { resource: res.resourceType.slice(res.resourceType.lastIndexOf(':') + 1, res.resourceType.length), count: res.count }; }); var listRoles = helpers.addSource(cache, source, - ['iam', 'listRoles', region]); + ['iam', 'listRoles', iamRegion]); if (!listRoles) return callback(null, results, source); @@ -144,14 +182,14 @@ module.exports = { // Get managed policies attached to role var listAttachedRolePolicies = helpers.addSource(cache, source, - ['iam', 'listAttachedRolePolicies', region, role.RoleName]); + ['iam', 'listAttachedRolePolicies', iamRegion, role.RoleName]); // Get inline policies attached to role var listRolePolicies = helpers.addSource(cache, source, - ['iam', 'listRolePolicies', region, role.RoleName]); + ['iam', 'listRolePolicies', iamRegion, role.RoleName]); var getRolePolicy = helpers.addSource(cache, source, - ['iam', 'getRolePolicy', region, role.RoleName]); + ['iam', 'getRolePolicy', iamRegion, role.RoleName]); if (!listAttachedRolePolicies || listAttachedRolePolicies.err) { helpers.addResult(results, 3, @@ -183,14 +221,14 @@ module.exports = { if (config.ignore_customer_managed_iam_policies && /^arn:aws:iam::[0-9]{12}:.*/.test(policy.PolicyArn)) continue; var getPolicy = helpers.addSource(cache, source, - ['iam', 'getPolicy', region, policy.PolicyArn]); + ['iam', 'getPolicy', iamRegion, policy.PolicyArn]); if (getPolicy && getPolicy.data && getPolicy.data.Policy && getPolicy.data.Policy.DefaultVersionId) { var getPolicyVersion = helpers.addSource(cache, source, - ['iam', 'getPolicyVersion', region, policy.PolicyArn]); + ['iam', 'getPolicyVersion', iamRegion, policy.PolicyArn]); if (getPolicyVersion && getPolicyVersion.data && @@ -204,7 +242,7 @@ module.exports = { let resource = statements.find((doc) => doc.Resource[0].includes('arn:')); if (resource) { let resourceName = resource && resource.Resource[0].split(':')[2]; - let service = discoveredResources.find((res) => res.resource.toLowerCase() === resourceName.toLowerCase()); + let service = allResources.find((res) => res.resource.toLowerCase() === resourceName.toLowerCase()); if (!service || service.count < 1) { let failMsg = `Role has policy with resource ${resourceName} which is not being used in this account`; if (failMsg && roleFailures.indexOf(failMsg) === -1) policyFailures.push(failMsg); @@ -235,7 +273,7 @@ module.exports = { for (let statement of statements) { let resources = [... new Set(statement.Action.map((action) => action.split(':')[0].toLowerCase()))]; resources.forEach((resource) => { - let service = discoveredResources.find((res) => res.resource.toLowerCase() === resource.toLowerCase()); + let service = allResources.find((res) => res.resource.toLowerCase() === resource.toLowerCase()); if (!service || service.count < 1) { let failMsg = `Role has policy with resource ${resource} which is not being used in this account`; if (failMsg && roleFailures.indexOf(failMsg) === -1) policyFailures.push(failMsg); From 79f83f678edcc8224c5ab16d8d485025241b0a68 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 15 May 2022 18:51:36 +0500 Subject: [PATCH 113/350] Added enableWDATPIntegration plugin and spec --- collectors/azure/collector.js | 5 ++ exports.js | 2 + helpers/azure/locations.js | 3 +- .../azure/defender/enableWDATPIntegration.js | 48 ++++++++++ .../defender/enableWDATPIntegration.spec.js | 87 +++++++++++++++++++ 5 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 plugins/azure/defender/enableWDATPIntegration.js create mode 100644 plugins/azure/defender/enableWDATPIntegration.spec.js diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index a559f259b1..316515b55b 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -215,6 +215,11 @@ var calls = { list: { url: 'https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.DocumentDB/databaseAccounts?api-version=2020-06-01-preview' } + }, + securityCenter: { + list: { + url: 'https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Security/settings?api-version=2021-06-01' + } } }; diff --git a/exports.js b/exports.js index 1c49f708a1..4d79f1e5e1 100644 --- a/exports.js +++ b/exports.js @@ -760,6 +760,8 @@ module.exports = { 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), 'automaticFailoverEnabled' : require(__dirname + '/plugins/azure/cosmosdb/automaticFailoverEnabled.js'), + + 'enableWDATPIntegration' : require(__dirname + '/plugins/azure/defender/enableWDATPIntegration.js'), }, github: { 'publicKeysRotated' : require(__dirname + '/plugins/github/users/publicKeysRotated.js'), diff --git a/helpers/azure/locations.js b/helpers/azure/locations.js index ce7825a86f..b4c27b6b24 100644 --- a/helpers/azure/locations.js +++ b/helpers/azure/locations.js @@ -98,5 +98,6 @@ module.exports = { resourceGroups: locations, policyDefinitions: locations, diagnosticSettingsOperations: ['global'], - databaseAccounts: locations + databaseAccounts: locations, + securityCenter: ['global'] }; \ No newline at end of file diff --git a/plugins/azure/defender/enableWDATPIntegration.js b/plugins/azure/defender/enableWDATPIntegration.js new file mode 100644 index 0000000000..e3ee14c3db --- /dev/null +++ b/plugins/azure/defender/enableWDATPIntegration.js @@ -0,0 +1,48 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Enable WDATP Integration', + category: 'Defender', + domain: 'Security', + description: 'Ensures that Microsoft Defender for Endpoint integration is enabled for Microsoft Defender for Cloud.', + more_info: 'WDATP integration brings comprehensive Endpoint Detection and Response (EDR) capabilities within Microsoft Defender for Cloud. This integration helps to spot abnormalities, detect and respond to advanced attacks on Windows server endpoints monitored by Microsoft Defender for Cloud. Windows Defender ATP in Microsoft Defender for Cloud supports detection on Windows Server 2016, 2012 R2, and 2008 R2 SP1 operating systems in a Standard service subscription.', + recommended_action: 'Ensure that Microsoft Defender for Endpoint integration is selected with Microsoft Defender for Cloud.', + link: 'https://docs.microsoft.com/en-in/azure/defender-for-cloud/integration-defender-for-endpoint?tabs=windows', + apis: ['securityCenter:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.securityCenter, function(location, rcb) { + var defenderSettings = helpers.addSource(cache, source, + ['securityCenter', 'list', location]); + + if (!defenderSettings) return rcb(); + + if (defenderSettings.err || !defenderSettings.data) { + helpers.addResult(results, 3, + 'Unable to query for Defender Settings: ' + helpers.addError(defenderSettings), location); + return rcb(); + } + + if (!defenderSettings.data.length) { + helpers.addResult(results, 0, 'No Defender Settings information found', location); + return rcb(); + } + + const wdatpIntegration = defenderSettings.data.find((settings) => settings.name.toLowerCase() === 'wdatp'); + if (wdatpIntegration && wdatpIntegration.enabled) { + helpers.addResult(results, 0, 'WDATP integration is enabled for Microsoft Defender', location, wdatpIntegration.id); + } else { + helpers.addResult(results, 2, 'WDATP integration is not enabled for Microsoft Defender', location); + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/defender/enableWDATPIntegration.spec.js b/plugins/azure/defender/enableWDATPIntegration.spec.js new file mode 100644 index 0000000000..9084e394dc --- /dev/null +++ b/plugins/azure/defender/enableWDATPIntegration.spec.js @@ -0,0 +1,87 @@ +var assert = require('assert'); +var expect = require('chai').expect; +var auth = require('./enableWDATPIntegration'); + +const createCache = (err, data) => { + return { + securityCenter: { + list: { + 'global': { + err: err, + data: data + } + } + } + } +}; + +describe('enableWDATPIntegration', function() { + describe('run', function() { + it('should give passing result if no settings 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 Defender Settings information found'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [] + ); + + auth.run(cache, {}, callback); + }); + + it('should give failing result if WDATP integration is not enabled for Azure Defender', 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('WDATP integration is not enabled for Microsoft Defender'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [ + { + id: '/subscriptions/dce7d0ad-ebf6-437f-a3b0-28fc0d22117e/providers/Microsoft.Security/settings/WDATP', + name: 'WDATP', + type: 'Microsoft.Security/settings', + kind: 'DataExportSettings', + enabled: false + }, + ] + ); + + auth.run(cache, {}, callback); + }); + + it('should give passing result if WDATP integration is enabled for Azure Defender', 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('WDATP integration is enabled for Microsoft Defender'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [ + { + id: '/subscriptions/dce7d0ad-ebf6-437f-a3b0-28fc0d22117e/providers/Microsoft.Security/settings/WDATP', + name: 'WDATP', + type: 'Microsoft.Security/settings', + kind: 'DataExportSettings', + enabled: true + }, + ] + ); + + auth.run(cache, {}, callback); + }) + }) +}); From 3432f78ac64ad08e4a7ac274ebf72a4096af6c89 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 15 May 2022 19:49:27 +0500 Subject: [PATCH 114/350] Added enableATP plugin and spec --- collectors/azure/collector.js | 7 + exports.js | 3 +- plugins/azure/sqlserver/enableATP.js | 67 +++++++++ plugins/azure/sqlserver/enableATP.spec.js | 157 ++++++++++++++++++++++ 4 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 plugins/azure/sqlserver/enableATP.js create mode 100644 plugins/azure/sqlserver/enableATP.spec.js diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index a559f259b1..1fdfe9278c 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -261,6 +261,13 @@ var postcalls = { url: 'https://management.azure.com/{id}/securityAlertPolicies?api-version=2017-03-01-preview' } }, + advancedThreatProtectionSettings: { + listByServer: { + reliesOnPath: 'servers.listSql', + properties: ['id'], + url: 'https://management.azure.com/{id}/advancedThreatProtectionSettings?api-version=2021-11-01-preview' + } + }, failoverGroups: { listByServer: { reliesOnPath: 'servers.listSql', diff --git a/exports.js b/exports.js index 1c49f708a1..3231fd1587 100644 --- a/exports.js +++ b/exports.js @@ -710,7 +710,8 @@ module.exports = { 'sqlServerTlsVersion' : require(__dirname + '/plugins/azure/sqlserver/sqlServerTlsVersion.js'), 'autoFailoverGroupsEnabled' : require(__dirname + '/plugins/azure/sqlserver/autoFailoverGroupsEnabled.js'), 'automaticTuningEnabled' : require(__dirname + '/plugins/azure/sqlserver/automaticTuningEnabled.js'), - + 'enableATP' : require(__dirname + '/plugins/azure/sqlserver/enableATP.js'), + 'javaVersion' : require(__dirname + '/plugins/azure/appservice/javaVersion.js'), 'phpVersion' : require(__dirname + '/plugins/azure/appservice/phpVersion.js'), 'pythonVersion' : require(__dirname + '/plugins/azure/appservice/pythonVersion.js'), diff --git a/plugins/azure/sqlserver/enableATP.js b/plugins/azure/sqlserver/enableATP.js new file mode 100644 index 0000000000..7d3cb176f5 --- /dev/null +++ b/plugins/azure/sqlserver/enableATP.js @@ -0,0 +1,67 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Advanced Threat Protection Enabled', + category: 'SQL Server', + domain: 'Databases', + description: 'Ensures that Advanced Threat Protection is enabled for SQL Servers', + more_info: 'Azure Defender for SQL is a unified package for advanced SQL security capabilities. Azure Defender is available for Azure SQL Database, Azure SQL Managed Instance, and Azure Synapse Analytics. It includes functionality for discovering and classifying sensitive data, surfacing and mitigating potential database vulnerabilities, and detecting anomalous activities that could indicate a threat to your database. It provides a single go-to location for enabling and managing these capabilities.', + recommended_action: 'Ensure that ThreatDetectionState is set to Enabled', + link: 'https://docs.microsoft.com/en-us/azure/azure-sql/database/azure-defender-for-sql', + apis: ['servers:listSql', 'advancedThreatProtectionSettings:listByServer'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + + async.each(locations.servers, function(location, rcb) { + + var servers = helpers.addSource(cache, source, + ['servers', 'listSql', location]); + + if (!servers) return rcb(); + + if (servers.err || !servers.data) { + helpers.addResult(results, 3, + 'Unable to query for SQL servers: ' + helpers.addError(servers), location); + return rcb(); + } + + if (!servers.data.length) { + helpers.addResult(results, 0, 'No SQL servers found', location); + return rcb(); + } + + servers.data.forEach(function(server) { + const advancedThreatProtectionSettings = helpers.addSource(cache, source, + ['advancedThreatProtectionSettings', 'listByServer', location, server.id]); + + if (!advancedThreatProtectionSettings || advancedThreatProtectionSettings.err || !advancedThreatProtectionSettings.data) { + helpers.addResult(results, 3, + 'Unable to query for Database Advanced Threat Protection settings: ' + helpers.addError(advancedThreatProtectionSettings), location, server.id); + } else { + if (!advancedThreatProtectionSettings.data.length) { + helpers.addResult(results, 2, 'No Database Advanced Threat Protection settings found', location, server.id); + } else { + advancedThreatProtectionSettings.data.forEach(threadProtectionSetting => { + if (threadProtectionSetting.state && + threadProtectionSetting.state.toLowerCase() == 'enabled') { + helpers.addResult(results, 0, + 'Advanced Threat Protection for the SQL server is enabled', location, server.id); + } else { + helpers.addResult(results, 2, + 'Advanced Threat Protection for the SQL server is disabled', location, server.id); + } + }); + } + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/sqlserver/enableATP.spec.js b/plugins/azure/sqlserver/enableATP.spec.js new file mode 100644 index 0000000000..b6ae3cb0bd --- /dev/null +++ b/plugins/azure/sqlserver/enableATP.spec.js @@ -0,0 +1,157 @@ +var expect = require('chai').expect; +var advancedDataSecurityEnabled = require('./enableATP'); + +const servers = [ + { + "id": "/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server", + } +]; + +const serverSecurityAlertPolicies = [ + { + id: '/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server/advancedThreatProtectionSettings/Default', + name: 'Default', + type: 'Microsoft.Sql/servers/advancedThreatProtectionSettings', + state: 'Enabled', + creationTime: '2022-05-12T10:08:23.127Z' + }, + { + id: '/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server/advancedThreatProtectionSettings/Default', + name: 'Default', + type: 'Microsoft.Sql/servers/advancedThreatProtectionSettings', + state: 'Disabled', + creationTime: '2022-05-12T10:08:23.127Z' + }, +]; + +const createCache = (servers, policies, serversErr, policiesErr) => { + const serverId = (servers && servers.length) ? servers[0].id : null; + return { + servers: { + listSql: { + 'eastus': { + err: serversErr, + data: servers + } + } + }, + advancedThreatProtectionSettings: { + listByServer: { + 'eastus': { + [serverId]: { + err: policiesErr, + data: policies + } + } + } + } + } +}; + +describe('enableATP', function() { + describe('run', function() { + it('should give passing result if no SQL 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 SQL servers found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + [] + ); + + advancedDataSecurityEnabled.run(cache, {}, callback); + }); + + it('should give failing result if no Database Advanced Threat Protection settings found', 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('No Database Advanced Threat Protection settings found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [] + ); + + advancedDataSecurityEnabled.run(cache, {}, callback); + }); + + it('should give failing result if Advanced Threat Protection for the SQL server is disabled', 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('Advanced Threat Protection for the SQL server is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [serverSecurityAlertPolicies[1]] + ); + + advancedDataSecurityEnabled.run(cache, {}, callback); + }); + + it('should give passing result if Advanced Threat Protection for the SQL server is enabled', 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('Advanced Threat Protection for the SQL server is enabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [serverSecurityAlertPolicies[0]] + ); + + advancedDataSecurityEnabled.run(cache, {}, callback); + }); + + it('should give unknown result if unable to query for SQL servers', 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 SQL servers'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [], + { message: 'unable to query servers'} + ); + + advancedDataSecurityEnabled.run(cache, {}, callback); + }); + + it('should give unknown result if Unable to query for Database Advanced Threat Protection settings', 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 Database Advanced Threat Protection settings'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [], + null, + { message: 'Unable to query for Database Advanced Threat Protection settings'} + ); + + advancedDataSecurityEnabled.run(cache, {}, callback); + }); + }) +}); From 5f385e8f7780544afe1df17d5f38839839a513f9 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Mon, 16 May 2022 03:07:21 +0500 Subject: [PATCH 115/350] Updated plugin --- plugins/azure/sqlserver/enableATP.spec.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/azure/sqlserver/enableATP.spec.js b/plugins/azure/sqlserver/enableATP.spec.js index b6ae3cb0bd..5e2450227a 100644 --- a/plugins/azure/sqlserver/enableATP.spec.js +++ b/plugins/azure/sqlserver/enableATP.spec.js @@ -1,5 +1,5 @@ var expect = require('chai').expect; -var advancedDataSecurityEnabled = require('./enableATP'); +var enableATP = require('./enableATP'); const servers = [ { @@ -7,7 +7,7 @@ const servers = [ } ]; -const serverSecurityAlertPolicies = [ +const advancedThreatProtectionSettings = [ { id: '/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server/advancedThreatProtectionSettings/Default', name: 'Default', @@ -63,7 +63,7 @@ describe('enableATP', function() { [] ); - advancedDataSecurityEnabled.run(cache, {}, callback); + enableATP.run(cache, {}, callback); }); it('should give failing result if no Database Advanced Threat Protection settings found', function(done) { @@ -80,7 +80,7 @@ describe('enableATP', function() { [] ); - advancedDataSecurityEnabled.run(cache, {}, callback); + enableATP.run(cache, {}, callback); }); it('should give failing result if Advanced Threat Protection for the SQL server is disabled', function(done) { @@ -94,10 +94,10 @@ describe('enableATP', function() { const cache = createCache( servers, - [serverSecurityAlertPolicies[1]] + [advancedThreatProtectionSettings[1]] ); - advancedDataSecurityEnabled.run(cache, {}, callback); + enableATP.run(cache, {}, callback); }); it('should give passing result if Advanced Threat Protection for the SQL server is enabled', function(done) { @@ -111,10 +111,10 @@ describe('enableATP', function() { const cache = createCache( servers, - [serverSecurityAlertPolicies[0]] + [advancedThreatProtectionSettings[0]] ); - advancedDataSecurityEnabled.run(cache, {}, callback); + enableATP.run(cache, {}, callback); }); it('should give unknown result if unable to query for SQL servers', function(done) { @@ -132,7 +132,7 @@ describe('enableATP', function() { { message: 'unable to query servers'} ); - advancedDataSecurityEnabled.run(cache, {}, callback); + enableATP.run(cache, {}, callback); }); it('should give unknown result if Unable to query for Database Advanced Threat Protection settings', function(done) { @@ -151,7 +151,7 @@ describe('enableATP', function() { { message: 'Unable to query for Database Advanced Threat Protection settings'} ); - advancedDataSecurityEnabled.run(cache, {}, callback); + enableATP.run(cache, {}, callback); }); }) }); From 56a7a2231faf6ba5a78feb480307d7276d56d5f7 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 16 May 2022 18:45:56 +0500 Subject: [PATCH 116/350] Added Remediation for StackTerminationProtection Plugin --- .../stackTerminationProtection.js | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/plugins/aws/cloudformation/stackTerminationProtection.js b/plugins/aws/cloudformation/stackTerminationProtection.js index a4fc25df1c..6dcf365d71 100644 --- a/plugins/aws/cloudformation/stackTerminationProtection.js +++ b/plugins/aws/cloudformation/stackTerminationProtection.js @@ -10,6 +10,18 @@ module.exports = { link: 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-protect-stacks.html', recommended_action: 'Enable termination protection for CloudFormation stack', apis: ['CloudFormation:listStacks', 'CloudFormation:describeStacks'], + remediation_description: 'Stack Termination protection will be enabled.', + remediation_min_version: '202205161341', + apis_remediate: ['CloudFormation:listStacks', 'CloudFormation:describeStacks'], + actions: { + remediate: ['CloudFormation:updateTerminationProtection'], + rollback: ['CloudFormation:updateTerminationProtection'] + }, + permissions: { + remediate: ['cloudformation:UpdateTerminationProtection'], + rollback: ['cloudformation:UpdateTerminationProtection'] + }, + realtime_triggers: ['cloudformation:UpdateTerminationProtection'], run: function(cache, settings, callback) { var results = []; @@ -67,5 +79,53 @@ module.exports = { }, function(){ callback(null, results, source); }); + }, + + remediate: function(config, cache, settings, resource, callback) { + var putCall = this.actions.remediate; + var pluginName = 'stackTerminationProtection'; + var stackNameArr = resource.split(':'); + var stacks = stackNameArr[stackNameArr.length - 1]; + var stackName = stacks.split('/'); + stackName = stackName[1]; + + var stackLocation = stackNameArr[3]; + + // add the location of the parameter group to the config + config.region = stackLocation; + var params = {}; + + // create the params necessary for the remediation + + params = { + EnableTerminationProtection: true, + StackName: stackName + }; + + var remediation_file = settings.remediation_file; + remediation_file['pre_remediate']['actions'][pluginName][resource] = { + 'TerminationProtection': 'Disabled', + 'StackName': stackName + }; + + // passes the config, put call, and params to the remediate helper function + helpers.remediatePlugin(config, putCall[0], params, function(err) { + if (err) { + remediation_file['remediate']['actions'][pluginName]['error'] = err; + return callback(err, null); + } + + let action = params; + action.action = putCall; + + remediation_file['post_remediate']['actions'][pluginName][resource] = action; + remediation_file['remediate']['actions'][pluginName][resource] = { + 'TerminationProtection': 'Enabled', + 'StackName': stackName + }; + + settings.remediation_file = remediation_file; + return callback(null, action); + }); } }; From a74e2e20511a0fe7fe815b669087d706f8ef4d84 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 16 May 2022 19:45:36 +0500 Subject: [PATCH 117/350] Update collectors/google/collector.js --- collectors/google/collector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collectors/google/collector.js b/collectors/google/collector.js index 43feecf1db..41f80c35c7 100644 --- a/collectors/google/collector.js +++ b/collectors/google/collector.js @@ -316,7 +316,7 @@ var postcalls = { properties: ['name'], pagination: true, paginationKey: 'pageSize' - } + } }, buckets: { getIamPolicy: { From 9892ef4abfec0767deb2d97b1170f4763272402b Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 16 May 2022 19:48:13 +0500 Subject: [PATCH 118/350] Update plugins/google/cryptographickeys/kmsPublicAccess.js --- plugins/google/cryptographickeys/kmsPublicAccess.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/google/cryptographickeys/kmsPublicAccess.js b/plugins/google/cryptographickeys/kmsPublicAccess.js index 02f9a5d28c..a277245a58 100644 --- a/plugins/google/cryptographickeys/kmsPublicAccess.js +++ b/plugins/google/cryptographickeys/kmsPublicAccess.js @@ -52,12 +52,12 @@ module.exports = { if (!cryptoKeysIamPolicies || cryptoKeysIamPolicies.err || !cryptoKeysIamPolicies.data) { helpers.addResult(results, 3, 'Unable to query IAM Policies for Cryptographic Keys: ' + helpers.addError(cryptoKeysIamPolicies), region); - return callback(null, results, source); + return rcb(); } if (!cryptoKeysIamPolicies.data.length) { helpers.addResult(results, 0, 'No IAM Policies found', region); - return callback(null, results, source); + return rcb(); } cryptoKeysIamPolicies = cryptoKeysIamPolicies.data; From 4bcb1a0756806e5abc45630003e4fbd8899d7fd1 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 16 May 2022 19:50:10 +0500 Subject: [PATCH 119/350] Apply suggestions from code review --- plugins/google/cryptographickeys/kmsPublicAccess.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/google/cryptographickeys/kmsPublicAccess.js b/plugins/google/cryptographickeys/kmsPublicAccess.js index a277245a58..58ac0129ea 100644 --- a/plugins/google/cryptographickeys/kmsPublicAccess.js +++ b/plugins/google/cryptographickeys/kmsPublicAccess.js @@ -63,6 +63,8 @@ module.exports = { cryptoKeysIamPolicies = cryptoKeysIamPolicies.data; cryptoKeys.data.forEach(cryptoKey => { + if (!cryptoKey.name) return; + let keyIamPolicy = cryptoKeysIamPolicies.find(iamPolicy => iamPolicy.parent && iamPolicy.parent.name === cryptoKey.name); if (!keyIamPolicy || !keyIamPolicy.bindings || !keyIamPolicy.bindings.length) { From 45019e3f0210f3635da4534eb34f860552e78b97 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 16 May 2022 19:55:19 +0500 Subject: [PATCH 120/350] Apply suggestions from code review --- exports.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/exports.js b/exports.js index dba7615513..05e744795c 100644 --- a/exports.js +++ b/exports.js @@ -1047,8 +1047,7 @@ module.exports = { 'trustedImageProjects' : require(__dirname + '/plugins/google/cloudresourcemanager/trustedImageProjects.js'), 'skipDefaultNetworkCreation' : require(__dirname + '/plugins/google/cloudresourcemanager/skipDefaultNetworkCreation.js'), 'locationBasedRestriction' : require(__dirname + '/plugins/google/cloudresourcemanager/locationBasedRestriction.js'), - 'disableServiceAccountCreation' : require(__dirname + '/plugins/google/cloudresourcemanager/disableServiceAccountCreation.js'), - + 'disableServiceAccountCreation' : require(__dirname + '/plugins/google/cloudresourcemanager/disableServiceAccountCreation.js') }, alibaba: { 'passwordMinLength' : require(__dirname + '/plugins/alibaba/ram/passwordMinLength.js'), From 37219de4d69397d94a65b42022ead1f06eafd418 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 16 May 2022 20:00:56 +0500 Subject: [PATCH 121/350] Update plugins/google/cryptographickeys/kmsPublicAccess.js --- plugins/google/cryptographickeys/kmsPublicAccess.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/google/cryptographickeys/kmsPublicAccess.js b/plugins/google/cryptographickeys/kmsPublicAccess.js index 58ac0129ea..e1865a21ea 100644 --- a/plugins/google/cryptographickeys/kmsPublicAccess.js +++ b/plugins/google/cryptographickeys/kmsPublicAccess.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/google'); module.exports = { title: 'KMS Public Access', category: 'Cryptographic Keys', - domain: 'Identity and Access Management', + domain: 'Application Integration', description: 'Ensures cryptographic keys are not publicly accessible.', more_info: 'To prevent exposing sensitive data and information leaks, make sure that your cryptokeys do not allow access from anonymous and public users.', link: 'https://cloud.google.com/kms/docs/reference/permissions-and-roles', From b29a715ad297fb41baabdbfbc148b877e602d273 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 16 May 2022 20:09:10 +0500 Subject: [PATCH 122/350] Changed domain --- plugins/google/cryptographickeys/keyProtectionLevel.js | 2 +- plugins/google/cryptographickeys/keyRotation.js | 2 +- plugins/google/cryptographickeys/kmsPublicAccess.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/google/cryptographickeys/keyProtectionLevel.js b/plugins/google/cryptographickeys/keyProtectionLevel.js index 3e0b524256..d7e0c9c399 100644 --- a/plugins/google/cryptographickeys/keyProtectionLevel.js +++ b/plugins/google/cryptographickeys/keyProtectionLevel.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/google'); module.exports = { title: 'Key Protection Level', category: 'Cryptographic Keys', - domain: 'Identity and Access Management', + domain: 'Application Integration', description: 'Ensure that cryptographic keys have protection level equal to or above desired protection level.', more_info: 'Cloud KMS cryptographic keys should be created with protection level set by your organization\'s compliance and security rules.', link: 'https://cloud.google.com/kms/docs/reference/rest/v1/ProtectionLevel', diff --git a/plugins/google/cryptographickeys/keyRotation.js b/plugins/google/cryptographickeys/keyRotation.js index 899836bde7..9517fab62c 100644 --- a/plugins/google/cryptographickeys/keyRotation.js +++ b/plugins/google/cryptographickeys/keyRotation.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/google'); module.exports = { title: 'Key Rotation', category: 'Cryptographic Keys', - domain: 'Identity and Access Management', + domain: 'Application Integration', description: 'Ensures cryptographic keys are set to rotate on a regular schedule', more_info: 'All cryptographic keys should have key rotation enabled. Google will handle the rotation of the encryption key itself, as well as storage of previous keys, so previous data does not need to be re-encrypted before the rotation occurs.', link: 'https://cloud.google.com/vpc/docs/using-cryptoKeys', diff --git a/plugins/google/cryptographickeys/kmsPublicAccess.js b/plugins/google/cryptographickeys/kmsPublicAccess.js index 58ac0129ea..e1865a21ea 100644 --- a/plugins/google/cryptographickeys/kmsPublicAccess.js +++ b/plugins/google/cryptographickeys/kmsPublicAccess.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/google'); module.exports = { title: 'KMS Public Access', category: 'Cryptographic Keys', - domain: 'Identity and Access Management', + domain: 'Application Integration', description: 'Ensures cryptographic keys are not publicly accessible.', more_info: 'To prevent exposing sensitive data and information leaks, make sure that your cryptokeys do not allow access from anonymous and public users.', link: 'https://cloud.google.com/kms/docs/reference/permissions-and-roles', From c71919147b649ce35afba9fbb8d143579beb1b42 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 16 May 2022 20:12:45 +0500 Subject: [PATCH 123/350] Apply suggestions from code review --- plugins/google/api/restrictedAPIKeys.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/google/api/restrictedAPIKeys.js b/plugins/google/api/restrictedAPIKeys.js index f390f087c5..a4b9b9c886 100644 --- a/plugins/google/api/restrictedAPIKeys.js +++ b/plugins/google/api/restrictedAPIKeys.js @@ -3,7 +3,7 @@ var helpers = require('../../../helpers/google'); module.exports = { title: 'Restricted API Keys', category: 'API', - domain: 'API', + domain: 'Identity and Access Management', description: 'Ensure that your Google Cloud API Keys are restricted to only those APIs that your application needs access to.', more_info: 'API keys are unrestricted by default. Unrestricted keys are insecure because they can be used by anyone from anywhere. To reduce the risk of attacks, Google Cloud API keys should be restricted to call only the APIs required by your application.', link: 'https://cloud.google.com/docs/authentication/api-keys#api_key_restrictions', From 9bb82faefb0e519e640c97c3a512688563925489 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 16 May 2022 20:23:15 +0500 Subject: [PATCH 124/350] Apply suggestions from code review --- plugins/google/api/apiKeyRotation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/google/api/apiKeyRotation.js b/plugins/google/api/apiKeyRotation.js index 1054378f64..291477dcd0 100644 --- a/plugins/google/api/apiKeyRotation.js +++ b/plugins/google/api/apiKeyRotation.js @@ -3,7 +3,7 @@ var helpers = require('../../../helpers/google'); module.exports = { title: 'Restricted API Keys', category: 'API', - domain: 'API', + domain: 'Identity and Access Management', description: 'Ensure that your Google Cloud API Keys are periodically regenerated.', more_info: 'Make sure that your Google API Keys are regenerated regularly to avoid data leaks and unauthorized access through outdated API Keys.', link: 'https://cloud.google.com/docs/authentication/api-keys', From ea9188ea9b003ea5d132c83971b417cff52cd1ba Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 16 May 2022 20:24:21 +0500 Subject: [PATCH 125/350] removed extra files --- plugins/google/api/restrictedAPIKeys.js | 58 --------- plugins/google/api/restrictedAPIKeys.spec.js | 118 ------------------- 2 files changed, 176 deletions(-) delete mode 100644 plugins/google/api/restrictedAPIKeys.js delete mode 100644 plugins/google/api/restrictedAPIKeys.spec.js diff --git a/plugins/google/api/restrictedAPIKeys.js b/plugins/google/api/restrictedAPIKeys.js deleted file mode 100644 index f390f087c5..0000000000 --- a/plugins/google/api/restrictedAPIKeys.js +++ /dev/null @@ -1,58 +0,0 @@ -var helpers = require('../../../helpers/google'); - -module.exports = { - title: 'Restricted API Keys', - category: 'API', - domain: 'API', - description: 'Ensure that your Google Cloud API Keys are restricted to only those APIs that your application needs access to.', - more_info: 'API keys are unrestricted by default. Unrestricted keys are insecure because they can be used by anyone from anywhere. To reduce the risk of attacks, Google Cloud API keys should be restricted to call only the APIs required by your application.', - link: 'https://cloud.google.com/docs/authentication/api-keys#api_key_restrictions', - recommended_action: 'Ensure that API restrictions are set for all Google Cloud API Keys.', - apis: ['apiKeys:list', 'projects:get'], - - run: function(cache, settings, callback) { - var results = []; - var source = {}; - - let projects = helpers.addSource(cache, source, - ['projects', 'get', 'global']); - - if (!projects || projects.err || !projects.data) { - helpers.addResult(results, 3, - 'Unable to query for projects: ' + helpers.addError(projects), 'global', null, null, projects.err); - return callback(null, results, source); - } - - let apiKeys = helpers.addSource(cache, source, - ['apiKeys', 'list', 'global']); - - if (!apiKeys) return callback(null, results, source); - - if (apiKeys.err || !apiKeys.data) { - helpers.addResult(results, 3, 'Unable to query API Keys for project', 'global', null, null, apiKeys.err); - return callback(null, results, source); - } - - if (!apiKeys.data.length) { - helpers.addResult(results, 0, 'No API Keys found', 'global'); - return callback(null, results, source); - } - - apiKeys.data.forEach(key => { - if (key.restrictions && key.restrictions.apiTargets && key.restrictions.apiTargets.length && - !key.restrictions.apiTargets.find(target => target.service && target.service === 'cloudapis.googleapis.com')) { - helpers.addResult(results, 0, - 'API Key is restricted', 'global', key.name); - } else { - helpers.addResult(results, 2, - 'API Key is not restricted', 'global', key.name); - } - }); - - return callback(null, results, source); - } -}; - - - - diff --git a/plugins/google/api/restrictedAPIKeys.spec.js b/plugins/google/api/restrictedAPIKeys.spec.js deleted file mode 100644 index 5a669bd0d8..0000000000 --- a/plugins/google/api/restrictedAPIKeys.spec.js +++ /dev/null @@ -1,118 +0,0 @@ -var expect = require('chai').expect; -var plugin = require('./restrictedAPIKeys'); - - -const apiKeys = [ - { - "name": "projects/my-project/locations/global/keys/my-key-1", - "displayName": "API Key 1", - "restrictions": { - "apiTargets": [ - { - "service": "apigateway.googleapis.com" - }, - { - "service": "apikeys" - } - ] - }, - }, - { - "name": "projects/my-project/locations/global/keys/my-key-2", - "displayName": "API key 2", - } -]; - -const createCache = (list, err) => { - return { - apiKeys: { - list: { - 'global': { - err: err, - data: list - } - }, - }, - projects: { - get: { - 'global': { - data: [ { name: 'testproj' } ] - } - } - } - } -}; - -describe('restrictedAPIKeys', function () { - describe('run', function () { - - it('should give unknown result if unable to query api keys', function (done) { - const callback = (err, results) => { - expect(results.length).to.be.above(0); - expect(results[0].status).to.equal(3); - expect(results[0].message).to.include('Unable to query API Keys for project'); - expect(results[0].region).to.equal('global'); - done() - }; - - const cache = createCache( - null, - ['error'] - ); - - plugin.run(cache, {}, callback); - }); - - it('should give passing result if no api keys found', function (done) { - const callback = (err, results) => { - expect(results.length).to.be.above(0); - expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No API Keys found'); - expect(results[0].region).to.equal('global'); - done() - }; - - const cache = createCache( - [], - null - ); - - plugin.run(cache, {}, callback); - }); - - it('should give passing result if google cloud api key is restricted', function (done) { - const callback = (err, results) => { - expect(results.length).to.be.above(0); - expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('API Key is restricted'); - expect(results[0].region).to.equal('global'); - done() - }; - - const cache = createCache( - [apiKeys[0]], - null - ); - - plugin.run(cache, {}, callback); - }); - - it('should give failing result if google cloud api key is not restricted', function (done) { - const callback = (err, results) => { - expect(results.length).to.be.above(0); - expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('API Key is not restricted'); - expect(results[0].region).to.equal('global') - done(); - }; - - const cache = createCache( - [apiKeys[1]], - null); - - plugin.run(cache, {}, callback); - }); - - }) -}); - From 984372eb2f32a318553c0f1ffdc8f8f1a4e2209f Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 16 May 2022 20:32:21 +0500 Subject: [PATCH 126/350] removed extra lines --- exports.js | 1 - 1 file changed, 1 deletion(-) diff --git a/exports.js b/exports.js index 4c4450acc5..6be95d2646 100644 --- a/exports.js +++ b/exports.js @@ -973,7 +973,6 @@ module.exports = { 'serviceAccountTokenCreator' : require(__dirname + '/plugins/google/iam/serviceAccountTokenCreator.js'), 'memberAdmin' : require(__dirname + '/plugins/google/iam/memberAdmin.js'), - 'restrictedAPIKeys' : require(__dirname + '/plugins/google/api/restrictedAPIKeys.js'), 'apiKeyRotation' : require(__dirname + '/plugins/google/api/apiKeyRotation.js'), 'privateEndpoint' : require(__dirname + '/plugins/google/kubernetes/privateEndpoint.js'), From 6fabf565b2de47bd6d8878ba8399e1bad4c7036e Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 16 May 2022 20:39:13 +0500 Subject: [PATCH 127/350] Removed extra files --- exports.js | 2 - .../api/apiKeyApplicationRestriction.js | 2 +- plugins/google/api/apiKeyRotation.js | 69 ---------- plugins/google/api/apiKeyRotation.spec.js | 111 ---------------- plugins/google/api/restrictedAPIKeys.js | 58 --------- plugins/google/api/restrictedAPIKeys.spec.js | 118 ------------------ 6 files changed, 1 insertion(+), 359 deletions(-) delete mode 100644 plugins/google/api/apiKeyRotation.js delete mode 100644 plugins/google/api/apiKeyRotation.spec.js delete mode 100644 plugins/google/api/restrictedAPIKeys.js delete mode 100644 plugins/google/api/restrictedAPIKeys.spec.js diff --git a/exports.js b/exports.js index 3908dd8b80..92cb972a46 100644 --- a/exports.js +++ b/exports.js @@ -973,8 +973,6 @@ module.exports = { 'serviceAccountTokenCreator' : require(__dirname + '/plugins/google/iam/serviceAccountTokenCreator.js'), 'memberAdmin' : require(__dirname + '/plugins/google/iam/memberAdmin.js'), - 'restrictedAPIKeys' : require(__dirname + '/plugins/google/api/restrictedAPIKeys.js'), - 'apiKeyRotation' : require(__dirname + '/plugins/google/api/apiKeyRotation.js'), 'apiKeyApplicationRestriction' : require(__dirname + '/plugins/google/api/apiKeyApplicationRestriction.js'), 'privateEndpoint' : require(__dirname + '/plugins/google/kubernetes/privateEndpoint.js'), diff --git a/plugins/google/api/apiKeyApplicationRestriction.js b/plugins/google/api/apiKeyApplicationRestriction.js index dcb96528ec..d9f0fc514f 100644 --- a/plugins/google/api/apiKeyApplicationRestriction.js +++ b/plugins/google/api/apiKeyApplicationRestriction.js @@ -3,7 +3,7 @@ var helpers = require('../../../helpers/google'); module.exports = { title: 'API Key Application Restriction', category: 'API', - domain: 'API', + domain: 'Identity and Access Management', description: 'Ensure there are no unrestricted API keys available within your GCP project.', more_info: 'To reduce the risk of attacks, Google Cloud API keys should be restricted only to trusted hosts, HTTP referrers, and Android/iOS mobile applications..', link: 'https://cloud.google.com/docs/authentication/api-keys#adding_application_restrictions', diff --git a/plugins/google/api/apiKeyRotation.js b/plugins/google/api/apiKeyRotation.js deleted file mode 100644 index 1054378f64..0000000000 --- a/plugins/google/api/apiKeyRotation.js +++ /dev/null @@ -1,69 +0,0 @@ -var helpers = require('../../../helpers/google'); - -module.exports = { - title: 'Restricted API Keys', - category: 'API', - domain: 'API', - description: 'Ensure that your Google Cloud API Keys are periodically regenerated.', - more_info: 'Make sure that your Google API Keys are regenerated regularly to avoid data leaks and unauthorized access through outdated API Keys.', - link: 'https://cloud.google.com/docs/authentication/api-keys', - recommended_action: 'Ensure that all your Google Cloud API keys are regenerated (rotated) after a specific period.', - apis: ['apiKeys:list', 'projects:get'], - settings: { - api_keys_rotation_interval: { - name: 'API Keys Rotation Interval', - description: 'Return a failing result when api keys exceed this number of days without being rotated', - regex: '^[1-9]{1}[0-9]{0,3}$', - default: '90' - } - }, - - run: function(cache, settings, callback) { - var results = []; - var source = {}; - - var apiKeyRotationInterval = parseInt(settings.api_keys_rotation_interval || this.settings.api_keys_rotation_interval.default); - - let projects = helpers.addSource(cache, source, - ['projects', 'get', 'global']); - - if (!projects || projects.err || !projects.data) { - helpers.addResult(results, 3, - 'Unable to query for projects: ' + helpers.addError(projects), 'global', null, null, projects.err); - return callback(null, results, source); - } - - let apiKeys = helpers.addSource(cache, source, - ['apiKeys', 'list', 'global']); - - if (!apiKeys) return callback(null, results, source); - - if (apiKeys.err || !apiKeys.data) { - helpers.addResult(results, 3, 'Unable to query API Keys for project', 'global', null, null, apiKeys.err); - return callback(null, results, source); - } - - if (!apiKeys.data.length) { - helpers.addResult(results, 0, 'No API Keys found', 'global'); - return callback(null, results, source); - } - - apiKeys.data.forEach(key => { - var diffInDays = helpers.daysBetween(key.createTime, new Date()); - - if (diffInDays > apiKeyRotationInterval) { - helpers.addResult(results, 2, - `API Key was last rotated ${diffInDays} days ago which is greater than ${apiKeyRotationInterval}`, 'global', key.name); - } else { - helpers.addResult(results, 0, - `API Key was last rotated ${diffInDays} days ago which is equal to or less than ${apiKeyRotationInterval}`, 'global', key.name); - } - }); - - return callback(null, results, source); - } -}; - - - - diff --git a/plugins/google/api/apiKeyRotation.spec.js b/plugins/google/api/apiKeyRotation.spec.js deleted file mode 100644 index cb41b3da39..0000000000 --- a/plugins/google/api/apiKeyRotation.spec.js +++ /dev/null @@ -1,111 +0,0 @@ -var expect = require('chai').expect; -var plugin = require('./apiKeyRotation'); - - -const apiKeys = [ - { - "name": "projects/my-project/locations/global/keys/my-key-1", - "displayName": "API Key 1", - "createTime": '2022-04-07T17:23:05.126949Z', - }, - { - "name": "projects/my-project/locations/global/keys/my-key-2", - "displayName": "API key 2", - "createTime": '2021-04-07T17:23:05.126949Z', - - } -]; - -const createCache = (list, err) => { - return { - apiKeys: { - list: { - 'global': { - err: err, - data: list - } - }, - }, - projects: { - get: { - 'global': { - data: [ { name: 'testproj' } ] - } - } - } - } -}; - -describe('restrictedAPIKeys', function () { - describe('run', function () { - - it('should give unknown result if unable to query api keys', function (done) { - const callback = (err, results) => { - expect(results.length).to.be.above(0); - expect(results[0].status).to.equal(3); - expect(results[0].message).to.include('Unable to query API Keys for project'); - expect(results[0].region).to.equal('global'); - done() - }; - - const cache = createCache( - null, - ['error'] - ); - - plugin.run(cache, {}, callback); - }); - - it('should give passing result if no api keys found', function (done) { - const callback = (err, results) => { - expect(results.length).to.be.above(0); - expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No API Keys found'); - expect(results[0].region).to.equal('global'); - done() - }; - - const cache = createCache( - [], - null - ); - - plugin.run(cache, {}, callback); - }); - - it('should give passing result if google cloud api key is not outdated', function (done) { - const callback = (err, results) => { - expect(results.length).to.be.above(0); - expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('which is equal to or less than'); - expect(results[0].region).to.equal('global'); - done() - }; - - const cache = createCache( - [apiKeys[0]], - null - ); - - plugin.run(cache, {}, callback); - }); - - it('should give failing result if google cloud api key is outdated', function (done) { - const callback = (err, results) => { - expect(results.length).to.be.above(0); - expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('which is greater than'); - expect(results[0].region).to.equal('global') - done(); - }; - - const cache = createCache( - [apiKeys[1]], - null); - - plugin.run(cache, {}, callback); - }); - - }) -}); - diff --git a/plugins/google/api/restrictedAPIKeys.js b/plugins/google/api/restrictedAPIKeys.js deleted file mode 100644 index f390f087c5..0000000000 --- a/plugins/google/api/restrictedAPIKeys.js +++ /dev/null @@ -1,58 +0,0 @@ -var helpers = require('../../../helpers/google'); - -module.exports = { - title: 'Restricted API Keys', - category: 'API', - domain: 'API', - description: 'Ensure that your Google Cloud API Keys are restricted to only those APIs that your application needs access to.', - more_info: 'API keys are unrestricted by default. Unrestricted keys are insecure because they can be used by anyone from anywhere. To reduce the risk of attacks, Google Cloud API keys should be restricted to call only the APIs required by your application.', - link: 'https://cloud.google.com/docs/authentication/api-keys#api_key_restrictions', - recommended_action: 'Ensure that API restrictions are set for all Google Cloud API Keys.', - apis: ['apiKeys:list', 'projects:get'], - - run: function(cache, settings, callback) { - var results = []; - var source = {}; - - let projects = helpers.addSource(cache, source, - ['projects', 'get', 'global']); - - if (!projects || projects.err || !projects.data) { - helpers.addResult(results, 3, - 'Unable to query for projects: ' + helpers.addError(projects), 'global', null, null, projects.err); - return callback(null, results, source); - } - - let apiKeys = helpers.addSource(cache, source, - ['apiKeys', 'list', 'global']); - - if (!apiKeys) return callback(null, results, source); - - if (apiKeys.err || !apiKeys.data) { - helpers.addResult(results, 3, 'Unable to query API Keys for project', 'global', null, null, apiKeys.err); - return callback(null, results, source); - } - - if (!apiKeys.data.length) { - helpers.addResult(results, 0, 'No API Keys found', 'global'); - return callback(null, results, source); - } - - apiKeys.data.forEach(key => { - if (key.restrictions && key.restrictions.apiTargets && key.restrictions.apiTargets.length && - !key.restrictions.apiTargets.find(target => target.service && target.service === 'cloudapis.googleapis.com')) { - helpers.addResult(results, 0, - 'API Key is restricted', 'global', key.name); - } else { - helpers.addResult(results, 2, - 'API Key is not restricted', 'global', key.name); - } - }); - - return callback(null, results, source); - } -}; - - - - diff --git a/plugins/google/api/restrictedAPIKeys.spec.js b/plugins/google/api/restrictedAPIKeys.spec.js deleted file mode 100644 index 5a669bd0d8..0000000000 --- a/plugins/google/api/restrictedAPIKeys.spec.js +++ /dev/null @@ -1,118 +0,0 @@ -var expect = require('chai').expect; -var plugin = require('./restrictedAPIKeys'); - - -const apiKeys = [ - { - "name": "projects/my-project/locations/global/keys/my-key-1", - "displayName": "API Key 1", - "restrictions": { - "apiTargets": [ - { - "service": "apigateway.googleapis.com" - }, - { - "service": "apikeys" - } - ] - }, - }, - { - "name": "projects/my-project/locations/global/keys/my-key-2", - "displayName": "API key 2", - } -]; - -const createCache = (list, err) => { - return { - apiKeys: { - list: { - 'global': { - err: err, - data: list - } - }, - }, - projects: { - get: { - 'global': { - data: [ { name: 'testproj' } ] - } - } - } - } -}; - -describe('restrictedAPIKeys', function () { - describe('run', function () { - - it('should give unknown result if unable to query api keys', function (done) { - const callback = (err, results) => { - expect(results.length).to.be.above(0); - expect(results[0].status).to.equal(3); - expect(results[0].message).to.include('Unable to query API Keys for project'); - expect(results[0].region).to.equal('global'); - done() - }; - - const cache = createCache( - null, - ['error'] - ); - - plugin.run(cache, {}, callback); - }); - - it('should give passing result if no api keys found', function (done) { - const callback = (err, results) => { - expect(results.length).to.be.above(0); - expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No API Keys found'); - expect(results[0].region).to.equal('global'); - done() - }; - - const cache = createCache( - [], - null - ); - - plugin.run(cache, {}, callback); - }); - - it('should give passing result if google cloud api key is restricted', function (done) { - const callback = (err, results) => { - expect(results.length).to.be.above(0); - expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('API Key is restricted'); - expect(results[0].region).to.equal('global'); - done() - }; - - const cache = createCache( - [apiKeys[0]], - null - ); - - plugin.run(cache, {}, callback); - }); - - it('should give failing result if google cloud api key is not restricted', function (done) { - const callback = (err, results) => { - expect(results.length).to.be.above(0); - expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('API Key is not restricted'); - expect(results[0].region).to.equal('global') - done(); - }; - - const cache = createCache( - [apiKeys[1]], - null); - - plugin.run(cache, {}, callback); - }); - - }) -}); - From afb21a751e9392696cf5463dd59e41822932f1b9 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 16 May 2022 20:41:02 +0500 Subject: [PATCH 128/350] Apply suggestions from code review --- plugins/google/api/apiKeyApplicationRestriction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/google/api/apiKeyApplicationRestriction.js b/plugins/google/api/apiKeyApplicationRestriction.js index d9f0fc514f..174cf6d83b 100644 --- a/plugins/google/api/apiKeyApplicationRestriction.js +++ b/plugins/google/api/apiKeyApplicationRestriction.js @@ -5,7 +5,7 @@ module.exports = { category: 'API', domain: 'Identity and Access Management', description: 'Ensure there are no unrestricted API keys available within your GCP project.', - more_info: 'To reduce the risk of attacks, Google Cloud API keys should be restricted only to trusted hosts, HTTP referrers, and Android/iOS mobile applications..', + more_info: 'To reduce the risk of attacks, Google Cloud API keys should be restricted only to trusted hosts, HTTP referrers, and Android/iOS mobile applications.', link: 'https://cloud.google.com/docs/authentication/api-keys#adding_application_restrictions', recommended_action: 'Ensure that Application restrictions are set for all Google Cloud API Keys.', apis: ['apiKeys:list', 'projects:get'], From 6c1793331b108f77a84f399121c33b1e409e2f54 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 16 May 2022 20:44:52 +0500 Subject: [PATCH 129/350] Apply suggestions from code review --- plugins/oracle/oke/okePrivateEndpoint.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oracle/oke/okePrivateEndpoint.js b/plugins/oracle/oke/okePrivateEndpoint.js index 86d72d5e79..9623e8938d 100644 --- a/plugins/oracle/oke/okePrivateEndpoint.js +++ b/plugins/oracle/oke/okePrivateEndpoint.js @@ -5,7 +5,7 @@ module.exports = { title: 'OKE Private Endpoint', category: 'OKE', domain: 'Containers', - description: 'Ensures the private endpoint setting is enabled for OKE clusters', + description: 'Ensure that private endpoint setting is enabled for OKE clusters.', more_info: 'OKE private endpoints can be used to route all traffic between the Kubernetes worker and control plane nodes over a private VCN endpoint rather than across the public internet.', recommended_action: 'Enable the private endpoint setting for all OKE clusters.', link: 'https://docs.oracle.com/en-us/iaas/Content/ContEng/Concepts/contengclustersnodes.htm#processes', From 84bc402dec43386a258934364239fb0cf62dda7b Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 16 May 2022 22:22:16 +0500 Subject: [PATCH 130/350] Update plugins/aws/imagebuilder/enhancedMetadataEnabled.js Co-authored-by: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> --- plugins/aws/imagebuilder/enhancedMetadataEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js index 8f1b03728b..debc83a264 100644 --- a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js +++ b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js @@ -6,7 +6,7 @@ module.exports = { category: 'Imagebuilder', domain: 'compute', severity: 'LOW', - description: 'Ensure that enhanced metadata collection is enabled for image pipeline.', + description: 'Ensure that enhanced metadata collection is enabled for image pipelines.', more_info: 'Image Builder is a fully managed AWS service that makes it easier to automate the creation, management, and deployment of customized, secure, and up-to-date server images that are pre-installed and pre-configured with software and settings to meet specific IT standards.', link: 'https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html', recommended_action: 'Enable enhanced metadata collection for image pipeline.', From fc0e0c93ec11f2534d1fa979d8a78c2527bbaf6f Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 16 May 2022 22:22:26 +0500 Subject: [PATCH 131/350] Update plugins/aws/imagebuilder/enhancedMetadataEnabled.js Co-authored-by: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> --- plugins/aws/imagebuilder/enhancedMetadataEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js index debc83a264..b52edd1fb9 100644 --- a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js +++ b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js @@ -7,7 +7,7 @@ module.exports = { domain: 'compute', severity: 'LOW', description: 'Ensure that enhanced metadata collection is enabled for image pipelines.', - more_info: 'Image Builder is a fully managed AWS service that makes it easier to automate the creation, management, and deployment of customized, secure, and up-to-date server images that are pre-installed and pre-configured with software and settings to meet specific IT standards.', + more_info: 'EC2 Image Builder is a fully managed AWS service that makes it easier to automate the creation, management, and deployment of customized, secure, and up-to-date server images that are pre-installed and pre-configured with software and settings to meet specific IT standards.', link: 'https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html', recommended_action: 'Enable enhanced metadata collection for image pipeline.', apis: ['Imagebuilder:listImagePipelines'], From 2df3c14a49d66463c897a18ba1b90c053c8e5740 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 16 May 2022 22:22:35 +0500 Subject: [PATCH 132/350] Update plugins/aws/imagebuilder/enhancedMetadataEnabled.spec.js Co-authored-by: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> --- plugins/aws/imagebuilder/enhancedMetadataEnabled.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/imagebuilder/enhancedMetadataEnabled.spec.js b/plugins/aws/imagebuilder/enhancedMetadataEnabled.spec.js index c0c35b276e..fce6f4a7d8 100644 --- a/plugins/aws/imagebuilder/enhancedMetadataEnabled.spec.js +++ b/plugins/aws/imagebuilder/enhancedMetadataEnabled.spec.js @@ -85,7 +85,7 @@ describe('enhancedMetadataEnabled', () => { enhancedMetadataEnabled.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No image pipeline list found') + expect(results[0].message).to.include('No Image Builder image pipelines found') }) }); it('should UNKNOWN if Unable to list image pipeline', () => { From 98089da3c201e240ccdd09bccf4576b0974b55eb Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 16 May 2022 22:24:35 +0500 Subject: [PATCH 133/350] Update plugins/aws/imagebuilder/enhancedMetadataEnabled.js Co-authored-by: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> --- plugins/aws/imagebuilder/enhancedMetadataEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js index b52edd1fb9..fc499d8743 100644 --- a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js +++ b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js @@ -29,7 +29,7 @@ module.exports = { if (!listImagePipelines.data.length) { helpers.addResult(results, 0, - 'No image pipeline list found', region); + 'No Image Builder image pipelines found', region); return rcb(); } From b9fded658a6123dc734cef732112f49f62da0f90 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 16 May 2022 22:24:43 +0500 Subject: [PATCH 134/350] Update plugins/aws/imagebuilder/enhancedMetadataEnabled.js Co-authored-by: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> --- plugins/aws/imagebuilder/enhancedMetadataEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js index fc499d8743..1cdd9f5fa3 100644 --- a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js +++ b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js @@ -38,7 +38,7 @@ module.exports = { let resource = image.arn; - if (image.enhancedImageMetadataEnabled == true) { + if (image.enhancedImageMetadataEnabled) { helpers.addResult(results, 0, 'Image pipeline has enhanced metadata collection enabled', region, resource); From f566be46d1052f3c84b9c860256af98a1b9adcfc Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 16 May 2022 22:25:46 +0500 Subject: [PATCH 135/350] Added some changes --- helpers/aws/regions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index aeea131079..a356935497 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -194,5 +194,5 @@ module.exports = { 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1'], frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'], - imagebuilder: regions + imagebuilder: [...regions, ...newRegions] }; From 3f7f57b58a52cb3ef35c7e2f501352ca73b52bea Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 16 May 2022 22:29:37 +0500 Subject: [PATCH 136/350] Added some changes --- plugins/aws/imagebuilder/enhancedMetadataEnabled.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js index 1cdd9f5fa3..b7427ecfb3 100644 --- a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js +++ b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js @@ -3,8 +3,8 @@ var helpers = require('../../../helpers/aws'); module.exports = { title: 'Enhanced Metadata Collection Enabled', - category: 'Imagebuilder', - domain: 'compute', + category: 'Image Builder', + domain: 'Compute', severity: 'LOW', description: 'Ensure that enhanced metadata collection is enabled for image pipelines.', more_info: 'EC2 Image Builder is a fully managed AWS service that makes it easier to automate the creation, management, and deployment of customized, secure, and up-to-date server images that are pre-installed and pre-configured with software and settings to meet specific IT standards.', From cfac4ead9be6e27e6c79279d1744c56911bc336c Mon Sep 17 00:00:00 2001 From: Massimo Prencipe Date: Tue, 17 May 2022 12:23:22 +0300 Subject: [PATCH 137/350] Fix Azure link typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 071b127f06..c8e84be368 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ $ docker run -e AWS_ACCESS_KEY_ID=XX -e AWS_SECRET_ACCESS_KEY=YY cloudsploit:0.0 + [CloudSploit Config File](#cloudsploit-config-file) + [Credential Files](#credential-files) + [AWS](#aws) - + [Azure](#azur) + + [Azure](#azure) + [GCP](#gcp) + [Oracle OCI](#oracle-oci) + [Environment Variables](#environment-variables) From 2251d83b3b6f94defa9cbcfc8e868a778ed955c8 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 17 May 2022 15:34:38 +0500 Subject: [PATCH 138/350] Fixed error in azure open all ports --- plugins/azure/networksecuritygroups/openAllPorts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/networksecuritygroups/openAllPorts.js b/plugins/azure/networksecuritygroups/openAllPorts.js index 2f4e3c8c7e..a53556db8e 100644 --- a/plugins/azure/networksecuritygroups/openAllPorts.js +++ b/plugins/azure/networksecuritygroups/openAllPorts.js @@ -45,7 +45,7 @@ module.exports = { let ports = { 'TCP': ['*'], - 'UCP': ['*'], + 'UDP': ['*'], '*' : ['*'] }; From 981814cf61971b32cf483c28f29bc9a68509ae14 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 17 May 2022 17:12:50 +0500 Subject: [PATCH 139/350] Added some changes --- helpers/aws/api.js | 6 ++++++ plugins/aws/imagebuilder/enhancedMetadataEnabled.js | 1 + 2 files changed, 7 insertions(+) diff --git a/helpers/aws/api.js b/helpers/aws/api.js index 39f955f078..5553d61675 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -684,6 +684,12 @@ var calls = { override: true } }, + Imagebuilder: { + listImagePipelines: { + property: 'imagePipelineList', + paginate: 'nextToken' + } + }, IoTSiteWise: { describeDefaultEncryptionConfiguration: { } diff --git a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js index b7427ecfb3..3559af7703 100644 --- a/plugins/aws/imagebuilder/enhancedMetadataEnabled.js +++ b/plugins/aws/imagebuilder/enhancedMetadataEnabled.js @@ -11,6 +11,7 @@ module.exports = { link: 'https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html', recommended_action: 'Enable enhanced metadata collection for image pipeline.', apis: ['Imagebuilder:listImagePipelines'], + run: function(cache, settings, callback) { var results = []; var source = {}; From 807fd29215e5e8deec04bacb11f74c66721589da Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 17 May 2022 17:41:29 +0500 Subject: [PATCH 140/350] Update enhancedMetadataEnabled.spec.js --- .../imagebuilder/enhancedMetadataEnabled.spec.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/plugins/aws/imagebuilder/enhancedMetadataEnabled.spec.js b/plugins/aws/imagebuilder/enhancedMetadataEnabled.spec.js index fce6f4a7d8..794cb0d441 100644 --- a/plugins/aws/imagebuilder/enhancedMetadataEnabled.spec.js +++ b/plugins/aws/imagebuilder/enhancedMetadataEnabled.spec.js @@ -69,7 +69,8 @@ describe('enhancedMetadataEnabled', () => { enhancedMetadataEnabled.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('Image pipeline has enhanced metadata collection enabled') + expect(results[0].message).to.include('Image pipeline has enhanced metadata collection enabled'); + expect(results[0].region).to.equal('us-east-1'); }) }); it('should FAIL if Image pipeline does not have enhanced metadata collection enabled', () => { @@ -77,7 +78,8 @@ describe('enhancedMetadataEnabled', () => { enhancedMetadataEnabled.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('Image pipeline does not have enhanced metadata collection enabled') + expect(results[0].message).to.include('Image pipeline does not have enhanced metadata collection enabled'); + expect(results[0].region).to.equal('us-east-1'); }) }); it('should PASS if No image pipeline list found', () => { @@ -85,7 +87,8 @@ describe('enhancedMetadataEnabled', () => { enhancedMetadataEnabled.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No Image Builder image pipelines found') + expect(results[0].message).to.include('No Image Builder image pipelines found'); + expect(results[0].region).to.equal('us-east-1'); }) }); it('should UNKNOWN if Unable to list image pipeline', () => { @@ -93,7 +96,8 @@ describe('enhancedMetadataEnabled', () => { enhancedMetadataEnabled.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 list image pipeline') + expect(results[0].message).to.include('Unable to list image pipeline'); + expect(results[0].region).to.equal('us-east-1'); }) }); it('should not return anything if list image pipeline response is not found', () => { @@ -102,4 +106,4 @@ describe('enhancedMetadataEnabled', () => { }) }); }); -}); \ No newline at end of file +}); From 7c22ad152f6334a595f8c26e6f94cece5c832aa8 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Wed, 18 May 2022 14:20:26 +0500 Subject: [PATCH 141/350] Update plugins/aws/ec2/openOracleAutoDataWarehouse.js --- plugins/aws/ec2/openOracleAutoDataWarehouse.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/ec2/openOracleAutoDataWarehouse.js b/plugins/aws/ec2/openOracleAutoDataWarehouse.js index a4f3f8a3b4..1c54614bc8 100644 --- a/plugins/aws/ec2/openOracleAutoDataWarehouse.js +++ b/plugins/aws/ec2/openOracleAutoDataWarehouse.js @@ -45,7 +45,7 @@ module.exports = { remediate: ['ec2:AuthorizeSecurityGroupIngress','ec2:RevokeSecurityGroupIngress'], rollback:['ec2:AuthorizeSecurityGroupIngress'] }, - realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress'], + realtime_triggers: ['ec2:AuthorizeSecurityGroupIngress','ec2:ModifySecurityGroupRules'], run: function(cache, settings, callback) { var config = { From d6e6d767d388888953ba68d460d828385ca8f7e9 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Wed, 18 May 2022 14:21:56 +0500 Subject: [PATCH 142/350] Update plugins/aws/eks/eksLatestPlatformVersion.js --- plugins/aws/eks/eksLatestPlatformVersion.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/aws/eks/eksLatestPlatformVersion.js b/plugins/aws/eks/eksLatestPlatformVersion.js index db0ddc16e7..b8c893e122 100644 --- a/plugins/aws/eks/eksLatestPlatformVersion.js +++ b/plugins/aws/eks/eksLatestPlatformVersion.js @@ -25,8 +25,7 @@ module.exports = { '1.22' : 1, '1.21' : 6, '1.20' : 5, - '1.19': 9, - '1.18': 11, + '1.19': 9 }; var deprecatedVersions = { From eb74f4454b335f1e784a978973fcee58ec39995e Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Wed, 18 May 2022 14:37:05 +0500 Subject: [PATCH 143/350] Added some changes --- plugins/aws/eks/eksLatestPlatformVersion.js | 3 ++- plugins/aws/lambda/lambdaOldRuntimes.js | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/aws/eks/eksLatestPlatformVersion.js b/plugins/aws/eks/eksLatestPlatformVersion.js index db0ddc16e7..05c75e7cf8 100644 --- a/plugins/aws/eks/eksLatestPlatformVersion.js +++ b/plugins/aws/eks/eksLatestPlatformVersion.js @@ -37,7 +37,8 @@ module.exports = { '1.14': '2020-12-08', '1.15': '2021-05-03', '1.16': '2021-09-27', - '1.17': '2021-11-02' + '1.17': '2021-11-02', + '1.18': '2022-03-31' }; async.each(regions.eks, function(region, rcb) { diff --git a/plugins/aws/lambda/lambdaOldRuntimes.js b/plugins/aws/lambda/lambdaOldRuntimes.js index dd6352d877..fe1ae2615f 100644 --- a/plugins/aws/lambda/lambdaOldRuntimes.js +++ b/plugins/aws/lambda/lambdaOldRuntimes.js @@ -27,6 +27,7 @@ module.exports = { { 'id':'dotnetcore2.0', 'name': '.Net Core 2.0', 'endOfLifeDate': '2018-10-01' }, { 'id':'dotnetcore1.0', 'name': '.Net Core 1.0', 'endOfLifeDate': '2019-06-27' }, { 'id':'python2.7', 'name': 'Python 2.7', 'endOfLifeDate': '2022-02-14' }, + { 'id':'python3.5', 'name': 'Python 3.5', 'endOfLifeDate': '2020-09-13' }, { 'id':'ruby2.5', 'name': 'Ruby 2.5', 'endOfLifeDate': '2022-03-31' }, ]; From adfa1c854946e29861eda46b245cbda770055c4a Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Thu, 19 May 2022 20:48:04 +0500 Subject: [PATCH 144/350] Update plugins/azure/appservice/azureActiveDirectoryEnabled.js --- plugins/azure/appservice/azureActiveDirectoryEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/appservice/azureActiveDirectoryEnabled.js b/plugins/azure/appservice/azureActiveDirectoryEnabled.js index 6e379e2277..7be675443a 100644 --- a/plugins/azure/appservice/azureActiveDirectoryEnabled.js +++ b/plugins/azure/appservice/azureActiveDirectoryEnabled.js @@ -5,7 +5,7 @@ module.exports = { title: 'Web Apps Azure Active Directory Enabled', category: 'App Service', domain: 'Application Integration', - description: 'Ensures that Azure Web Apps have Registration with Azure Active Directory is Enabled.', + description: 'Ensures that Azure Web Apps have registration with Azure Active Directory.', more_info: 'Registration with Azure Active Directory (AAD) enables App Service web applications to connect to other Azure cloud services securely without the need of access credentials such as user names and passwords.', recommended_action: 'Enable Registration with Azurre Active Directory for Azure Web Apps', link: 'https://docs.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=portal%2Chttp#add-a-system-assigned-identity', From 3569131a5d48fc18a65c02f040f3e9a2c51a0b7a Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Thu, 19 May 2022 20:48:14 +0500 Subject: [PATCH 145/350] Update plugins/azure/appservice/azureActiveDirectoryEnabled.js --- plugins/azure/appservice/azureActiveDirectoryEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/appservice/azureActiveDirectoryEnabled.js b/plugins/azure/appservice/azureActiveDirectoryEnabled.js index 7be675443a..d826e430b4 100644 --- a/plugins/azure/appservice/azureActiveDirectoryEnabled.js +++ b/plugins/azure/appservice/azureActiveDirectoryEnabled.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Application Integration', description: 'Ensures that Azure Web Apps have registration with Azure Active Directory.', more_info: 'Registration with Azure Active Directory (AAD) enables App Service web applications to connect to other Azure cloud services securely without the need of access credentials such as user names and passwords.', - recommended_action: 'Enable Registration with Azurre Active Directory for Azure Web Apps', + recommended_action: 'Enable Registration with Azure Active Directory for Azure Web Apps', link: 'https://docs.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=portal%2Chttp#add-a-system-assigned-identity', apis: ['webApps:list'], From 7cff9b4b84886dae15dd6974f3a6e9e9f014f14b Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 19 May 2022 21:17:07 +0500 Subject: [PATCH 146/350] PR changes --- exports.js | 2 +- ...ActiveDirectoryEnabled.js => webAppsADEnabled.js} | 0 ...ctoryEnabled.spec.js => webAppsADEnabled.spec.js} | 12 ++++++------ 3 files changed, 7 insertions(+), 7 deletions(-) rename plugins/azure/appservice/{azureActiveDirectoryEnabled.js => webAppsADEnabled.js} (100%) rename plugins/azure/appservice/{azureActiveDirectoryEnabled.spec.js => webAppsADEnabled.spec.js} (88%) diff --git a/exports.js b/exports.js index 1fb8a2b297..88ed993395 100644 --- a/exports.js +++ b/exports.js @@ -701,7 +701,7 @@ module.exports = { 'certificateExpiry' : require(__dirname + '/plugins/azure/appservice/certificateExpiry.js'), 'scmSiteAccessRestriction' : require(__dirname + '/plugins/azure/appservice/scmSiteAccessRestriction.js'), 'appServiceAccessRestriction' : require(__dirname + '/plugins/azure/appservice/appServiceAccessRestriction.js'), - 'azureActiveDirectoryEnabled' : require(__dirname + '/plugins/azure/appservice/azureActiveDirectoryEnabled.js'), + 'webAppsADEnabled' : require(__dirname + '/plugins/azure/appservice/webAppsADEnabled.js'), 'rbacEnabled' : require(__dirname + '/plugins/azure/kubernetesservice/rbacEnabled.js'), 'aksLatestVersion' : require(__dirname + '/plugins/azure/kubernetesservice/aksLatestVersion.js'), diff --git a/plugins/azure/appservice/azureActiveDirectoryEnabled.js b/plugins/azure/appservice/webAppsADEnabled.js similarity index 100% rename from plugins/azure/appservice/azureActiveDirectoryEnabled.js rename to plugins/azure/appservice/webAppsADEnabled.js diff --git a/plugins/azure/appservice/azureActiveDirectoryEnabled.spec.js b/plugins/azure/appservice/webAppsADEnabled.spec.js similarity index 88% rename from plugins/azure/appservice/azureActiveDirectoryEnabled.spec.js rename to plugins/azure/appservice/webAppsADEnabled.spec.js index 9b7421962e..6e169f86d4 100644 --- a/plugins/azure/appservice/azureActiveDirectoryEnabled.spec.js +++ b/plugins/azure/appservice/webAppsADEnabled.spec.js @@ -1,5 +1,5 @@ var expect = require('chai').expect; -var azureActiveDirectoryEnabled = require('./azureActiveDirectoryEnabled'); +var webAppsADEnabled = require('./webAppsADEnabled'); const webApps = [ { @@ -48,11 +48,11 @@ const createCache = (apps) => { }; }; -describe('azureActiveDirectoryEnabled', function() { +describe('webAppsADEnabled', function() { describe('run', function() { it('should give passing result if no web apps', function(done) { const cache = createCache([]); - azureActiveDirectoryEnabled.run(cache, {}, (err, results) => { + webAppsADEnabled.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 Web Apps found'); @@ -63,7 +63,7 @@ describe('azureActiveDirectoryEnabled', function() { it('should give unknown result if unable to query for web apps', function(done) { const cache = createCache(null); - azureActiveDirectoryEnabled.run(cache, {}, (err, results) => { + webAppsADEnabled.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 Web Apps'); @@ -74,7 +74,7 @@ describe('azureActiveDirectoryEnabled', function() { it('should give passing result if Registration with Azure Active Directory is enabled', function(done) { const cache = createCache([webApps[1]]); - azureActiveDirectoryEnabled.run(cache, {}, (err, results) => { + webAppsADEnabled.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); expect(results[0].message).to.include('Registration with Azure Active Directory is enabled for the Web App'); @@ -85,7 +85,7 @@ describe('azureActiveDirectoryEnabled', function() { it('should give failing result if Registration with Azure Active Directory is disabled', function(done) { const cache = createCache([webApps[0]]); - azureActiveDirectoryEnabled.run(cache, {}, (err, results) => { + webAppsADEnabled.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].message).to.include('Registration with Azure Active Directory is disabled for the Web App'); From b0e53c628a46c3db46a59321e12691de3ba2850d Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Thu, 19 May 2022 21:20:25 +0500 Subject: [PATCH 147/350] Update plugins/azure/appservice/webAppsADEnabled.js --- plugins/azure/appservice/webAppsADEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/appservice/webAppsADEnabled.js b/plugins/azure/appservice/webAppsADEnabled.js index d826e430b4..255a6f62a4 100644 --- a/plugins/azure/appservice/webAppsADEnabled.js +++ b/plugins/azure/appservice/webAppsADEnabled.js @@ -2,7 +2,7 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); module.exports = { - title: 'Web Apps Azure Active Directory Enabled', + title: 'Web Apps Active Directory Enabled', category: 'App Service', domain: 'Application Integration', description: 'Ensures that Azure Web Apps have registration with Azure Active Directory.', From a442a13cc43b3467aa9e262c2d5342970fd0fe71 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 19 May 2022 23:59:30 +0500 Subject: [PATCH 148/350] Fixed PR changes --- .../azure/keyvaults/cmkCreationForAppTier.js | 57 +++++++++---------- .../keyvaults/cmkCreationForAppTier.spec.js | 38 +++++-------- .../azure/keyvaults/keyExpirationEnabled.js | 2 +- plugins/azure/keyvaults/kvRecoveryEnabled.js | 2 +- .../keyvaults/secretExpirationEnabled.js | 2 +- 5 files changed, 43 insertions(+), 58 deletions(-) diff --git a/plugins/azure/keyvaults/cmkCreationForAppTier.js b/plugins/azure/keyvaults/cmkCreationForAppTier.js index 4b831eed44..cad0172cc8 100644 --- a/plugins/azure/keyvaults/cmkCreationForAppTier.js +++ b/plugins/azure/keyvaults/cmkCreationForAppTier.js @@ -1,23 +1,21 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); -var _ = require('underscore'); module.exports = { title: 'CMK Creation for App Tier Enabled', category: 'Key Vaults', - domain: 'Identity and Access Management', + domain: 'Application Integration', description: 'Ensure that a Customer-Managed Key (CMK) is created and configured for your Microsoft Azure application tier.', more_info: 'Setting a CMK for app tier, you gain full control over who can use this key to access the application data, implementing the principle of least privilege on the encryption key ownership and usage.', - recommended_action: 'Ensure each Key Vault has a CMK created and configured.', + recommended_action: 'Ensure a CMK created and configured for application tier in each region.', link: 'https://docs.microsoft.com/en-us/azure/azure-app-configuration/concept-customer-managed-keys', apis: ['vaults:list', 'vaults:getKeys'], settings: { - app_tier_tag_sets: { - name: 'App Tier Tag Sets', - description: 'An object of allowed tag set key value pairs to use for the CMKs creation for App Tier', - // eslint-disable-next-line no-useless-escape - regex: '/("?)\b(\w+)\1\s*:\s*("?)((?:\w+[-+*%])*?\w+)\b\3/g', - default: {} + app_tier_tag_key: { + name: 'App-Tier Tag Key', + description: 'Tag key to indicate App-Tier Key Vault keys', + regex: '^.*$s', + default: 'hello' } }, @@ -26,9 +24,11 @@ module.exports = { var source = {}; var locations = helpers.locations(settings.govcloud); var config = { - app_tier_tag_sets: settings.app_tier_tag_sets || this.settings.app_tier_tag_sets.default + app_tier_tag_key: settings.app_tier_tag_key || this.settings.app_tier_tag_key.default }; + if (!config.app_tier_tag_key.length) return callback(null, results, source); + async.each(locations.vaults, function(location, rcb) { var vaults = helpers.addSource(cache, source, ['vaults', 'list', location]); @@ -41,43 +41,40 @@ module.exports = { } if (!vaults.data.length) { - helpers.addResult(results, 0, 'No Key Vaults found', location); + helpers.addResult(results, 2, 'No Key Vaults found', location); return rcb(); } + let appTierKey; vaults.data.forEach((vault) => { var keys = helpers.addSource(cache, source, ['vaults', 'getKeys', location, vault.id]); if (!keys || keys.err || !keys.data) { helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); - } else if (!keys.data.length) { - helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); - } else { - keys.data.forEach((key) => { + return; + } + + if (keys.data.length) { + for (let key of keys.data) { var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); var keyId = `${vault.id}/keys/${keyName}`; - if (key.tags) { - const tags = key.tags; - const allowedTagSets = config.app_tier_tag_sets; - const result = _.pick(tags, (v, k) => _.isEqual(allowedTagSets[k], v)); - - if (Object.entries(result).length) { - helpers.addResult(results, 0, - 'CMK Creation for App Tier is enabled', location, keyId); - } else { - helpers.addResult(results, 2, - 'CMK Creation for App Tier is disabled', location, keyId); + if (Object.keys(key.tags).includes(config.app_tier_tag_key)) { + appTierKey = keyId; + break; } - } else { - helpers.addResult(results, 2, - 'CMK Creation for App Tier is disabled', location, keyId); } - }); + } } }); + if (appTierKey) { + helpers.addResult(results, 0, `CMK exists for application tier: ${appTierKey}`, location); + } else { + helpers.addResult(results, 2, 'CMK does not exist for application tier', location); + } + rcb(); }, function() { callback(null, results, source); diff --git a/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js b/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js index 941bde2d62..667f544c6b 100644 --- a/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js +++ b/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js @@ -37,7 +37,7 @@ const getKeys = [ "recoveryLevel": "Recoverable+Purgeable" }, "tags": { - "hello": "world" + "apptier": "app-rier" } }, { @@ -75,16 +75,16 @@ const createCache = (err, list, keys) => { describe('cmkCreationForAppTier', function() { describe('run', function() { - it('should give passing result if no key vaults found', function(done) { + it('should give failing result if no key vaults found', function(done) { const callback = (err, results) => { expect(results.length).to.equal(1); - expect(results[0].status).to.equal(0); + expect(results[0].status).to.equal(2); expect(results[0].message).to.include('No Key Vaults found'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [], {}), {}, callback); + auth.run(createCache(null, [], {}), { app_tier_tag_key: 'apptier' }, callback); }); it('should give unkown result if Unable to query for Key Vaults', function(done) { @@ -96,55 +96,43 @@ describe('cmkCreationForAppTier', function() { done() }; - auth.run(createCache(null, null, {}), {}, callback); - }); - - it('should give passing result if no key vault keys 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 Key Vault keys found'); - expect(results[0].region).to.equal('eastus'); - done() - }; - - auth.run(createCache(null, [listVaults[0]], []), {}, callback); + auth.run(createCache(null, null, {}), { app_tier_tag_key: 'apptier' }, callback); }); it('should give unkown result if Unable to query for Key Vaults keys', function(done) { const callback = (err, results) => { - expect(results.length).to.equal(1); + expect(results.length).to.equal(2); expect(results[0].status).to.equal(3); expect(results[0].message).to.include('Unable to query for Key Vault keys'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listVaults[0]], null), {}, callback); + auth.run(createCache(null, [listVaults[0]], null), { app_tier_tag_key: 'apptier' }, callback); }); - it('should give passing result if CMK Creation for App Tier is enabled', function(done) { + it('should give passing result if CMK exists for application tier', 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('CMK Creation for App Tier is enabled'); + expect(results[0].message).to.include('CMK exists for application tier'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listVaults[1]], [getKeys[0]]), { app_tier_tag_sets: { hello: 'world' } }, callback); + auth.run(createCache(null, [listVaults[1]], [getKeys[0]]), { app_tier_tag_key: 'apptier' }, callback); }); - it('should give failing result if CMK Creation for App Tier is disabled', function(done) { + it('should give failing result if CMK does not exist for application tier', 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('CMK Creation for App Tier is disabled'); + expect(results[0].message).to.include('CMK does not exist for application tier'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listVaults[1]], [getKeys[0]]), {}, callback); + auth.run(createCache(null, [listVaults[1]], [getKeys[0]]), { app_tier_tag_key: 'apptire' }, callback); }) }) }); diff --git a/plugins/azure/keyvaults/keyExpirationEnabled.js b/plugins/azure/keyvaults/keyExpirationEnabled.js index d1a2046505..4dc5714eda 100644 --- a/plugins/azure/keyvaults/keyExpirationEnabled.js +++ b/plugins/azure/keyvaults/keyExpirationEnabled.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/azure'); module.exports = { title: 'Key Expiration Enabled', category: 'Key Vaults', - domain: 'Identity and Access Management', + domain: 'Application Integration', description: 'Ensure that all Keys in Azure Key Vault have an expiry time set.', more_info: 'Setting an expiry time on all keys forces key rotation and removes unused and forgotten keys from being used.', recommended_action: 'Ensure each Key Vault has an expiry time set that provides for sufficient rotation.', diff --git a/plugins/azure/keyvaults/kvRecoveryEnabled.js b/plugins/azure/keyvaults/kvRecoveryEnabled.js index 5a2748e608..950125d464 100644 --- a/plugins/azure/keyvaults/kvRecoveryEnabled.js +++ b/plugins/azure/keyvaults/kvRecoveryEnabled.js @@ -4,7 +4,7 @@ const helpers = require('../../../helpers/azure'); module.exports = { title: 'Key Vault Recovery Enabled', category: 'Key Vaults', - domain: 'Identity and Access Management', + domain: 'Application Integration', description: 'Ensures that Purge Protection and Soft Delete are enabled on all Key Vaults', more_info: 'Purge Protection and Soft Delete are features that safeguard losing key access. With these setting enabled, key vaults have recovery actions available to restore deleted or compromised key vaults.', recommended_action: 'Once Key Vaults are created, the Azure CLI must be used to update the vault Soft Delete and Purge Protection settings.', diff --git a/plugins/azure/keyvaults/secretExpirationEnabled.js b/plugins/azure/keyvaults/secretExpirationEnabled.js index adf018b83f..a79fdd03f5 100644 --- a/plugins/azure/keyvaults/secretExpirationEnabled.js +++ b/plugins/azure/keyvaults/secretExpirationEnabled.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/azure'); module.exports = { title: 'Secret Expiration Enabled', category: 'Key Vaults', - domain: 'Identity and Access Management', + domain: 'Application Integration', description: 'Ensures that all secrets in Azure Key Vault have an expiry time set.', more_info: 'Setting an expiry time on all secrets forces secret rotation and removes unused and forgotten secrets from being used.', recommended_action: 'Ensure each Key Vault has an expiry time set that provides for sufficient rotation.', From 76fe65bb4b3aa38e30d4285d59021561bb169701 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 00:03:03 +0500 Subject: [PATCH 149/350] Changed plugin name --- exports.js | 2 +- .../{cmkCreationForAppTier.js => appTierCmkInUse.js} | 0 ...{cmkCreationForAppTier.spec.js => appTierCmkInUse.spec.js} | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) rename plugins/azure/keyvaults/{cmkCreationForAppTier.js => appTierCmkInUse.js} (100%) rename plugins/azure/keyvaults/{cmkCreationForAppTier.spec.js => appTierCmkInUse.spec.js} (98%) diff --git a/exports.js b/exports.js index aaafa2c844..16b2059b37 100644 --- a/exports.js +++ b/exports.js @@ -755,7 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), - 'cmkCreationForAppTier' : require(__dirname + '/plugins/azure/keyvaults/cmkCreationForAppTier.js'), + 'appTierCmkInUse' : require(__dirname + '/plugins/azure/keyvaults/appTierCmkInUse.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/cmkCreationForAppTier.js b/plugins/azure/keyvaults/appTierCmkInUse.js similarity index 100% rename from plugins/azure/keyvaults/cmkCreationForAppTier.js rename to plugins/azure/keyvaults/appTierCmkInUse.js diff --git a/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js b/plugins/azure/keyvaults/appTierCmkInUse.spec.js similarity index 98% rename from plugins/azure/keyvaults/cmkCreationForAppTier.spec.js rename to plugins/azure/keyvaults/appTierCmkInUse.spec.js index 667f544c6b..7e1f2852c7 100644 --- a/plugins/azure/keyvaults/cmkCreationForAppTier.spec.js +++ b/plugins/azure/keyvaults/appTierCmkInUse.spec.js @@ -1,5 +1,5 @@ var expect = require('chai').expect; -var auth = require('./cmkCreationForAppTier'); +var auth = require('./appTierCmkInUse'); const listVaults = [ { @@ -73,7 +73,7 @@ const createCache = (err, list, keys) => { } }; -describe('cmkCreationForAppTier', function() { +describe('appTierCmkInUse', function() { describe('run', function() { it('should give failing result if no key vaults found', function(done) { const callback = (err, results) => { From bc67f2edb7fac9f2ec0797e0e93d3b3bd9ac27b8 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 00:05:25 +0500 Subject: [PATCH 150/350] Fixed bug --- plugins/azure/keyvaults/appTierCmkInUse.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/keyvaults/appTierCmkInUse.js b/plugins/azure/keyvaults/appTierCmkInUse.js index cad0172cc8..5270ff8c94 100644 --- a/plugins/azure/keyvaults/appTierCmkInUse.js +++ b/plugins/azure/keyvaults/appTierCmkInUse.js @@ -15,7 +15,7 @@ module.exports = { name: 'App-Tier Tag Key', description: 'Tag key to indicate App-Tier Key Vault keys', regex: '^.*$s', - default: 'hello' + default: '' } }, From 55a13c5c291133d810ff1a4aab5d71b397ec7793 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 00:20:03 +0500 Subject: [PATCH 151/350] Fix PR changes --- plugins/azure/keyvaults/allowedCertificateKeyTypes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js index d2ff962aab..e051791b3b 100644 --- a/plugins/azure/keyvaults/allowedCertificateKeyTypes.js +++ b/plugins/azure/keyvaults/allowedCertificateKeyTypes.js @@ -13,7 +13,7 @@ module.exports = { settings: { allowed_certificate_key_types: { name: 'Key Vault Certificate Key Types', - description: 'Comma seprated key types supported for certificates in Azure Key Vault', + description: 'Comma separated key types supported for certificates in Azure Key Vault', regex: '^(RSA|EC)$', default: '' } From 13a0d89016fc514ad67896e88e471f1bfb1fd7e4 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 02:35:56 +0500 Subject: [PATCH 152/350] fixed PR changes --- exports.js | 2 +- ...tionKeysExpiry.js => keyVaultKeyExpiry.js} | 35 ++++++++--- ...piry.spec.js => keyVaultKeyExpiry.spec.js} | 63 +++++++++++++++---- 3 files changed, 76 insertions(+), 24 deletions(-) rename plugins/azure/keyvaults/{checkEncryptionKeysExpiry.js => keyVaultKeyExpiry.js} (59%) rename plugins/azure/keyvaults/{checkEncryptionKeysExpiry.spec.js => keyVaultKeyExpiry.spec.js} (71%) diff --git a/exports.js b/exports.js index 2ff7942db0..c5ff7f9c59 100644 --- a/exports.js +++ b/exports.js @@ -755,7 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), - 'checkEncryptionKeysExpiry' : require(__dirname + '/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js'), + 'keyVaultKeyExpiry' : require(__dirname + '/plugins/azure/keyvaults/keyVaultKeyExpiry.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js b/plugins/azure/keyvaults/keyVaultKeyExpiry.js similarity index 59% rename from plugins/azure/keyvaults/checkEncryptionKeysExpiry.js rename to plugins/azure/keyvaults/keyVaultKeyExpiry.js index 326b1a2ed4..6eb236cf35 100644 --- a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.js +++ b/plugins/azure/keyvaults/keyVaultKeyExpiry.js @@ -2,19 +2,30 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); module.exports = { - title: 'Key Expiration Enabled', + title: 'Key Vault Key Expiry', category: 'Key Vaults', - domain: 'Identity and Access Management', - description: 'Ensure that all Keys in Azure Key Vault have an expiry time set.', - more_info: 'Setting an expiry time on all keys forces key rotation and removes unused and forgotten keys from being used.', - recommended_action: 'Ensure each Key Vault has an expiry time set that provides for sufficient rotation.', + domain: 'Application Integration', + description: 'Proactively check for Key Vault keys expiry date and rotate then before expiry date is reached.', + more_info: 'After expiry date has reached for Key Vault key, it cannot be used anymore for cryptographic operations anymore.', + recommended_action: 'Ensure that Key Vault key are rotated before they get expired.', link: 'https://docs.microsoft.com/en-us/azure/key-vault/about-keys-secrets-and-certificates', apis: ['vaults:list', 'vaults:getKeys'], + settings: { + key_vault_key_expiry_fail: { + name: 'Key Vault Key Expiry Fail', + description: 'Return a failing result when key expiration date is within this number of days in the future', + regex: '^[1-9]{1}[0-9]{0,3}$', + default: '30' + } + }, run: function(cache, settings, callback) { var results = []; var source = {}; var locations = helpers.locations(settings.govcloud); + var config = { + key_vault_key_expiry_fail: parseInt(settings.key_vault_key_expiry_fail || this.settings.key_vault_key_expiry_fail.default) + } async.each(locations.vaults, function(location, rcb) { var vaults = helpers.addSource(cache, source, @@ -44,17 +55,21 @@ module.exports = { keys.data.forEach(function(key) { var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); var keyId = `${vault.id}/keys/${keyName}`; - + if (key.attributes && key.attributes.expires) { - if (new Date(Date.now()) < new Date(key.attributes.expires)) { + let difference = Math.round((new Date(key.attributes.expires).getTime() - (new Date).getTime())/(24*60*60*1000)); + if (difference > config.key_vault_key_expiry_fail) { helpers.addResult(results, 0, - 'Key expiry date is not yet reached', location, keyId); + `Key expires in ${difference} days`, location, keyId); + } else if (difference > 0){ + helpers.addResult(results, 2, + `Key expires in ${difference} days`, location, keyId); } else { helpers.addResult(results, 2, - 'Key has reached its expiry date', location, keyId); + `Key expired ${Math.abs(difference)} days ago`, location, keyId); } } else { - helpers.addResult(results, 2, + helpers.addResult(results, 0, 'Key expiration is not enabled', location, keyId); } }); diff --git a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js b/plugins/azure/keyvaults/keyVaultKeyExpiry.spec.js similarity index 71% rename from plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js rename to plugins/azure/keyvaults/keyVaultKeyExpiry.spec.js index a174d19bd8..6ecdff0c49 100644 --- a/plugins/azure/keyvaults/checkEncryptionKeysExpiry.spec.js +++ b/plugins/azure/keyvaults/keyVaultKeyExpiry.spec.js @@ -1,9 +1,18 @@ var expect = require('chai').expect; -var auth = require('./checkEncryptionKeysExpiry'); +var auth = require('./keyVaultKeyExpiry'); + +var keyExpiryPass = new Date(); +keyExpiryPass.setMonth(keyExpiryPass.getMonth() + 2); + +var keyExpiryFail = new Date(); +keyExpiryFail.setMonth(keyExpiryFail.getMonth() + 1); + +var keyExpired = new Date(); +keyExpired.setMonth(keyExpired.getMonth() - 1); const listKeyVaults = [ { - id: '/subscriptions/dce7d7as-ebf6-437f-a3b0-28fc0d22111e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/nauman-test', + id: '/subscriptions/abcdfget-ebf6-437f-a3b0-28fc0d22111e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/nauman-test', name: 'nauman-test', type: 'Microsoft.KeyVault/vaults', location: 'eastus', @@ -50,7 +59,7 @@ const listKeyVaults = [ "attributes": { "created": "2022-04-10T17:57:43+00:00", "enabled": true, - "expires": "2022-08-31T17:52:06+00:00", + "expires": keyExpiryPass, "notBefore": null, "recoveryLevel": "CustomizedRecoverable+Purgeable", "updated": "2022-04-10T17:57:43+00:00" @@ -66,7 +75,23 @@ const listKeyVaults = [ "attributes": { "created": "2022-04-10T17:57:43+00:00", "enabled": true, - "expires": "2022-04-01T17:52:06+00:00", + "expires": keyExpiryFail, + "notBefore": null, + "recoveryLevel": "CustomizedRecoverable+Purgeable", + "updated": "2022-04-10T17:57:43+00:00" + }, + "kid": "https://nauman-test.vault.azure.net/keys/nauman-test", + "managed": null, + "name": "nauman-test", + "tags": { + "hello": "world" + } + }, + { + "attributes": { + "created": "2022-04-10T17:57:43+00:00", + "enabled": true, + "expires": keyExpired, "notBefore": null, "recoveryLevel": "CustomizedRecoverable+Purgeable", "updated": "2022-04-10T17:57:43+00:00" @@ -91,7 +116,7 @@ const createCache = (err, list, keys) => { }, getKeys: { 'eastus': { - '/subscriptions/dce7d7as-ebf6-437f-a3b0-28fc0d22111e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/nauman-test': { + '/subscriptions/abcdfget-ebf6-437f-a3b0-28fc0d22111e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/nauman-test': { err: err, data: keys } @@ -101,7 +126,7 @@ const createCache = (err, list, keys) => { } }; -describe('checkEncryptionKeysExpiry', function() { +describe('keyVaultKeyExpiry', function() { describe('run', function() { it('should give passing result if no keys found', function(done) { const callback = (err, results) => { @@ -115,10 +140,10 @@ describe('checkEncryptionKeysExpiry', function() { auth.run(createCache(null, [], {}), {}, callback); }); - it('should give failing result if expiration is not set on keys', function(done) { + it('should give passing result if expiration is not set on keys', function(done) { const callback = (err, results) => { expect(results.length).to.equal(1); - expect(results[0].status).to.equal(2); + expect(results[0].status).to.equal(0); expect(results[0].message).to.include('Key expiration is not enabled'); expect(results[0].region).to.equal('eastus'); done() @@ -131,24 +156,36 @@ describe('checkEncryptionKeysExpiry', function() { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('Key expiry date is not yet reached'); + expect(results[0].message).to.include('Key expires in'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, listKeyVaults, [getKeys[1]]), { key_vault_key_expiry_fail: '30' }, callback); + }); + + it('should give failing results if the key has reached', 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('Key expired'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, listKeyVaults, [getKeys[1]]), {}, callback); + auth.run(createCache(null, listKeyVaults, [getKeys[3]]), { key_vault_key_expiry_fail: '40' }, callback); }); - it('should give failing results if the key has reached its expiry date', function(done) { + it('should give failing results if the key expired within failure expiry date', 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('Key has reached its expiry date'); + expect(results[0].message).to.include('Key expires'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, listKeyVaults, [getKeys[2]]), {}, callback); + auth.run(createCache(null, listKeyVaults, [getKeys[2]]), { key_vault_key_expiry_fail: '40' }, callback); }); }); }); From c202810456f497acb1136fd2fc61132653d633dc Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 02:36:41 +0500 Subject: [PATCH 153/350] fixed PR changes --- plugins/azure/keyvaults/keyVaultKeyExpiry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/keyvaults/keyVaultKeyExpiry.js b/plugins/azure/keyvaults/keyVaultKeyExpiry.js index 6eb236cf35..80ed69221f 100644 --- a/plugins/azure/keyvaults/keyVaultKeyExpiry.js +++ b/plugins/azure/keyvaults/keyVaultKeyExpiry.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Application Integration', description: 'Proactively check for Key Vault keys expiry date and rotate then before expiry date is reached.', more_info: 'After expiry date has reached for Key Vault key, it cannot be used anymore for cryptographic operations anymore.', - recommended_action: 'Ensure that Key Vault key are rotated before they get expired.', + recommended_action: 'Ensure that Key Vault keys are rotated before they get expired.', link: 'https://docs.microsoft.com/en-us/azure/key-vault/about-keys-secrets-and-certificates', apis: ['vaults:list', 'vaults:getKeys'], settings: { From 01c639ef23e6241b7b7a7f30e1105bd132732128 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 02:37:35 +0500 Subject: [PATCH 154/350] fixed PR changes --- plugins/azure/keyvaults/keyVaultKeyExpiry.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/azure/keyvaults/keyVaultKeyExpiry.js b/plugins/azure/keyvaults/keyVaultKeyExpiry.js index 80ed69221f..0c5856b8dd 100644 --- a/plugins/azure/keyvaults/keyVaultKeyExpiry.js +++ b/plugins/azure/keyvaults/keyVaultKeyExpiry.js @@ -5,8 +5,8 @@ module.exports = { title: 'Key Vault Key Expiry', category: 'Key Vaults', domain: 'Application Integration', - description: 'Proactively check for Key Vault keys expiry date and rotate then before expiry date is reached.', - more_info: 'After expiry date has reached for Key Vault key, it cannot be used anymore for cryptographic operations anymore.', + description: 'Proactively check for Key Vault keys expiry date and rotate them before expiry date is reached.', + more_info: 'After expiry date has reached for Key Vault key, it cannot be used for cryptographic operations anymore.', recommended_action: 'Ensure that Key Vault keys are rotated before they get expired.', link: 'https://docs.microsoft.com/en-us/azure/key-vault/about-keys-secrets-and-certificates', apis: ['vaults:list', 'vaults:getKeys'], From 71542c1e1fe91bc816d6829ca12d7706c789ab78 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 20 May 2022 02:40:26 +0500 Subject: [PATCH 155/350] Update plugins/azure/keyvaults/keyVaultKeyExpiry.js --- plugins/azure/keyvaults/keyVaultKeyExpiry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/keyvaults/keyVaultKeyExpiry.js b/plugins/azure/keyvaults/keyVaultKeyExpiry.js index 0c5856b8dd..d2719328d2 100644 --- a/plugins/azure/keyvaults/keyVaultKeyExpiry.js +++ b/plugins/azure/keyvaults/keyVaultKeyExpiry.js @@ -25,7 +25,7 @@ module.exports = { var locations = helpers.locations(settings.govcloud); var config = { key_vault_key_expiry_fail: parseInt(settings.key_vault_key_expiry_fail || this.settings.key_vault_key_expiry_fail.default) - } + }; async.each(locations.vaults, function(location, rcb) { var vaults = helpers.addSource(cache, source, From 19b4fdf68cc1be2733d0ba6f22cbafed6f9a5efa Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 03:24:57 +0500 Subject: [PATCH 156/350] fix PR changes --- exports.js | 2 +- plugins/azure/keyvaults/checkSecretsExpiry.js | 41 +++++--- .../azure/keyvaults/keyVaultSecretExpiry.js | 93 +++++++++++++++++++ ...y.spec.js => keyVaultSecretExpiry.spec.js} | 88 +++++++++++++++--- 4 files changed, 199 insertions(+), 25 deletions(-) create mode 100644 plugins/azure/keyvaults/keyVaultSecretExpiry.js rename plugins/azure/keyvaults/{checkSecretsExpiry.spec.js => keyVaultSecretExpiry.spec.js} (58%) diff --git a/exports.js b/exports.js index e4bc762704..af6872e7f1 100644 --- a/exports.js +++ b/exports.js @@ -755,7 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), - 'checkSecretsExpiry' : require(__dirname + '/plugins/azure/keyvaults/checkSecretsExpiry.js'), + 'keyVaultSecretExpiry' : require(__dirname + '/plugins/azure/keyvaults/keyVaultSecretExpiry.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/checkSecretsExpiry.js b/plugins/azure/keyvaults/checkSecretsExpiry.js index a2d36fea75..22acf7c1c3 100644 --- a/plugins/azure/keyvaults/checkSecretsExpiry.js +++ b/plugins/azure/keyvaults/checkSecretsExpiry.js @@ -2,19 +2,30 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); module.exports = { - title: 'Secret Expiration Enabled', + title: 'Key Vault Secret Expiry', category: 'Key Vaults', - domain: 'Identity and Access Management', - description: 'Ensures that all secrets in Azure Key Vault have an expiry time set.', - more_info: 'Setting an expiry time on all secrets forces secret rotation and removes unused and forgotten secrets from being used.', - recommended_action: 'Ensure each Key Vault has an expiry time set that provides for sufficient rotation.', + domain: 'Application Integration', + description: 'Proactively check for Key Vault secrets expiry date and rotate them before expiry date is reached.', + more_info: 'After the expiry date has reached for Key Vault secret, it cannot be used for storing sensitive and confidential data such as passwords and database connection strings anymore.', + recommended_action: 'Ensure that Key Vault secrets are rotated before they get expired.', link: 'https://docs.microsoft.com/en-us/azure/secret-vault/about-secrets-secrets-and-certificates', apis: ['vaults:list', 'vaults:getSecrets'], + settings: { + key_vault_secret_expiry_fail: { + name: 'Key Vault Secret Expiry Fail', + description: 'Return a failing result when secret expiration date is within this number of days in the future', + regex: '^[1-9]{1}[0-9]{0,3}$', + default: '30' + } + }, run: function(cache, settings, callback) { var results = []; var source = {}; var locations = helpers.locations(settings.govcloud); + var config = { + key_vault_secret_expiry_fail: parseInt(settings.key_vault_secret_expiry_fail || this.settings.key_vault_secret_expiry_fail.default) + }; async.each(locations.vaults, function(location, rcb) { var vaults = helpers.addSource(cache, source, @@ -48,22 +59,26 @@ module.exports = { if (secret.attributes) { let attributes = secret.attributes; if (!attributes.enabled) { - helpers.addResult(results, 0, 'The secret is disabled', location, secretId); + helpers.addResult(results, 0, 'Secret is not enabled', location, secretId); } else if (attributes.expiry) { - if (new Date(Date.now()) < new Date(attributes.expiry)) { + let difference = Math.round((new Date(attributes.expiry).getTime() - (new Date).getTime())/(24*60*60*1000)); + if (difference > config.key_vault_secret_expiry_fail) { helpers.addResult(results, 0, - 'Expiry date is set for the secret and date is not yet reached', location, secretId); + `Secret expires in ${difference} days`, location, secretId); + } else if (difference > 0){ + helpers.addResult(results, 2, + `Secret expires in ${difference} days`, location, secretId); } else { helpers.addResult(results, 2, - 'Expiry date is set for the secret and date has been reached', location, secretId); + `Secret expired ${Math.abs(difference)} days ago`, location, secretId); } } else { - helpers.addResult(results, 2, - 'Expiry date is not set for the secret', location, secretId); + helpers.addResult(results, 0, + 'Secret expiration is not enabled', location, secretId); } } else { - helpers.addResult(results, 2, - 'Expiry date is not set for the secret', location, secretId); + helpers.addResult(results, 0, + 'Secret expiration is not enabled', location, secretId); } }); } diff --git a/plugins/azure/keyvaults/keyVaultSecretExpiry.js b/plugins/azure/keyvaults/keyVaultSecretExpiry.js new file mode 100644 index 0000000000..8131acc5ff --- /dev/null +++ b/plugins/azure/keyvaults/keyVaultSecretExpiry.js @@ -0,0 +1,93 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Key Vault Secret Expiry', + category: 'Key Vaults', + domain: 'Application Integration', + description: 'Proactively check for Key Vault secrets expiry date and rotate them before expiry date is reached.', + more_info: 'After the expiry date has reached for Key Vault secret, it cannot be used for storing sensitive and confidential data such as passwords and database connection strings anymore.', + recommended_action: 'Ensure that Key Vault secrets are rotated before they get expired.', + link: 'https://docs.microsoft.com/en-us/azure/secret-vault/about-secrets-secrets-and-certificates', + apis: ['vaults:list', 'vaults:getSecrets'], + settings: { + key_vault_secret_expiry_fail: { + name: 'Key Vault Secret Expiry Fail', + description: 'Return a failing result when secret expiration date is within this number of days in the future', + regex: '^[1-9]{1}[0-9]{0,3}$', + default: '30' + } + }, + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + var config = { + key_vault_secret_expiry_fail: parseInt(settings.key_vault_secret_expiry_fail || this.settings.key_vault_secret_expiry_fail.default) + }; + + async.each(locations.vaults, function(location, rcb) { + var vaults = helpers.addSource(cache, source, + ['vaults', 'list', location]); + + if (!vaults) return rcb(); + + if (vaults.err || !vaults.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); + return rcb(); + } + + if (!vaults.data.length) { + helpers.addResult(results, 0, 'No Key Vaults found', location); + return rcb(); + } + + vaults.data.forEach(function(vault) { + var secrets = helpers.addSource(cache, source, + ['vaults', 'getSecrets', location, vault.id]); + + if (!secrets || secrets.err || !secrets.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault secrets: ' + helpers.addError(secrets), location, vault.id); + } else if (!secrets.data.length) { + helpers.addResult(results, 0, 'No Key Vault secrets found', location, vault.id); + } else { + secrets.data.forEach(function(secret) { + var secretName = secret.id.substring(secret.id.lastIndexOf('/') + 1); + var secretId = `${vault.id}/secrets/${secretName}`; + + if (secret.attributes) { + let attributes = secret.attributes; + if (!attributes.enabled) { + helpers.addResult(results, 0, 'Secret is not enabled', location, secretId); + } else if (attributes.exp || attributes.expiry) { + let secretExpiry = attributes.exp ? attributes.exp * 1000 : attributes.expiry; + let difference = Math.round((new Date(secretExpiry).getTime() - (new Date).getTime())/(24*60*60*1000)); + if (difference > config.key_vault_secret_expiry_fail) { + helpers.addResult(results, 0, + `Secret expires in ${difference} days`, location, secretId); + } else if (difference > 0){ + helpers.addResult(results, 2, + `Secret expires in ${difference} days`, location, secretId); + } else { + helpers.addResult(results, 2, + `Secret expired ${Math.abs(difference)} days ago`, location, secretId); + } + } else { + helpers.addResult(results, 0, + 'Secret expiration is not enabled', location, secretId); + } + } else { + helpers.addResult(results, 0, + 'Secret expiration is not enabled', location, secretId); + } + }); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/keyvaults/checkSecretsExpiry.spec.js b/plugins/azure/keyvaults/keyVaultSecretExpiry.spec.js similarity index 58% rename from plugins/azure/keyvaults/checkSecretsExpiry.spec.js rename to plugins/azure/keyvaults/keyVaultSecretExpiry.spec.js index eb4cd7d182..d08c57a3c9 100644 --- a/plugins/azure/keyvaults/checkSecretsExpiry.spec.js +++ b/plugins/azure/keyvaults/keyVaultSecretExpiry.spec.js @@ -1,5 +1,14 @@ var expect = require('chai').expect; -var auth = require('./checkSecretsExpiry'); +var auth = require('./keyVaultSecretExpiry'); + +var secretExpiryPass = new Date(); +secretExpiryPass.setMonth(secretExpiryPass.getMonth() + 2); + +var secretExpiryFail = new Date(); +secretExpiryFail.setMonth(secretExpiryFail.getMonth() + 1); + +var secretExpired = new Date(); +secretExpired.setMonth(secretExpired.getMonth() - 1); const listKeyVaults = [ { @@ -43,6 +52,22 @@ const getSecrets = [ } ] } + },{ + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "expiry": secretExpiryPass, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } }, { '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { @@ -51,7 +76,24 @@ const getSecrets = [ "id": "https://testvault.vault.azure.net/secrets/mysecret", "attributes": { "enabled": true, - "expiry": '2022-12-10T21:08:47.684Z', + "expiry": secretExpiryFail, + "created": 1572289869, + "updated": 1572290380, + "recoveryLevel": "Recoverable+Purgeable" + }, + "tags": {} + } + ] + } + }, + { + '/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault': { + data: [ + { + "id": "https://testvault.vault.azure.net/secrets/mysecret", + "attributes": { + "enabled": true, + "expiry": secretExpired, "created": 1572289869, "updated": 1572290380, "recoveryLevel": "Recoverable+Purgeable" @@ -68,7 +110,7 @@ const getSecrets = [ "id": "https://testvault.vault.azure.net/secrets/mysecret", "attributes": { "enabled": false, - "expiry": 1635448252, + "expiry": secretExpired, "created": 1572289869, "updated": 1572290380, "recoveryLevel": "Recoverable+Purgeable" @@ -96,7 +138,7 @@ const createCache = (err, list, get) => { } }; -describe('checkSecretsExpiry', function() { +describe('keyVaultSecretExpiry', function() { describe('run', function() { it('should give passing result if no secrets found', function(done) { const callback = (err, results) => { @@ -110,11 +152,11 @@ describe('checkSecretsExpiry', function() { auth.run(createCache(null, [], {}), {}, callback); }); - it('should give failing result if expiration is not set on secrets', function(done) { + it('should give passing result if secret expiration is not enabled', 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('Expiry date is not set for the secret'); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Secret expiration is not enabled'); expect(results[0].region).to.equal('eastus'); done() }; @@ -122,11 +164,11 @@ describe('checkSecretsExpiry', function() { auth.run(createCache(null, [listKeyVaults[0]], getSecrets[0]), {}, callback); }); - it('should give passing result if expiration is set on keys', function(done) { + it('should give passing result if secret expiry is not yet reached', 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('Expiry date is set for the secret'); + expect(results[0].message).to.include('Secret expires'); expect(results[0].region).to.equal('eastus'); done() }; @@ -134,16 +176,40 @@ describe('checkSecretsExpiry', function() { auth.run(createCache(null, [listKeyVaults[0]], getSecrets[1]), {}, callback); }); + it('should give failing result if secret has expired', 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('Secret expired'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listKeyVaults[0]], getSecrets[3]), {}, callback); + }); + + it('should give failing result if secret expires within failure expiry date', 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('Secret expires'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listKeyVaults[0]], getSecrets[2]), { key_vault_secret_expiry_fail: '40' }, callback); + }); + it('should give passing result if key is disabled', 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('The secret is disabled'); + expect(results[0].message).to.include('Secret is not enabled'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listKeyVaults[0]], getSecrets[2]), {}, callback); + auth.run(createCache(null, [listKeyVaults[0]], getSecrets[4]), {}, callback); }); }) }); From 344ea415a717537dba55b0e0098af5943a7393c8 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 03:26:42 +0500 Subject: [PATCH 157/350] fix PR changes --- plugins/azure/keyvaults/checkSecretsExpiry.js | 92 ------------------- 1 file changed, 92 deletions(-) delete mode 100644 plugins/azure/keyvaults/checkSecretsExpiry.js diff --git a/plugins/azure/keyvaults/checkSecretsExpiry.js b/plugins/azure/keyvaults/checkSecretsExpiry.js deleted file mode 100644 index 22acf7c1c3..0000000000 --- a/plugins/azure/keyvaults/checkSecretsExpiry.js +++ /dev/null @@ -1,92 +0,0 @@ -var async = require('async'); -var helpers = require('../../../helpers/azure'); - -module.exports = { - title: 'Key Vault Secret Expiry', - category: 'Key Vaults', - domain: 'Application Integration', - description: 'Proactively check for Key Vault secrets expiry date and rotate them before expiry date is reached.', - more_info: 'After the expiry date has reached for Key Vault secret, it cannot be used for storing sensitive and confidential data such as passwords and database connection strings anymore.', - recommended_action: 'Ensure that Key Vault secrets are rotated before they get expired.', - link: 'https://docs.microsoft.com/en-us/azure/secret-vault/about-secrets-secrets-and-certificates', - apis: ['vaults:list', 'vaults:getSecrets'], - settings: { - key_vault_secret_expiry_fail: { - name: 'Key Vault Secret Expiry Fail', - description: 'Return a failing result when secret expiration date is within this number of days in the future', - regex: '^[1-9]{1}[0-9]{0,3}$', - default: '30' - } - }, - - run: function(cache, settings, callback) { - var results = []; - var source = {}; - var locations = helpers.locations(settings.govcloud); - var config = { - key_vault_secret_expiry_fail: parseInt(settings.key_vault_secret_expiry_fail || this.settings.key_vault_secret_expiry_fail.default) - }; - - async.each(locations.vaults, function(location, rcb) { - var vaults = helpers.addSource(cache, source, - ['vaults', 'list', location]); - - if (!vaults) return rcb(); - - if (vaults.err || !vaults.data) { - helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); - return rcb(); - } - - if (!vaults.data.length) { - helpers.addResult(results, 0, 'No Key Vaults found', location); - return rcb(); - } - - vaults.data.forEach(function(vault) { - var secrets = helpers.addSource(cache, source, - ['vaults', 'getSecrets', location, vault.id]); - - if (!secrets || secrets.err || !secrets.data) { - helpers.addResult(results, 3, 'Unable to query for Key Vault secrets: ' + helpers.addError(secrets), location, vault.id); - } else if (!secrets.data.length) { - helpers.addResult(results, 0, 'No Key Vault secrets found', location, vault.id); - } else { - secrets.data.forEach(function(secret) { - var secretName = secret.id.substring(secret.id.lastIndexOf('/') + 1); - var secretId = `${vault.id}/secrets/${secretName}`; - - if (secret.attributes) { - let attributes = secret.attributes; - if (!attributes.enabled) { - helpers.addResult(results, 0, 'Secret is not enabled', location, secretId); - } else if (attributes.expiry) { - let difference = Math.round((new Date(attributes.expiry).getTime() - (new Date).getTime())/(24*60*60*1000)); - if (difference > config.key_vault_secret_expiry_fail) { - helpers.addResult(results, 0, - `Secret expires in ${difference} days`, location, secretId); - } else if (difference > 0){ - helpers.addResult(results, 2, - `Secret expires in ${difference} days`, location, secretId); - } else { - helpers.addResult(results, 2, - `Secret expired ${Math.abs(difference)} days ago`, location, secretId); - } - } else { - helpers.addResult(results, 0, - 'Secret expiration is not enabled', location, secretId); - } - } else { - helpers.addResult(results, 0, - 'Secret expiration is not enabled', location, secretId); - } - }); - } - }); - - rcb(); - }, function() { - callback(null, results, source); - }); - } -}; From 047f141c990752e2190efbfeff5d060951d1c092 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 03:41:02 +0500 Subject: [PATCH 158/350] fix pr changes --- plugins/azure/keyvaults/keyVaultKeyExpiry.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/azure/keyvaults/keyVaultKeyExpiry.js b/plugins/azure/keyvaults/keyVaultKeyExpiry.js index 0c5856b8dd..a8b7e687a8 100644 --- a/plugins/azure/keyvaults/keyVaultKeyExpiry.js +++ b/plugins/azure/keyvaults/keyVaultKeyExpiry.js @@ -56,8 +56,12 @@ module.exports = { var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); var keyId = `${vault.id}/keys/${keyName}`; - if (key.attributes && key.attributes.expires) { - let difference = Math.round((new Date(key.attributes.expires).getTime() - (new Date).getTime())/(24*60*60*1000)); + if (!key.attributes || !key.attributes.enabled) { + helpers.addResult(results, 0, + 'Key is not enabled', location, keyId); + } else if (key.attributes && (key.attributes.expires || key.attributes.exp)) { + let keyExpiry = key.attributes.exp ? key.attributes.exp * 1000 : key.attributes.expires; + let difference = Math.round((new Date(keyExpiry).getTime() - (new Date).getTime())/(24*60*60*1000)); if (difference > config.key_vault_key_expiry_fail) { helpers.addResult(results, 0, `Key expires in ${difference} days`, location, keyId); From 2d6a0c07e62088d170a0452132a1b3a49d40ffdb Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 03:45:38 +0500 Subject: [PATCH 159/350] fix changes --- .../azure/keyvaults/keyVaultSecretExpiry.js | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/plugins/azure/keyvaults/keyVaultSecretExpiry.js b/plugins/azure/keyvaults/keyVaultSecretExpiry.js index 8131acc5ff..850bb475b9 100644 --- a/plugins/azure/keyvaults/keyVaultSecretExpiry.js +++ b/plugins/azure/keyvaults/keyVaultSecretExpiry.js @@ -56,26 +56,21 @@ module.exports = { var secretName = secret.id.substring(secret.id.lastIndexOf('/') + 1); var secretId = `${vault.id}/secrets/${secretName}`; - if (secret.attributes) { + if (!secret.attributes || !secret.attributes.enabled) { + helpers.addResult(results, 0, 'Secret is not enabled', location, secretId); + } else if (secret.attributes && (secret.attributes.exp || secret.attributes.expiry)) { let attributes = secret.attributes; - if (!attributes.enabled) { - helpers.addResult(results, 0, 'Secret is not enabled', location, secretId); - } else if (attributes.exp || attributes.expiry) { - let secretExpiry = attributes.exp ? attributes.exp * 1000 : attributes.expiry; - let difference = Math.round((new Date(secretExpiry).getTime() - (new Date).getTime())/(24*60*60*1000)); - if (difference > config.key_vault_secret_expiry_fail) { - helpers.addResult(results, 0, - `Secret expires in ${difference} days`, location, secretId); - } else if (difference > 0){ - helpers.addResult(results, 2, - `Secret expires in ${difference} days`, location, secretId); - } else { - helpers.addResult(results, 2, - `Secret expired ${Math.abs(difference)} days ago`, location, secretId); - } - } else { + let secretExpiry = attributes.exp ? attributes.exp * 1000 : attributes.expiry; + let difference = Math.round((new Date(secretExpiry).getTime() - (new Date).getTime())/(24*60*60*1000)); + if (difference > config.key_vault_secret_expiry_fail) { helpers.addResult(results, 0, - 'Secret expiration is not enabled', location, secretId); + `Secret expires in ${difference} days`, location, secretId); + } else if (difference > 0){ + helpers.addResult(results, 2, + `Secret expires in ${difference} days`, location, secretId); + } else { + helpers.addResult(results, 2, + `Secret expired ${Math.abs(difference)} days ago`, location, secretId); } } else { helpers.addResult(results, 0, From 2da4c0539835b2c088843e093e35126cc6f241ed Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 04:14:45 +0500 Subject: [PATCH 160/350] PR changes fix --- exports.js | 2 +- .../rsaCertificateAllowedKeySizes.js | 16 ++-- .../azure/keyvaults/rsaCertificateKeySize.js | 83 +++++++++++++++++++ ....spec.js => rsaCertificateKeySize.spec.js} | 8 +- 4 files changed, 95 insertions(+), 14 deletions(-) create mode 100644 plugins/azure/keyvaults/rsaCertificateKeySize.js rename plugins/azure/keyvaults/{rsaCertificateAllowedKeySizes.spec.js => rsaCertificateKeySize.spec.js} (97%) diff --git a/exports.js b/exports.js index 1ee2d64d8d..b790b50892 100644 --- a/exports.js +++ b/exports.js @@ -755,7 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), - 'rsaCertificateAllowedKeySizes' : require(__dirname + '/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.js'), + 'rsaCertificateKeySize' : require(__dirname + '/plugins/azure/keyvaults/rsaCertificateKeySize.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.js b/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.js index bef2c10000..504820a91e 100644 --- a/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.js +++ b/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.js @@ -4,15 +4,15 @@ var helpers = require('../../../helpers/azure'); module.exports = { title: 'RSA Certificate Allowed Key Size', category: 'Key Vaults', - domain: 'Identity and Access Management', + domain: 'Application Integration', description: 'Ensures that Microsoft Azure Key Vault RSA certificates are using the allowed key size.', more_info: 'Having the right key type size for your Azure Key Vault RSA certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', recommended_action: 'Ensure that Key Vault RSA certificates are using the allowed key types.', link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/about-certificates', apis: ['vaults:list', 'vaults:getCertificates', 'getCertificatePolicy:get'], settings: { - rsa_certificate_key_size: { - name: 'RSA Certificate Allowed Key Size', + min_rsa_certificate_key_size: { + name: 'Minimum RSA Certificate Allowed Key Size', description: 'Key sizes supported for rsa certificates in Azure Key Vault', regex: '^(2048|3072|4096)$', default: '2048' @@ -24,7 +24,7 @@ module.exports = { var source = {}; var locations = helpers.locations(settings.govcloud); var config = { - rsa_certificate_key_size: settings.rsa_certificate_key_size || this.settings.rsa_certificate_key_size, + min_rsa_certificate_key_size: parseInt(settings.min_rsa_certificate_key_size || this.settings.min_rsa_certificate_key_size.default) }; async.each(locations.vaults, function(location, rcb) { @@ -62,12 +62,10 @@ module.exports = { const certificateKeys = certificatePolicy.data.key_props; if (certificateKeys && certificateKeys.kty) { - const allowedKeySize = new RegExp(config.rsa_certificate_key_size.regex); - - if (allowedKeySize.test(certificateKeys.key_size)) { - helpers.addResult(results, 0, 'RSA Certificate key size is within the Allowed Key Sizes: ' + certificateKeys.key_size, location, certificate.id); + if (certificateKeys.key_size >= config.min_rsa_certificate_key_size) { + helpers.addResult(results, 0, `RSA Certificate key size is ${certificateKeys.key_size}`, location, certificate.id); } else { - helpers.addResult(results, 2, 'RSA Certificate key size is not within the Allowed Key Sizes: ' + certificateKeys.key_size, location, certificate.id); + helpers.addResult(results, 2, `RSA Certificate key size is ${certificateKeys.key_size}`, location, certificate.id); } } else { helpers.addResult(results, 3, 'Unable to list key type for Key Vault Certificate: ' + helpers.addError(certificatePolicy), location, certificate.id); diff --git a/plugins/azure/keyvaults/rsaCertificateKeySize.js b/plugins/azure/keyvaults/rsaCertificateKeySize.js new file mode 100644 index 0000000000..02912604b8 --- /dev/null +++ b/plugins/azure/keyvaults/rsaCertificateKeySize.js @@ -0,0 +1,83 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'RSA Certificate Allowed Key Size', + category: 'Key Vaults', + domain: 'Application Integration', + description: 'Ensures that Microsoft Azure Key Vault RSA certificates are using the allowed minimum key size.', + more_info: 'Having the right key size for your Azure Key Vault RSA certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', + recommended_action: 'Ensure that Key Vault RSA certificates are using the allowed minimum key size.', + link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/about-certificates', + apis: ['vaults:list', 'vaults:getCertificates', 'getCertificatePolicy:get'], + settings: { + min_rsa_certificate_key_size: { + name: 'Minimum RSA Certificate Allowed Key Size', + description: 'Key sizes supported for rsa certificates in Azure Key Vault', + regex: '^[1-9]{1}[0-9]{0,5}$', + default: '2048' + } + }, + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + var config = { + min_rsa_certificate_key_size: parseInt(settings.min_rsa_certificate_key_size || this.settings.min_rsa_certificate_key_size.default) + }; + + async.each(locations.vaults, function(location, rcb) { + var vaults = helpers.addSource(cache, source, + ['vaults', 'list', location]); + + if (!vaults) return rcb(); + + if (vaults.err || !vaults.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); + return rcb(); + } + + if (!vaults.data.length) { + helpers.addResult(results, 0, 'No Key Vaults found', location); + return rcb(); + } + + vaults.data.forEach((vault) => { + var certificates = helpers.addSource(cache, source, + ['vaults', 'getCertificates', location, vault.id]); + + if (!certificates || certificates.err || !certificates.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault certificates: ' + helpers.addError(certificates), location, vault.id); + } else if (!certificates.data.length) { + helpers.addResult(results, 0, 'No Key Vault Certificates found', location, vault.id); + } else { + certificates.data.forEach((certificate) => { + var certificatePolicy = helpers.addSource(cache, source, + ['getCertificatePolicy', 'get', location, certificate.id]); + + if (!certificatePolicy || certificatePolicy.err || !certificatePolicy.data) { + helpers.addResult(results, 3, 'Unable to query for Certificate Policy: ' + helpers.addError(certificatePolicy), location, certificate.id); + } else { + const certificateKeys = certificatePolicy.data.key_props; + + if (certificateKeys && certificateKeys.kty) { + if (certificateKeys.key_size >= config.min_rsa_certificate_key_size) { + helpers.addResult(results, 0, `RSA Certificate key size is ${certificateKeys.key_size}`, location, certificate.id); + } else { + helpers.addResult(results, 2, `RSA Certificate key size is ${certificateKeys.key_size}`, location, certificate.id); + } + } else { + helpers.addResult(results, 3, 'Unable to list key type for Key Vault Certificate: ' + helpers.addError(certificatePolicy), location, certificate.id); + } + } + }); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.spec.js b/plugins/azure/keyvaults/rsaCertificateKeySize.spec.js similarity index 97% rename from plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.spec.js rename to plugins/azure/keyvaults/rsaCertificateKeySize.spec.js index 89bbec5e26..46c07c66ff 100644 --- a/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.spec.js +++ b/plugins/azure/keyvaults/rsaCertificateKeySize.spec.js @@ -1,5 +1,5 @@ var expect = require('chai').expect; -var auth = require('./rsaCertificateAllowedKeySizes'); +var auth = require('./rsaCertificateKeySize'); const listVaults = [ { @@ -96,7 +96,7 @@ const createCache = (err, list, certs, getCertificatePolicy) => { } }; -describe('rsaCertificateAllowedKeySizes', function() { +describe('rsaCertificateKeySize', function() { describe('run', function() { it('should give passing result if no key vaults found', function(done) { const callback = (err, results) => { @@ -174,7 +174,7 @@ describe('rsaCertificateAllowedKeySizes', function() { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('RSA Certificate key size is within the Allowed Key Sizes'); + expect(results[0].message).to.include('RSA Certificate key size is 2048'); expect(results[0].region).to.equal('eastus'); done() }; @@ -186,7 +186,7 @@ describe('rsaCertificateAllowedKeySizes', function() { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('RSA Certificate key size is not within the Allowed Key Sizes'); + expect(results[0].message).to.include('RSA Certificate key size is 1098'); expect(results[0].region).to.equal('eastus'); done() }; From 0cf00ed823e6de67ce56aa08d08fff1c78318561 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Fri, 20 May 2022 12:25:33 +0500 Subject: [PATCH 161/350] Added disbaleOpenUDPPorts plugin --- exports.js | 1 + .../disableOpenUDPPorts.js | 79 +++++++++++++++++++ .../disableOpenUDPPorts.spec.js | 0 3 files changed, 80 insertions(+) create mode 100644 plugins/azure/networksecuritygroups/disableOpenUDPPorts.js create mode 100644 plugins/azure/networksecuritygroups/disableOpenUDPPorts.spec.js diff --git a/exports.js b/exports.js index 1c49f708a1..ee9a1b3289 100644 --- a/exports.js +++ b/exports.js @@ -691,6 +691,7 @@ module.exports = { 'openSalt' : require(__dirname + '/plugins/azure/networksecuritygroups/openSalt.js'), 'openSMBoTCP' : require(__dirname + '/plugins/azure/networksecuritygroups/openSMBoTCP.js'), 'openSQLServer' : require(__dirname + '/plugins/azure/networksecuritygroups/openSQLServer.js'), + 'disableOpenUDPPorts' : require(__dirname + '/plugins/azure/networksecuritygroups/disableOpenUDPPorts.js'), 'nsgFlowLogsRetentionPeriod' : require(__dirname + '/plugins/azure/networkwatchers/nsgFlowLogsRetentionPeriod.js'), diff --git a/plugins/azure/networksecuritygroups/disableOpenUDPPorts.js b/plugins/azure/networksecuritygroups/disableOpenUDPPorts.js new file mode 100644 index 0000000000..fe2ca61633 --- /dev/null +++ b/plugins/azure/networksecuritygroups/disableOpenUDPPorts.js @@ -0,0 +1,79 @@ +const async = require('async'); +const helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Disable Open UDP Ports', + category: 'Network Security Groups', + domain: 'Network Access Control', + description: 'Ensures that Internet exposed UDP ports on network security groups are disabled.', + more_info: 'The potential security problem with broadly exposing UDP services over the Internet is that attackers can use DDoS amplification techniques to reflect spoofed UDP traffic from Azure Virtual Machines. The most common types of these attacks use exposed DNS, NTP, SSDP, SNMP, CLDAP and other UDP-based services as amplification source for disrupting services of other machines on the Azure Virtual Network or even attack networked devices outside of Azure.', + link: 'https://docs.microsoft.com/en-us/azure/security/benchmarks/security-controls-v2-network-security#ns-1-implement-security-for-internal-traffic', + recommended_action: 'Disable direct UDP access to your Azure Virtual Machines from the Internet', + apis: ['networkSecurityGroups:listAll'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + + async.each(locations.networkSecurityGroups, function(location, rcb) { + + let networkSecurityGroups = helpers.addSource( + cache, source, ['networkSecurityGroups', 'listAll', location] + ); + + if (!networkSecurityGroups) return rcb(); + + if (networkSecurityGroups.err || !networkSecurityGroups.data) { + helpers.addResult(results, 3, + 'Unable to query for Network Security Groups: ' + helpers.addError(networkSecurityGroups), location); + return rcb(); + } + + if (!networkSecurityGroups.data.length) { + helpers.addResult(results, 0, 'No security groups found', location); + return rcb(); + } + + for (let s in networkSecurityGroups.data) { + var sg = networkSecurityGroups.data[s]; + + let openUdpPorts = false; + if (sg.securityRules && + sg.securityRules.length) { + let InvalidSourceAddressPrefixes = ['*', '0.0.0.0', '/0', '/0', 'internet', 'any']; + + var accessRules = sg.securityRules.filter((rule) => { + return (rule.properties && + rule.properties.access && + rule.properties.access.toLowerCase() == 'allow' && + rule.properties.direction.toLowerCase() === 'inboud' && + rule.properties.protocol.toLowerCase() === 'udp'); + }); + + for (var rule in accessRules) { + if (!accessRules[rule].properties) continue; + + let dRule = accessRules[rule].properties; + + if (dRule.sourceAddressPrefix && + InvalidSourceAddressPrefixes.indexOf(dRule.sourceAddressPrefix) > -1) { + openUdpPorts = true; + } + } + + if (openUdpPorts) { + helpers.addResult(results, 2, + 'The security group: ' + sg.name + ' has open UDP ports for internet access', location, sg.id); + } else { + helpers.addResult(results, 0, + 'The security group: ' + sg.name + ' does not have open UDP ports for internet access', location, sg.id); + } + } + } + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/networksecuritygroups/disableOpenUDPPorts.spec.js b/plugins/azure/networksecuritygroups/disableOpenUDPPorts.spec.js new file mode 100644 index 0000000000..e69de29bb2 From 2a1dbf53b5554545c90dc6a9caac6f0d1dcfe8c3 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 14:48:02 +0500 Subject: [PATCH 162/350] PR changes fix --- .../azure/keyvaults/sslCertificateAutoRenewal.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/plugins/azure/keyvaults/sslCertificateAutoRenewal.js b/plugins/azure/keyvaults/sslCertificateAutoRenewal.js index f25f35409b..918ebf36db 100644 --- a/plugins/azure/keyvaults/sslCertificateAutoRenewal.js +++ b/plugins/azure/keyvaults/sslCertificateAutoRenewal.js @@ -4,9 +4,9 @@ var helpers = require('../../../helpers/azure'); module.exports = { title: 'SSL Certificate Auto Renewal', category: 'Key Vaults', - domain: 'Identity and Access Management', - description: 'Ensures that Microsoft Azure Key Vault SSL certificates auto renewal is enabled.', - more_info: 'Configure SSL certificates for auto renewal in order to prevent any application or service outage, credential leak, or process violation that can disrupt your business.', + domain: 'Application Integration', + description: 'Ensures that Microsoft Azure Key Vault SSL certificates have auto renewal enabled.', + more_info: 'Configure auto renewal for SSL certificates in order to prevent any application or service outage, credential leak, or process violation that can disrupt your business.', recommended_action: 'Ensure that Key Vault SSL certificates are configured to have auto renewal enabled.', link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/overview-renew-certificate', apis: ['vaults:list', 'vaults:getCertificates', 'getCertificatePolicy:get'], @@ -48,14 +48,11 @@ module.exports = { if (!certificatePolicy || certificatePolicy.err || !certificatePolicy.data) { helpers.addResult(results, 3, 'Unable to query for Certificate Policy: ' + helpers.addError(certificatePolicy), location, certificate.id); } else { - let autoRenew = false; const lifetimeActions = certificatePolicy.data.lifetime_actions; - lifetimeActions.forEach(({ action }) => { - if (action.action_type.toLowerCase() === 'autorenew') { - autoRenew = true; - } - }); + let autoRenew = lifetimeActions && lifetimeActions.find(lifetimeAction => + lifetimeAction.action && lifetimeAction.action.action_type && + lifetimeAction.action.action_type.toLowerCase() == 'autorenew'); if (autoRenew) { helpers.addResult(results, 0, 'SSL Certificate auto renewal is enabled', location, certificate.id); From dfb6253ba0ced6977d9a7b17cf32492cf68b0f52 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 15:18:06 +0500 Subject: [PATCH 163/350] fix pr changes --- exports.js | 2 +- ...rmissions.js => manageKeyAccessAndPermissions.js} | 12 ++++++------ ...spec.js => manageKeyAccessAndPermissions.spec.js} | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) rename plugins/azure/keyvaults/{manageAccessAndPermissions.js => manageKeyAccessAndPermissions.js} (87%) rename plugins/azure/keyvaults/{manageAccessAndPermissions.spec.js => manageKeyAccessAndPermissions.spec.js} (95%) diff --git a/exports.js b/exports.js index fe2acb7335..1e720e9c09 100644 --- a/exports.js +++ b/exports.js @@ -755,7 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), - 'manageAccessAndPermissions' : require(__dirname + '/plugins/azure/keyvaults/manageAccessAndPermissions.js'), + 'manageKeyAccessAndPermissions' : require(__dirname + '/plugins/azure/keyvaults/manageKeyAccessAndPermissions.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/manageAccessAndPermissions.js b/plugins/azure/keyvaults/manageKeyAccessAndPermissions.js similarity index 87% rename from plugins/azure/keyvaults/manageAccessAndPermissions.js rename to plugins/azure/keyvaults/manageKeyAccessAndPermissions.js index 72ca856c1d..d0234cc2fa 100644 --- a/plugins/azure/keyvaults/manageAccessAndPermissions.js +++ b/plugins/azure/keyvaults/manageKeyAccessAndPermissions.js @@ -3,11 +3,11 @@ var helpers = require('../../../helpers/azure'); var _ = require('underscore'); module.exports = { - title: 'Manage Access and Permissions', + title: 'Manage Key Access and Permissions', category: 'Key Vaults', - domain: 'Identity and Access Management', - description: 'Ensures that there is no Microsoft Azure user, group or application with full administrator privileges.', - more_info: 'Having the right key type set for your Azure Key Vault SSL certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', + domain: 'Application Integration', + description: 'Ensures that no Microsoft Azure user, group or application with full administrator privileges to the Key Vaults.', + more_info: 'A principal such as a user, group or application should have access to execute only specific operations for Azure Key Vault keys, secrets or certificates as a security best practice.', recommended_action: 'Ensure that no Microsoft Azure user, group or application is using administrator privileges.', link: 'https://docs.microsoft.com/en-us/azure/key-vault/general/rbac-guide?tabs=azure-cli', apis: ['vaults:list'], @@ -105,10 +105,10 @@ module.exports = { if (policyFound) { helpers.addResult(results, 2, - 'User/Group or Application has full access to the specified vault', location, vault.id); + 'User/Group or Application has full access to the vault', location, vault.id); } else { helpers.addResult(results, 0, - 'No User/Group or Application has full access to the specified vault', location, vault.id); + 'No User/Group or Application has full access to the vault', location, vault.id); } }); diff --git a/plugins/azure/keyvaults/manageAccessAndPermissions.spec.js b/plugins/azure/keyvaults/manageKeyAccessAndPermissions.spec.js similarity index 95% rename from plugins/azure/keyvaults/manageAccessAndPermissions.spec.js rename to plugins/azure/keyvaults/manageKeyAccessAndPermissions.spec.js index 62f2af3ea8..7bcd858e55 100644 --- a/plugins/azure/keyvaults/manageAccessAndPermissions.spec.js +++ b/plugins/azure/keyvaults/manageKeyAccessAndPermissions.spec.js @@ -1,5 +1,5 @@ var expect = require('chai').expect; -var auth = require('./manageAccessAndPermissions'); +var auth = require('./manageKeyAccessAndPermissions'); const listVaults = [ { @@ -137,7 +137,7 @@ const createCache = (err, list, get) => { } }; -describe('manageAccessAndPermissions', function() { +describe('manageKeyAccessAndPermissions', function() { describe('run', function() { it('should give passing result if no key vaults found', function(done) { const callback = (err, results) => { @@ -167,7 +167,7 @@ describe('manageAccessAndPermissions', function() { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No User/Group or Application has full access to the specified vault'); + expect(results[0].message).to.include('No User/Group or Application has full access to the vault'); expect(results[0].region).to.equal('eastus'); done() }; @@ -175,11 +175,11 @@ describe('manageAccessAndPermissions', function() { auth.run(createCache(null, [listVaults[0]]), {}, callback); }); - it('should give failing result if a User/Group or Application has full access to the specified vault', function(done) { + it('should give failing result if a User/Group or Application has full access to the vault', 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('User/Group or Application has full access to the specified vault'); + expect(results[0].message).to.include('User/Group or Application has full access to the vault'); expect(results[0].region).to.equal('eastus'); done() }; From 26087aea941e96b60de95a9ca3b37c0230e082ee Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 20 May 2022 15:35:53 +0500 Subject: [PATCH 164/350] Update plugins/azure/keyvaults/manageKeyAccessAndPermissions.js --- plugins/azure/keyvaults/manageKeyAccessAndPermissions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/keyvaults/manageKeyAccessAndPermissions.js b/plugins/azure/keyvaults/manageKeyAccessAndPermissions.js index d0234cc2fa..3f7305cab4 100644 --- a/plugins/azure/keyvaults/manageKeyAccessAndPermissions.js +++ b/plugins/azure/keyvaults/manageKeyAccessAndPermissions.js @@ -6,7 +6,7 @@ module.exports = { title: 'Manage Key Access and Permissions', category: 'Key Vaults', domain: 'Application Integration', - description: 'Ensures that no Microsoft Azure user, group or application with full administrator privileges to the Key Vaults.', + description: 'Ensures that no Microsoft Azure user, group or application has administrator privileges to the Key Vaults.', more_info: 'A principal such as a user, group or application should have access to execute only specific operations for Azure Key Vault keys, secrets or certificates as a security best practice.', recommended_action: 'Ensure that no Microsoft Azure user, group or application is using administrator privileges.', link: 'https://docs.microsoft.com/en-us/azure/key-vault/general/rbac-guide?tabs=azure-cli', From 8db2ae7e9d5b4021faa379ecec27645004604a35 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 16:04:07 +0500 Subject: [PATCH 165/350] fix pr change --- exports.js | 2 +- ...atabaseTier.js => databaseTierCmkInuse.js} | 61 +++++++++---------- ...r.spec.js => databaseTierCmkInuse.spec.js} | 44 +++++-------- 3 files changed, 46 insertions(+), 61 deletions(-) rename plugins/azure/keyvaults/{cmkCreationForDatabaseTier.js => databaseTierCmkInuse.js} (52%) rename plugins/azure/keyvaults/{cmkCreationForDatabaseTier.spec.js => databaseTierCmkInuse.spec.js} (72%) diff --git a/exports.js b/exports.js index 6b7621f385..e26daf8908 100644 --- a/exports.js +++ b/exports.js @@ -755,7 +755,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), - 'cmkCreationForDatabaseTier' : require(__dirname + '/plugins/azure/keyvaults/cmkCreationForDatabaseTier.js'), + 'databaseTierCmkInUse' : require(__dirname + '/plugins/azure/keyvaults/databaseTierCmkInUse.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/cmkCreationForDatabaseTier.js b/plugins/azure/keyvaults/databaseTierCmkInuse.js similarity index 52% rename from plugins/azure/keyvaults/cmkCreationForDatabaseTier.js rename to plugins/azure/keyvaults/databaseTierCmkInuse.js index b4e3849559..08d8099047 100644 --- a/plugins/azure/keyvaults/cmkCreationForDatabaseTier.js +++ b/plugins/azure/keyvaults/databaseTierCmkInuse.js @@ -1,23 +1,21 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); -var _ = require('underscore'); module.exports = { - title: 'CMK Creation for Database Tier Enabled', + title: 'Database Tier CMK In Use', category: 'Key Vaults', - domain: 'Identity and Access Management', - description: 'Ensures that a Customer-Managed Key (CMK) is created and configured for your Microsoft Azure database tier.', + domain: 'Application Integration', + description: 'Ensure that a Customer-Managed Key (CMK) is created and configured for your Microsoft Azure application tier.', more_info: 'Setting a CMK for database tier, you gain full control over who can use this key to access the database tier data, implementing the principle of least privilege on the encryption key ownership and usage.', - recommended_action: 'Ensure each Key Vault has a CMK created and configured for database tier.', + recommended_action: 'Ensure a CMK created and configured for database tier in each region.', link: 'https://docs.microsoft.com/en-us/azure/azure-sql/database/transparent-data-encryption-byok-overview?view=azuresql', apis: ['vaults:list', 'vaults:getKeys'], settings: { - database_tier_tag_sets: { - name: 'Database Tier Tag Sets', - description: 'An object of allowed tag set key value pairs to use for the CMKs creation for Database Tier', - // eslint-disable-next-line no-useless-escape - regex: '/("?)\b(\w+)\1\s*:\s*("?)((?:\w+[-+*%])*?\w+)\b\3/g', - default: {} + db_tier_tag_key: { + name: 'Database-Tier Tag Key', + description: 'Tag key to indicate Database-Tier Key Vault keys', + regex: '^.*$s', + default: '' } }, @@ -26,9 +24,11 @@ module.exports = { var source = {}; var locations = helpers.locations(settings.govcloud); var config = { - database_tier_tag_sets: settings.database_tier_tag_sets || this.settings.database_tier_tag_sets.default + db_tier_tag_key: settings.db_tier_tag_key || this.settings.db_tier_tag_key.default }; + if (!config.db_tier_tag_key.length) return callback(null, results, source); + async.each(locations.vaults, function(location, rcb) { var vaults = helpers.addSource(cache, source, ['vaults', 'list', location]); @@ -41,43 +41,40 @@ module.exports = { } if (!vaults.data.length) { - helpers.addResult(results, 0, 'No Key Vaults found', location); + helpers.addResult(results, 2, 'No Key Vaults found', location); return rcb(); } + let dbTierKey; vaults.data.forEach((vault) => { var keys = helpers.addSource(cache, source, ['vaults', 'getKeys', location, vault.id]); if (!keys || keys.err || !keys.data) { helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); - } else if (!keys.data.length) { - helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); - } else { - keys.data.forEach((key) => { + return; + } + + if (keys.data.length) { + for (let key of keys.data) { var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); var keyId = `${vault.id}/keys/${keyName}`; - if (key.tags) { - const tags = key.tags; - const allowedTagSets = config.database_tier_tag_sets; - const result = _.pick(tags, (v, k) => _.isEqual(allowedTagSets[k], v)); - - if (Object.entries(result).length) { - helpers.addResult(results, 0, - 'CMK Creation for Database Tier is enabled', location, keyId); - } else { - helpers.addResult(results, 2, - 'CMK Creation for Database Tier is disabled', location, keyId); + if (Object.keys(key.tags).includes(config.db_tier_tag_key)) { + dbTierKey = keyId; + break; } - } else { - helpers.addResult(results, 2, - 'CMK Creation for Database Tier is disabled', location, keyId); } - }); + } } }); + if (dbTierKey) { + helpers.addResult(results, 0, `CMK exists for database tier: ${dbTierKey}`, location); + } else { + helpers.addResult(results, 2, 'CMK does not exist for database tier', location); + } + rcb(); }, function() { callback(null, results, source); diff --git a/plugins/azure/keyvaults/cmkCreationForDatabaseTier.spec.js b/plugins/azure/keyvaults/databaseTierCmkInuse.spec.js similarity index 72% rename from plugins/azure/keyvaults/cmkCreationForDatabaseTier.spec.js rename to plugins/azure/keyvaults/databaseTierCmkInuse.spec.js index 117688be92..fe70b57afa 100644 --- a/plugins/azure/keyvaults/cmkCreationForDatabaseTier.spec.js +++ b/plugins/azure/keyvaults/databaseTierCmkInuse.spec.js @@ -1,5 +1,5 @@ var expect = require('chai').expect; -var auth = require('./cmkCreationForDatabaseTier'); +var auth = require('./databaseTierCmkInUse'); const listVaults = [ { @@ -37,7 +37,7 @@ const getKeys = [ "recoveryLevel": "Recoverable+Purgeable" }, "tags": { - "Owner": "AzSQLManager" + "databasetier": "db-rier" } }, { @@ -73,18 +73,18 @@ const createCache = (err, list, keys) => { } }; -describe('cmkCreationForDatabaseTier', function() { +describe('databaseTierCmkInUse', function() { describe('run', function() { - it('should give passing result if no key vaults found', function(done) { + it('should give failing result if no key vaults found', function(done) { const callback = (err, results) => { expect(results.length).to.equal(1); - expect(results[0].status).to.equal(0); + expect(results[0].status).to.equal(2); expect(results[0].message).to.include('No Key Vaults found'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [], {}), {}, callback); + auth.run(createCache(null, [], {}), { db_tier_tag_key: 'dbtier' }, callback); }); it('should give unkown result if Unable to query for Key Vaults', function(done) { @@ -96,55 +96,43 @@ describe('cmkCreationForDatabaseTier', function() { done() }; - auth.run(createCache(null, null, {}), {}, callback); - }); - - it('should give passing result if no key vault keys 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 Key Vault keys found'); - expect(results[0].region).to.equal('eastus'); - done() - }; - - auth.run(createCache(null, [listVaults[0]], []), {}, callback); + auth.run(createCache(null, null, {}), { db_tier_tag_key: 'dbtier' }, callback); }); it('should give unkown result if Unable to query for Key Vaults keys', function(done) { const callback = (err, results) => { - expect(results.length).to.equal(1); + expect(results.length).to.equal(2); expect(results[0].status).to.equal(3); expect(results[0].message).to.include('Unable to query for Key Vault keys'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listVaults[0]], null), {}, callback); + auth.run(createCache(null, [listVaults[0]], null), { db_tier_tag_key: 'dbtier' }, callback); }); - it('should give passing result if CMK Creation for Database Tier is enabled', function(done) { + it('should give passing result if CMK exists for database tier', 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('CMK Creation for Database Tier is enabled'); + expect(results[0].message).to.include('CMK exists for database tier'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listVaults[1]], [getKeys[0]]), { database_tier_tag_sets: { Owner: 'AzSQLManager' } }, callback); + auth.run(createCache(null, [listVaults[1]], [getKeys[0]]), { db_tier_tag_key: 'databasetier' }, callback); }); - it('should give failing result if CMK Creation for Database Tier is disabled', function(done) { + it('should give failing result if CMK does not exist for database tier', 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('CMK Creation for Database Tier is disabled'); + expect(results[0].message).to.include('CMK does not exist for database tier'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, [listVaults[1]], [getKeys[0]]), {}, callback); + auth.run(createCache(null, [listVaults[1]], [getKeys[0]]), { db_tier_tag_key: 'dbtire' }, callback); }) }) -}); +}); \ No newline at end of file From eadd07c8e89f1ad5fc5b8e3c3bb1c9ba650046b9 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 16:13:18 +0500 Subject: [PATCH 166/350] pr changes --- .../{databaseTierCmkInuse.js => databaseTierCmkInUse.js} | 0 ...{databaseTierCmkInuse.spec.js => databaseTierCmkInUse.spec.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename plugins/azure/keyvaults/{databaseTierCmkInuse.js => databaseTierCmkInUse.js} (100%) rename plugins/azure/keyvaults/{databaseTierCmkInuse.spec.js => databaseTierCmkInUse.spec.js} (100%) diff --git a/plugins/azure/keyvaults/databaseTierCmkInuse.js b/plugins/azure/keyvaults/databaseTierCmkInUse.js similarity index 100% rename from plugins/azure/keyvaults/databaseTierCmkInuse.js rename to plugins/azure/keyvaults/databaseTierCmkInUse.js diff --git a/plugins/azure/keyvaults/databaseTierCmkInuse.spec.js b/plugins/azure/keyvaults/databaseTierCmkInUse.spec.js similarity index 100% rename from plugins/azure/keyvaults/databaseTierCmkInuse.spec.js rename to plugins/azure/keyvaults/databaseTierCmkInUse.spec.js From 42edf20f2d72eaff2794dc0af2cd39f44a61c369 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 20:06:38 +0500 Subject: [PATCH 167/350] Added Azure enableDefenderForSqlServers plugin --- collectors/azure/collector.js | 2 +- exports.js | 2 + .../defender/enableDefenderForSqlServers.js | 53 +++++++++++ .../enableDefenderForSqlServers.spec.js | 87 +++++++++++++++++++ 4 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 plugins/azure/defender/enableDefenderForSqlServers.js create mode 100644 plugins/azure/defender/enableDefenderForSqlServers.spec.js diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index a559f259b1..5cbb7cef29 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -177,7 +177,7 @@ var calls = { }, pricings: { list: { - url: 'https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Security/pricings?api-version=2018-06-01' + url: 'https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Security/pricings?api-version=2022-03-01' } }, availabilitySets: { diff --git a/exports.js b/exports.js index 1c49f708a1..bb040a2e39 100644 --- a/exports.js +++ b/exports.js @@ -760,6 +760,8 @@ module.exports = { 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), 'automaticFailoverEnabled' : require(__dirname + '/plugins/azure/cosmosdb/automaticFailoverEnabled.js'), + + 'enableDefenderForSqlServers' : require(__dirname + '/plugins/azure/defender/enableDefenderForSqlServers.js') }, github: { 'publicKeysRotated' : require(__dirname + '/plugins/github/users/publicKeysRotated.js'), diff --git a/plugins/azure/defender/enableDefenderForSqlServers.js b/plugins/azure/defender/enableDefenderForSqlServers.js new file mode 100644 index 0000000000..bca9c10360 --- /dev/null +++ b/plugins/azure/defender/enableDefenderForSqlServers.js @@ -0,0 +1,53 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Enable Defender For SQL Servers', + category: 'Defender', + domain: 'Management and Governance', + description: 'Ensures that Microsoft Defender is enabled for Azure SQL Server Databases.', + more_info: 'Turning on Microsoft Defender for Azure SQL Server Databases enables threat detection for Azure SQL database servers, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.', + recommended_action: 'Turning on Microsoft Defender for Azure SQL Databases incurs an additional cost per resource.', + link: 'https://docs.microsoft.com/en-us/azure/security-center/security-center-detection-capabilities', + apis: ['pricings:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.pricings, function(location, rcb) { + var pricings = helpers.addSource(cache, source, + ['pricings', 'list', location]); + + if (!pricings) return rcb(); + + if (pricings.err || !pricings.data) { + helpers.addResult(results, 3, + 'Unable to query for Pricing: ' + helpers.addError(pricings), location); + return rcb(); + } + + if (!pricings.data.length) { + helpers.addResult(results, 0, 'No Pricing information found', location); + return rcb(); + } + + let sqlServersPricing = pricings.data.find((pricing) => pricing.name && pricing.name.toLowerCase() === 'sqlservers'); + + if (sqlServersPricing) { + if (sqlServersPricing.pricingTier.toLowerCase() === 'standard') { + helpers.addResult(results, 0, 'Azure Defender is enabled for SQL Server Databases', location, sqlServersPricing.id); + } else { + helpers.addResult(results, 2, 'Azure Defender is not enabled for SQL Server Databases', location, sqlServersPricing.id); + } + } else { + helpers.addResult(results, 2, 'Azure Defender is not enabled for SQL Server Databases', location); + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/defender/enableDefenderForSqlServers.spec.js b/plugins/azure/defender/enableDefenderForSqlServers.spec.js new file mode 100644 index 0000000000..26a315964e --- /dev/null +++ b/plugins/azure/defender/enableDefenderForSqlServers.spec.js @@ -0,0 +1,87 @@ +var assert = require('assert'); +var expect = require('chai').expect; +var auth = require('./enableDefenderForSqlServers'); + +const createCache = (err, data) => { + return { + pricings: { + list: { + 'global': { + err: err, + data: data + } + } + } + } +}; + +describe('enableDefenderForSqlDatabases', function() { + describe('run', function() { + it('should give passing result if no pricings 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 Pricing information found'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [] + ); + + auth.run(cache, {}, callback); + }); + + it('should give failing result if Azure Defender for SQL Server Databases is not enabled', 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('Azure Defender is not enabled for SQL Server Databases'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [ + { + "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/providers/Microsoft.Security/pricings/default", + "name": "SqlServers", + "type": "Microsoft.Security/pricings", + "pricingTier": "free", + "location": "global" + } + ] + ); + + auth.run(cache, {}, callback); + }); + + it('should give passing result if Azure Defender for SQL Server Databases is enabled', 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('Azure Defender is enabled for SQL Server Databases'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [ + { + "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/providers/Microsoft.Security/pricings/default", + "name": "SqlServers", + "type": "Microsoft.Security/pricings", + "pricingTier": "Standard", + "location": "global" + } + ] + ); + + auth.run(cache, {}, callback); + }) + }) +}); \ No newline at end of file From 11f1fe9b2c38a5bf7504d1565d1827c365971f80 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 20:17:38 +0500 Subject: [PATCH 168/350] changed few things --- .../azure/defender/enableDefenderForSqlServers.js | 14 +++++++------- .../defender/enableDefenderForSqlServers.spec.js | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/plugins/azure/defender/enableDefenderForSqlServers.js b/plugins/azure/defender/enableDefenderForSqlServers.js index bca9c10360..dbad58a96e 100644 --- a/plugins/azure/defender/enableDefenderForSqlServers.js +++ b/plugins/azure/defender/enableDefenderForSqlServers.js @@ -5,10 +5,10 @@ module.exports = { title: 'Enable Defender For SQL Servers', category: 'Defender', domain: 'Management and Governance', - description: 'Ensures that Microsoft Defender is enabled for Azure SQL Server Databases.', - more_info: 'Turning on Microsoft Defender for Azure SQL Server Databases enables threat detection for Azure SQL database servers, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.', - recommended_action: 'Turning on Microsoft Defender for Azure SQL Databases incurs an additional cost per resource.', - link: 'https://docs.microsoft.com/en-us/azure/security-center/security-center-detection-capabilities', + description: 'Ensures that Microsoft Defender is enabled for SQL Servers.', + more_info: 'Turning on Microsoft Defender for SQL Servers enables threat detection for Azure SQL database servers, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.', + recommended_action: 'Enable Microsoft Defender for SQL Servers in Defender plans for the subscription.', + link: 'https://docs.microsoft.com/en-us/azure/defender-for-cloud/defender-for-sql-introduction', apis: ['pricings:list'], run: function(cache, settings, callback) { @@ -37,12 +37,12 @@ module.exports = { if (sqlServersPricing) { if (sqlServersPricing.pricingTier.toLowerCase() === 'standard') { - helpers.addResult(results, 0, 'Azure Defender is enabled for SQL Server Databases', location, sqlServersPricing.id); + helpers.addResult(results, 0, 'Azure Defender is enabled for SQL Servers', location, sqlServersPricing.id); } else { - helpers.addResult(results, 2, 'Azure Defender is not enabled for SQL Server Databases', location, sqlServersPricing.id); + helpers.addResult(results, 2, 'Azure Defender is not enabled for SQL Servers', location, sqlServersPricing.id); } } else { - helpers.addResult(results, 2, 'Azure Defender is not enabled for SQL Server Databases', location); + helpers.addResult(results, 2, 'Azure Defender is not enabled for SQL Servers', location); } rcb(); diff --git a/plugins/azure/defender/enableDefenderForSqlServers.spec.js b/plugins/azure/defender/enableDefenderForSqlServers.spec.js index 26a315964e..20c73cf1ae 100644 --- a/plugins/azure/defender/enableDefenderForSqlServers.spec.js +++ b/plugins/azure/defender/enableDefenderForSqlServers.spec.js @@ -34,11 +34,11 @@ describe('enableDefenderForSqlDatabases', function() { auth.run(cache, {}, callback); }); - it('should give failing result if Azure Defender for SQL Server Databases is not enabled', function(done) { + it('should give failing result if Azure Defender for SQL Servers is not enabled', 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('Azure Defender is not enabled for SQL Server Databases'); + expect(results[0].message).to.include('Azure Defender is not enabled for SQL Servers'); expect(results[0].region).to.equal('global'); done() }; @@ -59,11 +59,11 @@ describe('enableDefenderForSqlDatabases', function() { auth.run(cache, {}, callback); }); - it('should give passing result if Azure Defender for SQL Server Databases is enabled', function(done) { + it('should give passing result if Azure Defender for SQL Servers is enabled', 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('Azure Defender is enabled for SQL Server Databases'); + expect(results[0].message).to.include('Azure Defender is enabled for SQL Servers'); expect(results[0].region).to.equal('global'); done() }; From c56c28336486a612a3b86286374d2d4260c899f1 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 20:42:03 +0500 Subject: [PATCH 169/350] Added Azure keyVaultInUse plugin --- exports.js | 1 + plugins/azure/keyvaults/keyVaultInUse.js | 69 +++++++++++ plugins/azure/keyvaults/keyVaultInUse.spec.js | 110 ++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 plugins/azure/keyvaults/keyVaultInUse.js create mode 100644 plugins/azure/keyvaults/keyVaultInUse.spec.js diff --git a/exports.js b/exports.js index bb040a2e39..2be52a4268 100644 --- a/exports.js +++ b/exports.js @@ -756,6 +756,7 @@ module.exports = { 'kvRecoveryEnabled' : require(__dirname + '/plugins/azure/keyvaults/kvRecoveryEnabled.js'), 'keyExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyExpirationEnabled.js'), 'secretExpirationEnabled' : require(__dirname + '/plugins/azure/keyvaults/secretExpirationEnabled.js'), + 'keyVaultInUse' : require(__dirname + '/plugins/azure/keyvaults/keyVaultInUse.js'), 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), diff --git a/plugins/azure/keyvaults/keyVaultInUse.js b/plugins/azure/keyvaults/keyVaultInUse.js new file mode 100644 index 0000000000..2e76596ade --- /dev/null +++ b/plugins/azure/keyvaults/keyVaultInUse.js @@ -0,0 +1,69 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Key Vault In Use', + category: 'Key Vaults', + domain: 'Application Integration', + description: 'Ensures that Key Vaults are being used to store secrets.', + more_info: 'App secrets control access to the application and thus need to be secured externally to the app configuration, storing the secrets externally and referencing them in the configuration also enables key rotation without having to redeploy the app service.', + recommended_action: 'Ensure that Azure Key Vaults are being used to store secrets.', + link: 'https://docs.microsoft.com/en-us/azure/app-service/app-service-key-vault-references', + apis: ['vaults:list', 'vaults:getKeys'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.vaults, function(location, rcb) { + var vaults = helpers.addSource(cache, source, + ['vaults', 'list', location]); + + if (!vaults) return rcb(); + + if (vaults.err || !vaults.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); + return rcb(); + } + + if (!vaults.data.length) { + helpers.addResult(results, 2, 'Key Vaults are not being used to store secrets', location); + return rcb(); + } + + let keyVaultsBeingUsed = false; + for (let vault of vaults.data) { + var keys = helpers.addSource(cache, source, + ['vaults', 'getKeys', location, vault.id]); + + var secrets = helpers.addSource(cache, source, + ['vaults', 'getSecrets', location, vault.id]); + + if (!keys || keys.err || !keys.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); + } else if (keys.data.length) { + keyVaultsBeingUsed = true; + break; + } + + if (!secrets || secrets.err || !secrets.data) { + helpers.addResult(results, 3, 'Unable to query for Key Vault secrets: ' + helpers.addError(secrets), location, vault.id); + } else if (secrets.data.length) { + keyVaultsBeingUsed = true; + break; + } + } + + if (keyVaultsBeingUsed) { + helpers.addResult(results, 0, 'Key Vaults are being used to store secrets', location); + } else { + helpers.addResult(results, 2, 'Key Vaults are not being used to store secrets', location); + } + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/keyvaults/keyVaultInUse.spec.js b/plugins/azure/keyvaults/keyVaultInUse.spec.js new file mode 100644 index 0000000000..9baffbc9b4 --- /dev/null +++ b/plugins/azure/keyvaults/keyVaultInUse.spec.js @@ -0,0 +1,110 @@ +var expect = require('chai').expect; +var auth = require('./keyVaultInUse'); + +const listKeyVaults = [ + { + id: '/subscriptions/qdn32rdm-ebf6-437f-a3b0-28fc0d22111e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/nauman-test', + name: 'nauman-test', + type: 'Microsoft.KeyVault/vaults', + location: 'eastus', + tags: { owner: 'kubernetes' }, + sku: { family: 'A', name: 'Standard' }, + tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', + accessPolicies: [ + { + tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', + objectId: 'b4062000-c33b-448b-817e-fa0f17bef4b9', + permissions: { + keys: ['Get', 'List'], + secrets: ['Get', 'List'], + certificates: ['Get', 'List'] + } + } + ], + enableSoftDelete: true, + softDeleteRetentionInDays: 7, + enableRbacAuthorization: false, + vaultUri: 'https://nauman-test.vault.azure.net/', + provisioningState: 'Succeeded' + } +]; + +const getKeys = [ + { + "attributes": { + "created": "2022-04-10T17:57:43+00:00", + "enabled": true, + "expires": null, + "notBefore": null, + "recoveryLevel": "CustomizedRecoverable+Purgeable", + "updated": "2022-04-10T17:57:43+00:00" + }, + "kid": "https://nauman-test.vault.azure.net/keys/nauman-test", + "managed": null, + "name": "nauman-test", + "tags": { + "hello": "world" + } + } +]; + +const createCache = (err, list, keys) => { + return { + vaults: { + list: { + 'eastus': { + err: err, + data: list + } + }, + getKeys: { + 'eastus': { + '/subscriptions/qdn32rdm-ebf6-437f-a3b0-28fc0d22111e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/nauman-test': { + err: err, + data: keys + } + } + } + } + } +}; + +describe('keyVaultInUse', function() { + describe('run', function() { + it('should give failing result if no key vaults found', 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('Key Vaults are not being used to store secrets'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [], {}), {}, callback); + }); + + it('should give passing result if key vaults are being used to store secrets', 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('Key Vaults are being used to store secrets'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [listKeyVaults[0]], [getKeys[0]]), {}, callback); + }); + + it('should give failing result if no keys in key vaults found', 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('Key Vaults are not being used to store secrets'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + auth.run(createCache(null, [], {}), {}, callback); + }); + }); +}); \ No newline at end of file From eea4c368bbfac344b1cad045b5835bb119a7f0d4 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 20:45:33 +0500 Subject: [PATCH 170/350] removed extra files --- collectors/azure/collector.js | 2 +- exports.js | 2 - .../defender/enableDefenderForSqlServers.js | 53 ----------- .../enableDefenderForSqlServers.spec.js | 87 ------------------- 4 files changed, 1 insertion(+), 143 deletions(-) delete mode 100644 plugins/azure/defender/enableDefenderForSqlServers.js delete mode 100644 plugins/azure/defender/enableDefenderForSqlServers.spec.js diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index 5cbb7cef29..a559f259b1 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -177,7 +177,7 @@ var calls = { }, pricings: { list: { - url: 'https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Security/pricings?api-version=2022-03-01' + url: 'https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Security/pricings?api-version=2018-06-01' } }, availabilitySets: { diff --git a/exports.js b/exports.js index 2be52a4268..390b708888 100644 --- a/exports.js +++ b/exports.js @@ -761,8 +761,6 @@ module.exports = { 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), 'automaticFailoverEnabled' : require(__dirname + '/plugins/azure/cosmosdb/automaticFailoverEnabled.js'), - - 'enableDefenderForSqlServers' : require(__dirname + '/plugins/azure/defender/enableDefenderForSqlServers.js') }, github: { 'publicKeysRotated' : require(__dirname + '/plugins/github/users/publicKeysRotated.js'), diff --git a/plugins/azure/defender/enableDefenderForSqlServers.js b/plugins/azure/defender/enableDefenderForSqlServers.js deleted file mode 100644 index dbad58a96e..0000000000 --- a/plugins/azure/defender/enableDefenderForSqlServers.js +++ /dev/null @@ -1,53 +0,0 @@ -var async = require('async'); -var helpers = require('../../../helpers/azure'); - -module.exports = { - title: 'Enable Defender For SQL Servers', - category: 'Defender', - domain: 'Management and Governance', - description: 'Ensures that Microsoft Defender is enabled for SQL Servers.', - more_info: 'Turning on Microsoft Defender for SQL Servers enables threat detection for Azure SQL database servers, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.', - recommended_action: 'Enable Microsoft Defender for SQL Servers in Defender plans for the subscription.', - link: 'https://docs.microsoft.com/en-us/azure/defender-for-cloud/defender-for-sql-introduction', - apis: ['pricings:list'], - - run: function(cache, settings, callback) { - var results = []; - var source = {}; - var locations = helpers.locations(settings.govcloud); - - async.each(locations.pricings, function(location, rcb) { - var pricings = helpers.addSource(cache, source, - ['pricings', 'list', location]); - - if (!pricings) return rcb(); - - if (pricings.err || !pricings.data) { - helpers.addResult(results, 3, - 'Unable to query for Pricing: ' + helpers.addError(pricings), location); - return rcb(); - } - - if (!pricings.data.length) { - helpers.addResult(results, 0, 'No Pricing information found', location); - return rcb(); - } - - let sqlServersPricing = pricings.data.find((pricing) => pricing.name && pricing.name.toLowerCase() === 'sqlservers'); - - if (sqlServersPricing) { - if (sqlServersPricing.pricingTier.toLowerCase() === 'standard') { - helpers.addResult(results, 0, 'Azure Defender is enabled for SQL Servers', location, sqlServersPricing.id); - } else { - helpers.addResult(results, 2, 'Azure Defender is not enabled for SQL Servers', location, sqlServersPricing.id); - } - } else { - helpers.addResult(results, 2, 'Azure Defender is not enabled for SQL Servers', location); - } - - rcb(); - }, function(){ - callback(null, results, source); - }); - } -}; \ No newline at end of file diff --git a/plugins/azure/defender/enableDefenderForSqlServers.spec.js b/plugins/azure/defender/enableDefenderForSqlServers.spec.js deleted file mode 100644 index 20c73cf1ae..0000000000 --- a/plugins/azure/defender/enableDefenderForSqlServers.spec.js +++ /dev/null @@ -1,87 +0,0 @@ -var assert = require('assert'); -var expect = require('chai').expect; -var auth = require('./enableDefenderForSqlServers'); - -const createCache = (err, data) => { - return { - pricings: { - list: { - 'global': { - err: err, - data: data - } - } - } - } -}; - -describe('enableDefenderForSqlDatabases', function() { - describe('run', function() { - it('should give passing result if no pricings 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 Pricing information found'); - expect(results[0].region).to.equal('global'); - done() - }; - - const cache = createCache( - null, - [] - ); - - auth.run(cache, {}, callback); - }); - - it('should give failing result if Azure Defender for SQL Servers is not enabled', 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('Azure Defender is not enabled for SQL Servers'); - expect(results[0].region).to.equal('global'); - done() - }; - - const cache = createCache( - null, - [ - { - "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/providers/Microsoft.Security/pricings/default", - "name": "SqlServers", - "type": "Microsoft.Security/pricings", - "pricingTier": "free", - "location": "global" - } - ] - ); - - auth.run(cache, {}, callback); - }); - - it('should give passing result if Azure Defender for SQL Servers is enabled', 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('Azure Defender is enabled for SQL Servers'); - expect(results[0].region).to.equal('global'); - done() - }; - - const cache = createCache( - null, - [ - { - "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/providers/Microsoft.Security/pricings/default", - "name": "SqlServers", - "type": "Microsoft.Security/pricings", - "pricingTier": "Standard", - "location": "global" - } - ] - ); - - auth.run(cache, {}, callback); - }) - }) -}); \ No newline at end of file From 5688350ac20f71ae8bf47c4458476de9cdef7b5f Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 20:46:32 +0500 Subject: [PATCH 171/350] removed extra files --- plugins/azure/networksecuritygroups/openAllPorts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/networksecuritygroups/openAllPorts.js b/plugins/azure/networksecuritygroups/openAllPorts.js index a53556db8e..2f4e3c8c7e 100644 --- a/plugins/azure/networksecuritygroups/openAllPorts.js +++ b/plugins/azure/networksecuritygroups/openAllPorts.js @@ -45,7 +45,7 @@ module.exports = { let ports = { 'TCP': ['*'], - 'UDP': ['*'], + 'UCP': ['*'], '*' : ['*'] }; From f3be22613c6a4a9aef4ca526b234f46b16a84499 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Suleman Date: Fri, 20 May 2022 09:29:19 -0700 Subject: [PATCH 172/350] Update plugins/azure/defender/enableWDATPIntegration.js Co-authored-by: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> --- plugins/azure/defender/enableWDATPIntegration.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/defender/enableWDATPIntegration.js b/plugins/azure/defender/enableWDATPIntegration.js index e3ee14c3db..490d47529b 100644 --- a/plugins/azure/defender/enableWDATPIntegration.js +++ b/plugins/azure/defender/enableWDATPIntegration.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/azure'); module.exports = { title: 'Enable WDATP Integration', category: 'Defender', - domain: 'Security', + domain: 'Management and Governance', description: 'Ensures that Microsoft Defender for Endpoint integration is enabled for Microsoft Defender for Cloud.', more_info: 'WDATP integration brings comprehensive Endpoint Detection and Response (EDR) capabilities within Microsoft Defender for Cloud. This integration helps to spot abnormalities, detect and respond to advanced attacks on Windows server endpoints monitored by Microsoft Defender for Cloud. Windows Defender ATP in Microsoft Defender for Cloud supports detection on Windows Server 2016, 2012 R2, and 2008 R2 SP1 operating systems in a Standard service subscription.', recommended_action: 'Ensure that Microsoft Defender for Endpoint integration is selected with Microsoft Defender for Cloud.', From 648e19d164d59732fd7f8120df29941f4ad7f578 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Suleman Date: Fri, 20 May 2022 09:29:32 -0700 Subject: [PATCH 173/350] Update plugins/azure/defender/enableWDATPIntegration.js Co-authored-by: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> --- plugins/azure/defender/enableWDATPIntegration.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/defender/enableWDATPIntegration.js b/plugins/azure/defender/enableWDATPIntegration.js index 490d47529b..45c10afc69 100644 --- a/plugins/azure/defender/enableWDATPIntegration.js +++ b/plugins/azure/defender/enableWDATPIntegration.js @@ -33,7 +33,7 @@ module.exports = { return rcb(); } - const wdatpIntegration = defenderSettings.data.find((settings) => settings.name.toLowerCase() === 'wdatp'); + const wdatpIntegration = defenderSettings.data.find((settings) => settings.name && settings.name.toLowerCase() === 'wdatp'); if (wdatpIntegration && wdatpIntegration.enabled) { helpers.addResult(results, 0, 'WDATP integration is enabled for Microsoft Defender', location, wdatpIntegration.id); } else { From fc164d1e238f9cec35e095f1ffb8ae98a4658078 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 22:33:17 +0500 Subject: [PATCH 174/350] Added azure enableDefenderForStorage plugin --- exports.js | 2 + .../defender/enableDefenderForStorage.js | 52 +++++++++++ .../defender/enableDefenderForStorage.spec.js | 87 +++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 plugins/azure/defender/enableDefenderForStorage.js create mode 100644 plugins/azure/defender/enableDefenderForStorage.spec.js diff --git a/exports.js b/exports.js index 1c49f708a1..df80c41863 100644 --- a/exports.js +++ b/exports.js @@ -760,6 +760,8 @@ module.exports = { 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), 'automaticFailoverEnabled' : require(__dirname + '/plugins/azure/cosmosdb/automaticFailoverEnabled.js'), + + 'enableDefenderForStorage' : require(__dirname + '/plugins/azure/defender/enableDefenderForStorage.js'), }, github: { 'publicKeysRotated' : require(__dirname + '/plugins/github/users/publicKeysRotated.js'), diff --git a/plugins/azure/defender/enableDefenderForStorage.js b/plugins/azure/defender/enableDefenderForStorage.js new file mode 100644 index 0000000000..d8adbac8cb --- /dev/null +++ b/plugins/azure/defender/enableDefenderForStorage.js @@ -0,0 +1,52 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Enable Defender For Storage', + category: 'Defender', + domain: 'Management and Governance', + description: 'Ensures that Microsoft Defender is enabled for Storage.', + more_info: 'Turning on Microsoft Defender for Storage enables threat detection for Storage, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.', + recommended_action: 'Enable Microsoft Defender for Storage in Defender plans for the subscription.', + link: 'https://docs.microsoft.com/en-us/azure/defender-for-cloud/defender-for-storage-introduction', + apis: ['pricings:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.pricings, function(location, rcb) { + var pricings = helpers.addSource(cache, source, + ['pricings', 'list', location]); + + if (!pricings) return rcb(); + + if (pricings.err || !pricings.data) { + helpers.addResult(results, 3, + 'Unable to query for Pricing: ' + helpers.addError(pricings), location); + return rcb(); + } + + if (!pricings.data.length) { + helpers.addResult(results, 0, 'No Pricing information found', location); + return rcb(); + } + + let storagePricing = pricings.data.find((pricing) => pricing.name.toLowerCase() === 'storageaccounts'); + if (storagePricing) { + if (storagePricing.pricingTier.toLowerCase() === 'standard') { + helpers.addResult(results, 0, 'Azure Defender is enabled for Storage Accounts', location, storagePricing.id); + } else { + helpers.addResult(results, 2, 'Azure Defender is not enabled for Storage Accounts', location, storagePricing.id); + } + } else { + helpers.addResult(results, 2, 'Azure Defender is not enabled for Storage Accounts', location); + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/defender/enableDefenderForStorage.spec.js b/plugins/azure/defender/enableDefenderForStorage.spec.js new file mode 100644 index 0000000000..93869a310a --- /dev/null +++ b/plugins/azure/defender/enableDefenderForStorage.spec.js @@ -0,0 +1,87 @@ +var assert = require('assert'); +var expect = require('chai').expect; +var auth = require('./enableDefenderForStorage'); + +const createCache = (err, data) => { + return { + pricings: { + list: { + 'global': { + err: err, + data: data + } + } + } + } +}; + +describe('enableDefenderForStorage', function() { + describe('run', function() { + it('should give passing result if no pricings 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 Pricing information found'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [] + ); + + auth.run(cache, {}, callback); + }); + + it('should give failing result if Azure Defender for Storage Account is not enabled', 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('Azure Defender is not enabled for Storage Accounts'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [ + { + "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/providers/Microsoft.Security/pricings/default", + "name": "StorageAccounts", + "type": "Microsoft.Security/pricings", + "pricingTier": "free", + "location": "global" + } + ] + ); + + auth.run(cache, {}, callback); + }); + + it('should give passing result if Azure Defender for Storage Account is enabled', 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('Azure Defender is enabled for Storage Accounts'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [ + { + "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/providers/Microsoft.Security/pricings/default", + "name": "StorageAccounts", + "type": "Microsoft.Security/pricings", + "pricingTier": "Standard", + "location": "global" + } + ] + ); + + auth.run(cache, {}, callback); + }) + }) +}); \ No newline at end of file From 8dfa6bf28a25b9c1a8733b43ffcaa48382a6a9ab Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 20 May 2022 22:35:27 +0500 Subject: [PATCH 175/350] Update plugins/azure/networksecuritygroups/openAllPorts.js --- plugins/azure/networksecuritygroups/openAllPorts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/networksecuritygroups/openAllPorts.js b/plugins/azure/networksecuritygroups/openAllPorts.js index a53556db8e..2f4e3c8c7e 100644 --- a/plugins/azure/networksecuritygroups/openAllPorts.js +++ b/plugins/azure/networksecuritygroups/openAllPorts.js @@ -45,7 +45,7 @@ module.exports = { let ports = { 'TCP': ['*'], - 'UDP': ['*'], + 'UCP': ['*'], '*' : ['*'] }; From 54b0daa694440e2fde093477303018c2ba946ef9 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 23:00:59 +0500 Subject: [PATCH 176/350] Added Azure enableDefenderForContainer plugin --- exports.js | 2 + .../defender/enableDefenderForContainers.js | 52 +++++++++++ .../enableDefenderForContainers.spec.js | 87 +++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 plugins/azure/defender/enableDefenderForContainers.js create mode 100644 plugins/azure/defender/enableDefenderForContainers.spec.js diff --git a/exports.js b/exports.js index 1c49f708a1..ed3765ba88 100644 --- a/exports.js +++ b/exports.js @@ -760,6 +760,8 @@ module.exports = { 'advancedThreatProtection' : require(__dirname + '/plugins/azure/cosmosdb/advancedThreatProtection.js'), 'cosmosPublicAccessDisabled' : require(__dirname + '/plugins/azure/cosmosdb/cosmosPublicAccessDisabled.js'), 'automaticFailoverEnabled' : require(__dirname + '/plugins/azure/cosmosdb/automaticFailoverEnabled.js'), + + 'enableDefenderForContainers' : require(__dirname + '/plugins/azure/defender/enableDefenderForContainers.js'), }, github: { 'publicKeysRotated' : require(__dirname + '/plugins/github/users/publicKeysRotated.js'), diff --git a/plugins/azure/defender/enableDefenderForContainers.js b/plugins/azure/defender/enableDefenderForContainers.js new file mode 100644 index 0000000000..f14d797f23 --- /dev/null +++ b/plugins/azure/defender/enableDefenderForContainers.js @@ -0,0 +1,52 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Enable Defender For Containers', + category: 'Defender', + domain: 'Management and Governance', + description: 'Ensures that Microsoft Defender is enabled for all containers.', + more_info: 'Turning on Microsoft Defender for Containers enables threat detection, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.', + recommended_action: 'Enable Microsoft Defender for Containers in Defender plans for the subscription.', + link: 'https://docs.microsoft.com/en-us/azure/security-center/security-center-detection-capabilities', + apis: ['pricings:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.pricings, function(location, rcb) { + var pricings = helpers.addSource(cache, source, + ['pricings', 'list', location]); + + if (!pricings) return rcb(); + + if (pricings.err || !pricings.data) { + helpers.addResult(results, 3, + 'Unable to query for Pricing: ' + helpers.addError(pricings), location); + return rcb(); + } + + if (!pricings.data.length) { + helpers.addResult(results, 0, 'No Pricing information found', location); + return rcb(); + } + + let containersPricing = pricings.data.find((pricing) => pricing.name.toLowerCase() === 'containers'); + if (containersPricing) { + if (containersPricing.pricingTier.toLowerCase() === 'standard') { + helpers.addResult(results, 0, 'Azure Defender is enabled for Containers', location, containersPricing.id); + } else { + helpers.addResult(results, 2, 'Azure Defender is not enabled for Containers', location, containersPricing.id); + } + } else { + helpers.addResult(results, 2, 'Azure Defender is not enabled for Containers', location); + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/defender/enableDefenderForContainers.spec.js b/plugins/azure/defender/enableDefenderForContainers.spec.js new file mode 100644 index 0000000000..e90e3e672a --- /dev/null +++ b/plugins/azure/defender/enableDefenderForContainers.spec.js @@ -0,0 +1,87 @@ +var assert = require('assert'); +var expect = require('chai').expect; +var auth = require('./enableDefenderForContainers'); + +const createCache = (err, data) => { + return { + pricings: { + list: { + 'global': { + err: err, + data: data + } + } + } + } +}; + +describe('enableDefenderForKubernetes', function() { + describe('run', function() { + it('should give passing result if no pricings 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 Pricing information found'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [] + ); + + auth.run(cache, {}, callback); + }); + + it('should give failing result if Azure Defender for Containers is not enabled', 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('Azure Defender is not enabled for Containers'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [ + { + "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/providers/Microsoft.Security/pricings/default", + "name": "KubernetesService", + "type": "Microsoft.Security/pricings", + "pricingTier": "free", + "location": "global" + } + ] + ); + + auth.run(cache, {}, callback); + }); + + it('should give passing result if Azure Defender for Containers is enabled', 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('Azure Defender is enabled for Containers'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [ + { + "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/providers/Microsoft.Security/pricings/default", + "name": "Containers", + "type": "Microsoft.Security/pricings", + "pricingTier": "Standard", + "location": "global" + } + ] + ); + + auth.run(cache, {}, callback); + }) + }) +}); \ No newline at end of file From 39b9ed8e419b1b9be6baae9014175b38d62c8b4b Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 20 May 2022 23:09:23 +0500 Subject: [PATCH 177/350] Update plugins/azure/networksecuritygroups/openAllPorts.js --- plugins/azure/networksecuritygroups/openAllPorts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/networksecuritygroups/openAllPorts.js b/plugins/azure/networksecuritygroups/openAllPorts.js index a53556db8e..2f4e3c8c7e 100644 --- a/plugins/azure/networksecuritygroups/openAllPorts.js +++ b/plugins/azure/networksecuritygroups/openAllPorts.js @@ -45,7 +45,7 @@ module.exports = { let ports = { 'TCP': ['*'], - 'UDP': ['*'], + 'UCP': ['*'], '*' : ['*'] }; From 65c065c5cdd725ebe7154aa8708ee659c92b39a5 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 20 May 2022 23:15:51 +0500 Subject: [PATCH 178/350] Added Azure serverSendEmailToAdmins pluging --- collectors/azure/collector.js | 7 + exports.js | 1 + .../sqlserver/serverSendEmailToAdmins.js | 65 ++++++++ .../sqlserver/serverSendEmailToAdmins.spec.js | 157 ++++++++++++++++++ 4 files changed, 230 insertions(+) create mode 100644 plugins/azure/sqlserver/serverSendEmailToAdmins.js create mode 100644 plugins/azure/sqlserver/serverSendEmailToAdmins.spec.js diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index a559f259b1..61ce024602 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -261,6 +261,13 @@ var postcalls = { url: 'https://management.azure.com/{id}/securityAlertPolicies?api-version=2017-03-01-preview' } }, + vulnerabilityAssessments: { + listByServer: { + reliesOnPath: 'servers.listSql', + properties: ['id'], + url: 'https://management.azure.com/{id}/vulnerabilityAssessments?api-version=2021-02-01-preview' + } + }, failoverGroups: { listByServer: { reliesOnPath: 'servers.listSql', diff --git a/exports.js b/exports.js index 1c49f708a1..4002faecb5 100644 --- a/exports.js +++ b/exports.js @@ -710,6 +710,7 @@ module.exports = { 'sqlServerTlsVersion' : require(__dirname + '/plugins/azure/sqlserver/sqlServerTlsVersion.js'), 'autoFailoverGroupsEnabled' : require(__dirname + '/plugins/azure/sqlserver/autoFailoverGroupsEnabled.js'), 'automaticTuningEnabled' : require(__dirname + '/plugins/azure/sqlserver/automaticTuningEnabled.js'), + 'serverSendEmailToAdmins' : require(__dirname + '/plugins/azure/sqlserver/serverSendEmailToAdmins.js'), 'javaVersion' : require(__dirname + '/plugins/azure/appservice/javaVersion.js'), 'phpVersion' : require(__dirname + '/plugins/azure/appservice/phpVersion.js'), diff --git a/plugins/azure/sqlserver/serverSendEmailToAdmins.js b/plugins/azure/sqlserver/serverSendEmailToAdmins.js new file mode 100644 index 0000000000..700dfc192d --- /dev/null +++ b/plugins/azure/sqlserver/serverSendEmailToAdmins.js @@ -0,0 +1,65 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Server Send Email to Admin and Owners', + category: 'SQL Server', + domain: 'Databases', + description: 'Ensures that Send Emails to admins and owners is enabled for SQL Servers.', + more_info: 'Vulnerability Assessment (VA) scan reports and alerts will be sent to email addresses configured at "Send scan reports to". This may help in reducing time required for identifying risks and taking corrective measures.', + recommended_action: 'Configure Send scan reports to email addresses of concerned data owners/stakeholders for critical SQL servers.', + link: 'https://docs.microsoft.com/en-us/azure/sql-database/sql-vulnerability-assessment', + apis: ['servers:listSql', 'vulnerabilityAssessments:listByServer'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + + async.each(locations.servers, function(location, rcb) { + var servers = helpers.addSource(cache, source, + ['servers', 'listSql', location]); + + if (!servers) return rcb(); + + if (servers.err || !servers.data) { + helpers.addResult(results, 3, + 'Unable to query for SQL servers: ' + helpers.addError(servers), location); + return rcb(); + } + + if (!servers.data.length) { + helpers.addResult(results, 0, 'No SQL servers found', location); + return rcb(); + } + + servers.data.forEach(function(server) { + const vulnerabilityAssessments = helpers.addSource(cache, source, + ['vulnerabilityAssessments', 'listByServer', location, server.id]); + + if (!vulnerabilityAssessments || vulnerabilityAssessments.err || !vulnerabilityAssessments.data) { + helpers.addResult(results, 3, + 'Unable to query for Vulnerability Assessments setting: ' + helpers.addError(vulnerabilityAssessments), location, server.id); + } else { + if (!vulnerabilityAssessments.data.length) { + helpers.addResult(results, 2, 'No Vulnerability Assessments setting found', location, server.id); + } else { + vulnerabilityAssessments.data.forEach(vulnerabilityAssessment => { + if (vulnerabilityAssessment.recurringScans && vulnerabilityAssessment.recurringScans.emailSubscriptionAdmins) { + helpers.addResult(results, 0, + 'Send Email notifications to admins for the SQL server is enabled', location, server.id); + } else { + helpers.addResult(results, 2, + 'Send Email notifications to admins for the SQL server is disabled', location, server.id); + } + }); + } + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/sqlserver/serverSendEmailToAdmins.spec.js b/plugins/azure/sqlserver/serverSendEmailToAdmins.spec.js new file mode 100644 index 0000000000..fb1c8511f7 --- /dev/null +++ b/plugins/azure/sqlserver/serverSendEmailToAdmins.spec.js @@ -0,0 +1,157 @@ +var expect = require('chai').expect; +var serverSendEmailToAdmins = require('./serverSendEmailToAdmins'); + +const servers = [ + { + "id": "/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server", + } +]; + +const vulnerabilityAssessments = [ + { + id: '/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server/vulnerabilityAssessments/Default', + name: 'Default', + type: 'Microsoft.Sql/servers/vulnerabilityAssessments', + storageContainerPath: 'https://sqlvadfi44mwgvnjki.blob.core.windows.net/vulnerability-assessment/', + recurringScans: { isEnabled: true, emailSubscriptionAdmins: true, emails: [ 'test@gmail.com' ] } + }, + { + id: '/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server/vulnerabilityAssessments/Default', + name: 'Default', + type: 'Microsoft.Sql/servers/vulnerabilityAssessments', + storageContainerPath: 'https://sqlvadfi44mwgvnjki.blob.core.windows.net/vulnerability-assessment/', + recurringScans: { isEnabled: false, emailSubscriptionAdmins: false, emails: [] } + } +]; + +const createCache = (servers, policies, serversErr, policiesErr) => { + const serverId = (servers && servers.length) ? servers[0].id : null; + return { + servers: { + listSql: { + 'eastus': { + err: serversErr, + data: servers + } + } + }, + vulnerabilityAssessments: { + listByServer: { + 'eastus': { + [serverId]: { + err: policiesErr, + data: policies + } + } + } + } + } +}; + +describe('serverSendEmailToAdmins', function() { + describe('run', function() { + it('should give passing result if no SQL 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 SQL servers found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + [] + ); + + serverSendEmailToAdmins.run(cache, {}, callback); + }); + + it('should give failing result if No Vulnerability Assessments setting found', 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('No Vulnerability Assessments setting found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [] + ); + + serverSendEmailToAdmins.run(cache, {}, callback); + }); + + it('should give failing result if Send Email notifications to admins for the SQL server is disabled', 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('Send Email notifications to admins for the SQL server is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [vulnerabilityAssessments[1]] + ); + + serverSendEmailToAdmins.run(cache, {}, callback); + }); + + it('should give passing result if Send Email notifications to admins for the SQL server is enabled', 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('Send Email notifications to admins for the SQL server is enabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [vulnerabilityAssessments[0]] + ); + + serverSendEmailToAdmins.run(cache, {}, callback); + }); + + it('should give unknown result if unable to query for SQL servers', 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 SQL servers'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [], + { message: 'unable to query servers'} + ); + + serverSendEmailToAdmins.run(cache, {}, callback); + }); + + it('should give unknown result if Unable to query for Vulnerability Assessments setting', 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 Vulnerability Assessments setting'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [], + null, + { message: 'Unable to query for Vulnerability Assessments setting'} + ); + + serverSendEmailToAdmins.run(cache, {}, callback); + }); + }) +}); \ No newline at end of file From 1d66d41de370e57f29ea66f8648568126d3c0666 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 20 May 2022 23:17:21 +0500 Subject: [PATCH 179/350] Update plugins/azure/networksecuritygroups/openAllPorts.js --- plugins/azure/networksecuritygroups/openAllPorts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/networksecuritygroups/openAllPorts.js b/plugins/azure/networksecuritygroups/openAllPorts.js index a53556db8e..2f4e3c8c7e 100644 --- a/plugins/azure/networksecuritygroups/openAllPorts.js +++ b/plugins/azure/networksecuritygroups/openAllPorts.js @@ -45,7 +45,7 @@ module.exports = { let ports = { 'TCP': ['*'], - 'UDP': ['*'], + 'UCP': ['*'], '*' : ['*'] }; From 18747848bd76f2cbac29ef875e57278d1f2c333a Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Sat, 21 May 2022 01:04:49 +0500 Subject: [PATCH 180/350] Added azure sqlServerRecurringScans plugin --- collectors/azure/collector.js | 7 + exports.js | 1 + .../sqlserver/sqlServerRecurringScans.js | 66 ++++++++ .../sqlserver/sqlServerRecurringScans.spec.js | 157 ++++++++++++++++++ 4 files changed, 231 insertions(+) create mode 100644 plugins/azure/sqlserver/sqlServerRecurringScans.js create mode 100644 plugins/azure/sqlserver/sqlServerRecurringScans.spec.js diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index a559f259b1..61ce024602 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -261,6 +261,13 @@ var postcalls = { url: 'https://management.azure.com/{id}/securityAlertPolicies?api-version=2017-03-01-preview' } }, + vulnerabilityAssessments: { + listByServer: { + reliesOnPath: 'servers.listSql', + properties: ['id'], + url: 'https://management.azure.com/{id}/vulnerabilityAssessments?api-version=2021-02-01-preview' + } + }, failoverGroups: { listByServer: { reliesOnPath: 'servers.listSql', diff --git a/exports.js b/exports.js index 1c49f708a1..012fd757f9 100644 --- a/exports.js +++ b/exports.js @@ -710,6 +710,7 @@ module.exports = { 'sqlServerTlsVersion' : require(__dirname + '/plugins/azure/sqlserver/sqlServerTlsVersion.js'), 'autoFailoverGroupsEnabled' : require(__dirname + '/plugins/azure/sqlserver/autoFailoverGroupsEnabled.js'), 'automaticTuningEnabled' : require(__dirname + '/plugins/azure/sqlserver/automaticTuningEnabled.js'), + 'sqlServerRecurringScans' : require(__dirname + '/plugins/azure/sqlserver/sqlServerRecurringScans.js'), 'javaVersion' : require(__dirname + '/plugins/azure/appservice/javaVersion.js'), 'phpVersion' : require(__dirname + '/plugins/azure/appservice/phpVersion.js'), diff --git a/plugins/azure/sqlserver/sqlServerRecurringScans.js b/plugins/azure/sqlserver/sqlServerRecurringScans.js new file mode 100644 index 0000000000..2d612db9c3 --- /dev/null +++ b/plugins/azure/sqlserver/sqlServerRecurringScans.js @@ -0,0 +1,66 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'SQL Server Recurring Scans Enabled', + category: 'SQL Server', + domain: 'Databases', + description: 'Ensures that Period Recurring Scans feature is enabled for SQL Servers.', + more_info: 'Setting periodic recurring scans schedules periodic (weekly) vulnerability scanning for the SQL server and corresponding Databases. Periodic and regular vulnerability scanning provides risk visibility based on updated known vulnerability signatures and best practices.', + recommended_action: 'Ensure that recurring scans feature is set to Enabled.', + link: 'https://docs.microsoft.com/en-us/azure/sql-database/sql-vulnerability-assessment', + apis: ['servers:listSql', 'vulnerabilityAssessments:listByServer'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + + async.each(locations.servers, function(location, rcb) { + + var servers = helpers.addSource(cache, source, + ['servers', 'listSql', location]); + + if (!servers) return rcb(); + + if (servers.err || !servers.data) { + helpers.addResult(results, 3, + 'Unable to query for SQL servers: ' + helpers.addError(servers), location); + return rcb(); + } + + if (!servers.data.length) { + helpers.addResult(results, 0, 'No SQL servers found', location); + return rcb(); + } + + servers.data.forEach(function(server) { + const vulnerabilityAssessments = helpers.addSource(cache, source, + ['vulnerabilityAssessments', 'listByServer', location, server.id]); + + if (!vulnerabilityAssessments || vulnerabilityAssessments.err || !vulnerabilityAssessments.data) { + helpers.addResult(results, 3, + 'Unable to query for Vulnerability Assessments setting: ' + helpers.addError(vulnerabilityAssessments), location, server.id); + } else { + if (!vulnerabilityAssessments.data.length) { + helpers.addResult(results, 2, 'No Vulnerability Assessments setting found', location, server.id); + } else { + vulnerabilityAssessments.data.forEach(vulnerabilityAssessment => { + if (vulnerabilityAssessment.recurringScans && vulnerabilityAssessment.recurringScans.isEnabled) { + helpers.addResult(results, 0, + 'Recurring Scans for the SQL server is enabled', location, server.id); + } else { + helpers.addResult(results, 2, + 'Recurring Scans for the SQL server is disabled', location, server.id); + } + }); + } + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/sqlserver/sqlServerRecurringScans.spec.js b/plugins/azure/sqlserver/sqlServerRecurringScans.spec.js new file mode 100644 index 0000000000..35564ee9af --- /dev/null +++ b/plugins/azure/sqlserver/sqlServerRecurringScans.spec.js @@ -0,0 +1,157 @@ +var expect = require('chai').expect; +var sqlServerRecurringScans = require('./sqlServerRecurringScans'); + +const servers = [ + { + "id": "/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server", + } +]; + +const vulnerabilityAssessments = [ + { + id: '/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server/vulnerabilityAssessments/Default', + name: 'Default', + type: 'Microsoft.Sql/servers/vulnerabilityAssessments', + storageContainerPath: 'https://sqlvadfi44mwgvnjki.blob.core.windows.net/vulnerability-assessment/', + recurringScans: { isEnabled: true, emailSubscriptionAdmins: true, emails: [] } + }, + { + id: '/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server/vulnerabilityAssessments/Default', + name: 'Default', + type: 'Microsoft.Sql/servers/vulnerabilityAssessments', + storageContainerPath: 'https://sqlvadfi44mwgvnjki.blob.core.windows.net/vulnerability-assessment/', + recurringScans: { isEnabled: false, emailSubscriptionAdmins: true, emails: [] } + } +]; + +const createCache = (servers, policies, serversErr, policiesErr) => { + const serverId = (servers && servers.length) ? servers[0].id : null; + return { + servers: { + listSql: { + 'eastus': { + err: serversErr, + data: servers + } + } + }, + vulnerabilityAssessments: { + listByServer: { + 'eastus': { + [serverId]: { + err: policiesErr, + data: policies + } + } + } + } + } +}; + +describe('sqlServerRecurringScans', function() { + describe('run', function() { + it('should give passing result if no SQL 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 SQL servers found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + [] + ); + + sqlServerRecurringScans.run(cache, {}, callback); + }); + + it('should give failing result if No Vulnerability Assessments setting found', 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('No Vulnerability Assessments setting found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [] + ); + + sqlServerRecurringScans.run(cache, {}, callback); + }); + + it('should give failing result if Recurring Scans for Sql Server is disabled', 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('Recurring Scans for the SQL server is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [vulnerabilityAssessments[1]] + ); + + sqlServerRecurringScans.run(cache, {}, callback); + }); + + it('should give passing result if Recurring Scans for the SQL server is enabled', 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('Recurring Scans for the SQL server is enabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [vulnerabilityAssessments[0]] + ); + + sqlServerRecurringScans.run(cache, {}, callback); + }); + + it('should give unknown result if unable to query for SQL servers', 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 SQL servers'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [], + { message: 'unable to query servers'} + ); + + sqlServerRecurringScans.run(cache, {}, callback); + }); + + it('should give unknown result if Unable to query for Vulnerability Assessments setting', 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 Vulnerability Assessments setting'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [], + null, + { message: 'Unable to query for Vulnerability Assessments setting'} + ); + + sqlServerRecurringScans.run(cache, {}, callback); + }); + }) +}); \ No newline at end of file From 5e93b8313bf8ddf439dc2750b6cda7c60911a23f Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sat, 21 May 2022 08:00:13 +0500 Subject: [PATCH 181/350] Updated plugin --- plugins/aws/iam/checkAllUsedServices.js | 31 +++++++++++-------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/plugins/aws/iam/checkAllUsedServices.js b/plugins/aws/iam/checkAllUsedServices.js index ae51f9fd25..b89fd88c11 100644 --- a/plugins/aws/iam/checkAllUsedServices.js +++ b/plugins/aws/iam/checkAllUsedServices.js @@ -93,7 +93,7 @@ module.exports = { async.each(regions.configservice, function(region, rcb) { var configSRecorderStatus = helpers.addSource(cache, source, ['configservice', 'describeConfigurationRecorderStatus', region]); - + if (!configSRecorderStatus) { return rcb(); } @@ -103,7 +103,7 @@ module.exports = { 'Unable to query config service: ' + helpers.addError(configSRecorderStatus)); return rcb(null, results, source); } - + if (!configSRecorderStatus.data.length) { helpers.addResult(results, 0, 'Config service is not configured: ' + helpers.addError(configSRecorderStatus)); @@ -126,14 +126,14 @@ module.exports = { var discoveredResources = helpers.addSource(cache, source, ['configservice', 'getDiscoveredResourceCounts', region]); - + if (discoveredResources.err || !discoveredResources.data) { helpers.addResult(results, 3, 'Unable to query for Config Resources: ' + helpers.addError(discoveredResources)); return rcb(null, results, source); } - allResources.push(discoveredResources.data); + allResources.push(...discoveredResources.data); rcb(); }); @@ -236,16 +236,15 @@ module.exports = { getPolicyVersion.data.PolicyVersion.Document) { let statements = helpers.normalizePolicyDocument( getPolicyVersion.data.PolicyVersion.Document); - + if (!statements) break; - - let resource = statements.find((doc) => doc.Resource[0].includes('arn:')); + + let resource = statements.find((doc) => doc.Resource[0].includes('arn:')); if (resource) { let resourceName = resource && resource.Resource[0].split(':')[2]; let service = allResources.find((res) => res.resource.toLowerCase() === resourceName.toLowerCase()); if (!service || service.count < 1) { - let failMsg = `Role has policy with resource ${resourceName} which is not being used in this account`; - if (failMsg && roleFailures.indexOf(failMsg) === -1) policyFailures.push(failMsg); + if (policyFailures.indexOf(resourceName) === -1) policyFailures.push(resourceName); } } @@ -275,8 +274,7 @@ module.exports = { resources.forEach((resource) => { let service = allResources.find((res) => res.resource.toLowerCase() === resource.toLowerCase()); if (!service || service.count < 1) { - let failMsg = `Role has policy with resource ${resource} which is not being used in this account`; - if (failMsg && roleFailures.indexOf(failMsg) === -1) policyFailures.push(failMsg); + if (policyFailures.indexOf(resource) === -1) policyFailures.push(resource); } }); } @@ -286,11 +284,10 @@ module.exports = { } } - - if (policyFailures.length) { - helpers.addResult(results, 2, policyFailures.join(', '), 'global', role.Arn, custom); - } else if (roleFailures.length) { - helpers.addResult(results, 2, roleFailures.join(', '), 'global', role.Arn, custom); + if (policyFailures.length || roleFailures.length) { + let failureMsg = policyFailures.length ? 'Role has policy with following resources which are not being used in this account: ' + + '[ ' + policyFailures.join(', ') + ' ]' + '\r\n' + roleFailures.join(', ') : roleFailures.join(', '); + helpers.addResult(results, 2, failureMsg, 'global', role.Arn, custom); } else { helpers.addResult(results, 0, 'Role does not have overly-permissive policy', @@ -298,7 +295,7 @@ module.exports = { } cb(); - }, function(){ + }, function() { callback(null, results, source); }); } From b8c83a4a99a4d2e5abd03590573ea1a70ca4da99 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sat, 21 May 2022 08:57:25 +0500 Subject: [PATCH 182/350] Updated plugin --- plugins/aws/iam/checkAllUsedServices.js | 34 +++++++++++++++---------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/plugins/aws/iam/checkAllUsedServices.js b/plugins/aws/iam/checkAllUsedServices.js index b89fd88c11..3b109ae8cb 100644 --- a/plugins/aws/iam/checkAllUsedServices.js +++ b/plugins/aws/iam/checkAllUsedServices.js @@ -134,16 +134,22 @@ module.exports = { } allResources.push(...discoveredResources.data); - rcb(); }); - if (allResources.length === 0) { + if (!allResources.length) { helpers.addResult(results, 2, 'No Config Resources found.'); return callback(null, results, source); } - allResources = allResources.map((res) => { return { resource: res.resourceType.slice(res.resourceType.lastIndexOf(':') + 1, res.resourceType.length), count: res.count }; }); + allResources = allResources.map((resource) => { + let arr = resource.resourceType.split(':'); + return { + service: arr[2].toLowerCase(), + subService: arr[4].toLowerCase(), + count: resource.count + }; + }); var listRoles = helpers.addSource(cache, source, ['iam', 'listRoles', iamRegion]); @@ -239,12 +245,12 @@ module.exports = { if (!statements) break; - let resource = statements.find((doc) => doc.Resource[0].includes('arn:')); - if (resource) { - let resourceName = resource && resource.Resource[0].split(':')[2]; - let service = allResources.find((res) => res.resource.toLowerCase() === resourceName.toLowerCase()); - if (!service || service.count < 1) { - if (policyFailures.indexOf(resourceName) === -1) policyFailures.push(resourceName); + let service = statements.find((doc) => doc.Resource[0].includes('arn:')); + if (service) { + let serviceName = service.Resource[0].split(':')[2]; + let serviceFound = allResources.find((resource) => resource.service === serviceName && resource.count > 0); + if (!serviceFound) { + if (policyFailures.indexOf(serviceName) === -1) policyFailures.push(serviceName); } } @@ -270,11 +276,11 @@ module.exports = { if (!statements) break; for (let statement of statements) { - let resources = [... new Set(statement.Action.map((action) => action.split(':')[0].toLowerCase()))]; - resources.forEach((resource) => { - let service = allResources.find((res) => res.resource.toLowerCase() === resource.toLowerCase()); - if (!service || service.count < 1) { - if (policyFailures.indexOf(resource) === -1) policyFailures.push(resource); + let services = [... new Set(statement.Action.map((action) => action.split(':')[0].toLowerCase()))]; + services.forEach((service) => { + let serviceFound = allResources.find((resource) => resource.service === service && resource.count > 0); + if (!serviceFound) { + if (policyFailures.indexOf(service) === -1) policyFailures.push(service); } }); } From fd4dd370999ede1b7bfa198b230b401ffff79feb Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sat, 21 May 2022 08:59:04 +0500 Subject: [PATCH 183/350] Renamed the plugin --- exports.js | 2 +- .../{disableOpenUDPPorts.js => openUDP.js} | 0 .../{disableOpenUDPPorts.spec.js => openUDP.spec.js} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename plugins/azure/networksecuritygroups/{disableOpenUDPPorts.js => openUDP.js} (100%) rename plugins/azure/networksecuritygroups/{disableOpenUDPPorts.spec.js => openUDP.spec.js} (100%) diff --git a/exports.js b/exports.js index ee9a1b3289..11c4276efa 100644 --- a/exports.js +++ b/exports.js @@ -691,7 +691,7 @@ module.exports = { 'openSalt' : require(__dirname + '/plugins/azure/networksecuritygroups/openSalt.js'), 'openSMBoTCP' : require(__dirname + '/plugins/azure/networksecuritygroups/openSMBoTCP.js'), 'openSQLServer' : require(__dirname + '/plugins/azure/networksecuritygroups/openSQLServer.js'), - 'disableOpenUDPPorts' : require(__dirname + '/plugins/azure/networksecuritygroups/disableOpenUDPPorts.js'), + 'openUDP' : require(__dirname + '/plugins/azure/networksecuritygroups/openUDP.js'), 'nsgFlowLogsRetentionPeriod' : require(__dirname + '/plugins/azure/networkwatchers/nsgFlowLogsRetentionPeriod.js'), diff --git a/plugins/azure/networksecuritygroups/disableOpenUDPPorts.js b/plugins/azure/networksecuritygroups/openUDP.js similarity index 100% rename from plugins/azure/networksecuritygroups/disableOpenUDPPorts.js rename to plugins/azure/networksecuritygroups/openUDP.js diff --git a/plugins/azure/networksecuritygroups/disableOpenUDPPorts.spec.js b/plugins/azure/networksecuritygroups/openUDP.spec.js similarity index 100% rename from plugins/azure/networksecuritygroups/disableOpenUDPPorts.spec.js rename to plugins/azure/networksecuritygroups/openUDP.spec.js From 20a0243a05f0f2c9297aa5726447dc980bbcac47 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sat, 21 May 2022 10:10:08 +0500 Subject: [PATCH 184/350] Added spec --- .../azure/networksecuritygroups/openUDP.js | 4 +- .../networksecuritygroups/openUDP.spec.js | 143 ++++++++++++++++++ 2 files changed, 145 insertions(+), 2 deletions(-) diff --git a/plugins/azure/networksecuritygroups/openUDP.js b/plugins/azure/networksecuritygroups/openUDP.js index fe2ca61633..00ff708717 100644 --- a/plugins/azure/networksecuritygroups/openUDP.js +++ b/plugins/azure/networksecuritygroups/openUDP.js @@ -2,7 +2,7 @@ const async = require('async'); const helpers = require('../../../helpers/azure'); module.exports = { - title: 'Disable Open UDP Ports', + title: 'Open UDP Ports', category: 'Network Security Groups', domain: 'Network Access Control', description: 'Ensures that Internet exposed UDP ports on network security groups are disabled.', @@ -47,7 +47,7 @@ module.exports = { return (rule.properties && rule.properties.access && rule.properties.access.toLowerCase() == 'allow' && - rule.properties.direction.toLowerCase() === 'inboud' && + rule.properties.direction.toLowerCase() === 'inbound' && rule.properties.protocol.toLowerCase() === 'udp'); }); diff --git a/plugins/azure/networksecuritygroups/openUDP.spec.js b/plugins/azure/networksecuritygroups/openUDP.spec.js index e69de29bb2..5d9377feeb 100644 --- a/plugins/azure/networksecuritygroups/openUDP.spec.js +++ b/plugins/azure/networksecuritygroups/openUDP.spec.js @@ -0,0 +1,143 @@ +var expect = require('chai').expect; +var openUDP = require('./openUDP'); + +const networkSecurityGroups = [ + { + "name": "aadds-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "4a6b1ca1-a123-4829-a25d-1a6bcde3fg45", + "securityRules": [ + { + "name": "AllowPSRemoting", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowPSRemoting", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "UDP", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + } + } + ], + "defaultSecurityRules": [], + "subnets": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/aadds-subnet" + } + ] + }, + { + "name": "test-vm-1-nsg", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-vm-1-nsg", + "etag": "W/\"9479cb49-b812-4f0f-825b-2960bfcd14e3\"", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "eastus", + "provisioningState": "Succeeded", + "resourceGuid": "12a3456b-8cc0-4d9e-aa71-99cdc67b4506", + "securityRules": [ + { + "name": "AllowRD", + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/aadds-nsg/securityRules/AllowRD", + "etag": "W/\"a1bb27cd-711f-4ede-b673-2fe8e7e07eee\"", + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "properties": { + "provisioningState": "Succeeded", + "protocol": "UDP", + "sourcePortRange": "*", + "destinationPortRange": "5986", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 301, + "direction": "Inbound", + } + } + ], + "defaultSecurityRules": [], + "networkInterfaces": [ + { + "id": "/subscriptions/ab12c345-def7-890g-a1b2-28fc0d22117e/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-vm-1969" + } + ] + } +]; + +const createCache = (securityGroups) => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': { + data: securityGroups + } + } + } + }; +}; + +const createErrorCache = () => { + return { + networkSecurityGroups: { + listAll: { + 'eastus': {} + } + } + }; +}; + +describe('openUDP', function() { + describe('run', function() { + it('should give passing result if no Network Security Groups found', function(done) { + const cache = createCache([]); + openUDP.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('No security groups found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for Network Security Groups', function(done) { + const cache = createErrorCache(); + openUDP.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 Network Security Groups:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if the security group does not have open UDP ports for internet access', function(done) { + const cache = createCache([networkSecurityGroups[0]]); + openUDP.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('does not have open UDP ports for internet access'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if the security group has open UDP ports for internet access', function(done) { + const cache = createCache([networkSecurityGroups[1]]); + openUDP.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('has open UDP ports for internet access'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); From 0b7af0220574504e5ef5e962a819ecf9fd780f33 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sat, 21 May 2022 10:23:46 +0500 Subject: [PATCH 185/350] Incoporated feedback changes --- plugins/azure/sqlserver/enableATP.js | 6 +++--- plugins/azure/sqlserver/enableATP.spec.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/azure/sqlserver/enableATP.js b/plugins/azure/sqlserver/enableATP.js index 7d3cb176f5..d083259b6f 100644 --- a/plugins/azure/sqlserver/enableATP.js +++ b/plugins/azure/sqlserver/enableATP.js @@ -5,7 +5,7 @@ module.exports = { title: 'Advanced Threat Protection Enabled', category: 'SQL Server', domain: 'Databases', - description: 'Ensures that Advanced Threat Protection is enabled for SQL Servers', + description: 'Ensures that Advanced Threat Protection is enabled on SQL Servers.', more_info: 'Azure Defender for SQL is a unified package for advanced SQL security capabilities. Azure Defender is available for Azure SQL Database, Azure SQL Managed Instance, and Azure Synapse Analytics. It includes functionality for discovering and classifying sensitive data, surfacing and mitigating potential database vulnerabilities, and detecting anomalous activities that could indicate a threat to your database. It provides a single go-to location for enabling and managing these capabilities.', recommended_action: 'Ensure that ThreatDetectionState is set to Enabled', link: 'https://docs.microsoft.com/en-us/azure/azure-sql/database/azure-defender-for-sql', @@ -40,10 +40,10 @@ module.exports = { if (!advancedThreatProtectionSettings || advancedThreatProtectionSettings.err || !advancedThreatProtectionSettings.data) { helpers.addResult(results, 3, - 'Unable to query for Database Advanced Threat Protection settings: ' + helpers.addError(advancedThreatProtectionSettings), location, server.id); + 'Unable to query for Advanced Threat Protection settings: ' + helpers.addError(advancedThreatProtectionSettings), location, server.id); } else { if (!advancedThreatProtectionSettings.data.length) { - helpers.addResult(results, 2, 'No Database Advanced Threat Protection settings found', location, server.id); + helpers.addResult(results, 2, 'No Advanced Threat Protection setting found', location, server.id); } else { advancedThreatProtectionSettings.data.forEach(threadProtectionSetting => { if (threadProtectionSetting.state && diff --git a/plugins/azure/sqlserver/enableATP.spec.js b/plugins/azure/sqlserver/enableATP.spec.js index 5e2450227a..ba55cefdd2 100644 --- a/plugins/azure/sqlserver/enableATP.spec.js +++ b/plugins/azure/sqlserver/enableATP.spec.js @@ -70,7 +70,7 @@ describe('enableATP', function() { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('No Database Advanced Threat Protection settings found'); + expect(results[0].message).to.include('No Advanced Threat Protection setting found'); expect(results[0].region).to.equal('eastus'); done() }; From 85214731babc3f30422d3828d30ab4284b2de9d0 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Suleman Date: Fri, 20 May 2022 22:27:33 -0700 Subject: [PATCH 186/350] Update plugins/azure/defender/enableWDATPIntegration.js --- plugins/azure/defender/enableWDATPIntegration.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/defender/enableWDATPIntegration.js b/plugins/azure/defender/enableWDATPIntegration.js index 45c10afc69..c732120f23 100644 --- a/plugins/azure/defender/enableWDATPIntegration.js +++ b/plugins/azure/defender/enableWDATPIntegration.js @@ -5,7 +5,7 @@ module.exports = { title: 'Enable WDATP Integration', category: 'Defender', domain: 'Management and Governance', - description: 'Ensures that Microsoft Defender for Endpoint integration is enabled for Microsoft Defender for Cloud.', + description: 'Ensures that WDATP integration is enabled for Microsoft Defender for Cloud.', more_info: 'WDATP integration brings comprehensive Endpoint Detection and Response (EDR) capabilities within Microsoft Defender for Cloud. This integration helps to spot abnormalities, detect and respond to advanced attacks on Windows server endpoints monitored by Microsoft Defender for Cloud. Windows Defender ATP in Microsoft Defender for Cloud supports detection on Windows Server 2016, 2012 R2, and 2008 R2 SP1 operating systems in a Standard service subscription.', recommended_action: 'Ensure that Microsoft Defender for Endpoint integration is selected with Microsoft Defender for Cloud.', link: 'https://docs.microsoft.com/en-in/azure/defender-for-cloud/integration-defender-for-endpoint?tabs=windows', From fba16996db75c07642353045a96f6a7f21fabdfe Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sun, 22 May 2022 18:38:48 +0500 Subject: [PATCH 187/350] remove warn results --- .../oracle/identity/usersPasswordLastUsed.js | 9 --- .../identity/usersPasswordLastUsed.spec.js | 65 ++----------------- 2 files changed, 6 insertions(+), 68 deletions(-) diff --git a/plugins/oracle/identity/usersPasswordLastUsed.js b/plugins/oracle/identity/usersPasswordLastUsed.js index 7b3de65f03..3289479d51 100644 --- a/plugins/oracle/identity/usersPasswordLastUsed.js +++ b/plugins/oracle/identity/usersPasswordLastUsed.js @@ -19,12 +19,6 @@ module.exports = { description: 'Return a failing result when users with password logins exceed this number of days without being used', regex: '^[1-9]{1}[0-9]{0,3}$', default: 180 - }, - identity_users_password_last_used_warn: { - name: 'Users Password Last Used Warn', - description: 'Return a warning result when users with password logins exceed this number of days without being used', - regex: '^[1-9]{1}[0-9]{0,3}$', - default: 90 } }, @@ -34,7 +28,6 @@ module.exports = { var source = {}; var config = { identity_users_password_last_used_fail: settings.identity_users_password_last_used_fail || this.settings.identity_users_password_last_used_fail.default, - identity_users_password_last_used_warn: settings.identity_users_password_last_used_warn || this.settings.identity_users_password_last_used_warn.default }; var region = helpers.objectFirstKey(cache['regionSubscription']['list']); @@ -73,8 +66,6 @@ module.exports = { if (daysAgo > config.identity_users_password_last_used_fail) { returnCode = 2; - } else if (daysAgo > config.identity_users_password_last_used_warn) { - returnCode = 1; } else { returnCode = 0; } diff --git a/plugins/oracle/identity/usersPasswordLastUsed.spec.js b/plugins/oracle/identity/usersPasswordLastUsed.spec.js index 2915743445..102bca5bf0 100644 --- a/plugins/oracle/identity/usersPasswordLastUsed.spec.js +++ b/plugins/oracle/identity/usersPasswordLastUsed.spec.js @@ -1,8 +1,6 @@ var expect = require('chai').expect; var plugin = require('./usersPasswordLastUsed'); -var warnDate = new Date(); -warnDate.setMonth(warnDate.getMonth() - 4); var passDate = new Date(); passDate.setMonth(passDate.getMonth() - 2); var failDate = new Date(); @@ -26,25 +24,6 @@ const user = [ "id": "111", "timeCreated": failDate, }, - { - "defined-tags": {}, - "description": "login user", - "email": "user1@gmail.com", - "isMfaActivated": false, - "id": "111", - "timeCreated": warnDate, - "lastSuccessfulLoginTime": warnDate, - - }, - { - "defined-tags": {}, - "description": "login user", - "email": "user1@gmail.com", - "isMfaActivated": false, - "id": "111", - "timeCreated": warnDate, - - }, { "email": "user2@gmail.com", "emailVerified": true, @@ -155,7 +134,7 @@ describe('usersPasswordLastUsed', function () { const cache = createCache( null, - [user[6], user[6]] + [user[4], user[4]] ); plugin.run(cache, {}, callback); @@ -171,10 +150,10 @@ describe('usersPasswordLastUsed', function () { const cache = createCache( null, - [user[4], user[5]] + [user[2], user[3]] ); - plugin.run(cache, { identity_users_password_last_used_fail: 180, identity_users_password_last_used_warn: 90 }, callback); + plugin.run(cache, { identity_users_password_last_used_fail: 180 }, callback); }) it('should PASS if the user was created within the pass limit but never used', function (done) { @@ -185,44 +164,12 @@ describe('usersPasswordLastUsed', function () { done() }; - const cache = createCache( - null, - [user[5], user[4]] - ); - - plugin.run(cache, { identity_users_password_last_used_fail: 180, identity_users_password_last_used_warn: 90 }, callback); - }) - - it('should WARN if the user password was last used within the warn limit', function (done) { - const callback = (err, results) => { - expect(results.length).to.be.above(0) - expect(results[0].status).to.equal(1) - expect(results[0].region).to.equal('global') - done() - }; - - const cache = createCache( - null, - [user[2], user[3]] - ); - - plugin.run(cache, { identity_users_password_last_used_fail: 180, identity_users_password_last_used_warn: 90 }, callback); - }) - - it('should WARN if the user was created within the warn limit but never used', function (done) { - const callback = (err, results) => { - expect(results.length).to.be.above(0) - expect(results[0].status).to.equal(1) - expect(results[0].region).to.equal('global') - done() - }; - const cache = createCache( null, [user[3], user[2]] ); - plugin.run(cache, { identity_users_password_last_used_fail: 180, identity_users_password_last_used_warn: 90 }, callback); + plugin.run(cache, { identity_users_password_last_used_fail: 180 }, callback); }) it('should FAIL if the user password was last used within the fail limit', function (done) { @@ -238,7 +185,7 @@ describe('usersPasswordLastUsed', function () { [user[0], user[1]] ); - plugin.run(cache, { identity_users_password_last_used_fail: 180, identity_users_password_last_used_warn: 90 }, callback); + plugin.run(cache, { identity_users_password_last_used_fail: 180 }, callback); }) it('should FAIL if the user was created within the fail limit but never used', function (done) { @@ -254,7 +201,7 @@ describe('usersPasswordLastUsed', function () { [user[1], user[0]] ); - plugin.run(cache, { identity_users_password_last_used_fail: 180, identity_users_password_last_used_warn: 90 }, callback); + plugin.run(cache, { identity_users_password_last_used_fail: 180 }, callback); }) }); From 8f1de36213fdb0b267fea93d09aa18f141d52ef5 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 23 May 2022 00:44:49 +0500 Subject: [PATCH 188/350] Syncing open source with saas --- collectors/google/collector.js | 1 - helpers/aws/api.js | 10 ++++-- helpers/aws/api_multipart.js | 8 +++-- helpers/google/index.js | 12 +++---- plugins/aws/autoscaling/asgMultiAz.js | 5 ++- .../cloudtrailNotificationsEnabled.js | 15 ++++++--- .../cloudtrailNotificationsEnabled.spec.js | 33 ++----------------- .../configServiceMissingBucket.js | 2 +- plugins/aws/ec2/flowLogsEnabled.js | 15 +++------ plugins/aws/ec2/multipleSubnets.js | 14 +++----- plugins/aws/elb/insecureCiphers.js | 13 +++----- .../aws/redshift/redshiftEncryptionEnabled.js | 14 +++----- .../redshift/redshiftPubliclyAccessible.js | 14 +++----- .../redshift/redshiftUnusedReservedNodes.js | 12 ++----- plugins/aws/s3/bucketPolicyCloudFrontOai.js | 7 ++-- plugins/aws/s3/versionedBucketsLC.js | 8 +++-- plugins/aws/ses/dkimEnabled.js | 14 +++----- plugins/aws/sns/snsCrossAccount.js | 2 +- plugins/aws/sns/topicPolicies.js | 2 +- .../networksecuritygroups/openAllPorts.js | 2 +- 20 files changed, 76 insertions(+), 127 deletions(-) diff --git a/collectors/google/collector.js b/collectors/google/collector.js index 9dcc89cf77..29d9419e2c 100644 --- a/collectors/google/collector.js +++ b/collectors/google/collector.js @@ -426,7 +426,6 @@ var collect = function(GoogleConfig, settings, callback) { postcallCb(); }); }, function() { - JSON.stringify(collection, null, 2); callback(null, collection); }); }); diff --git a/helpers/aws/api.js b/helpers/aws/api.js index 39f955f078..7f49e7cc60 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -544,6 +544,8 @@ var calls = { describeLoadBalancers: { property: 'LoadBalancers', paginate: 'NextMarker', + reliesOnService: 'ec2', + reliesOnCall: 'describeVpcs', paginateReqProp: 'Marker' }, describeTargetGroups: { @@ -558,8 +560,12 @@ var calls = { }, sendIntegration: { enabled: true, - reliesOnCalls: ['ELBv2:describeTargetGroups', 'ELBv2:describeTargetHealth'] - } + reliesOnCalls: ['ELBv2:describeTargetGroups', 'ELBv2:describeTargetHealth'], + integrationReliesOn: { + serviceName: 'EC2', + calls: ['ELBv2:describeLoadBalancers'] + } + }, }, EMR: { listClusters: { diff --git a/helpers/aws/api_multipart.js b/helpers/aws/api_multipart.js index 92bccbdad5..11893fd648 100644 --- a/helpers/aws/api_multipart.js +++ b/helpers/aws/api_multipart.js @@ -1038,8 +1038,12 @@ var calls = [ }, sendIntegration: { enabled: true, - reliesOnCalls: ['ELBv2:describeTargetGroups', 'ELBv2:describeTargetHealth'] - } + reliesOnCalls: ['ELBv2:describeTargetGroups', 'ELBv2:describeTargetHealth'], + integrationReliesOn: { + serviceName: 'EC2', + calls: ['ELBv2:describeLoadBalancers'] + } + }, } } ]; diff --git a/helpers/google/index.js b/helpers/google/index.js index 5716594b3d..25be31216c 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -4,7 +4,6 @@ var regRegions = require('./regions.js'); const {JWT} = require('google-auth-library'); - var async = require('async'); var regions = function() { @@ -268,11 +267,11 @@ var execute = async function(LocalGoogleConfig, collection, service, callObj, ca collectionItems = myEngine ? collection[service][myEngine][callKey][region] : collection[service][callKey][region]; let set = true; if (data.data.items) { - resultItems = setData(collectionItems, data.data.items, postCall, parent); + resultItems = setData(collectionItems, data.data.items, postCall, parent, {'service': service, 'callKey': callKey}); } else if (data.data[service]) { - resultItems = setData(collectionItems, data.data[service], postCall, parent); + resultItems = setData(collectionItems, data.data[service], postCall, parent, {'service': service, 'callKey': callKey}); } else if (!myEngine && data.data.accounts) { - resultItems = setData(collectionItems, data.data.accounts, postCall, parent); + resultItems = setData(collectionItems, data.data.accounts, postCall, parent, {'service': service, 'callKey': callKey}); } else if (!myEngine && data.data) { set = false; if (data.data.constructor.name === 'Array') { @@ -282,7 +281,7 @@ var execute = async function(LocalGoogleConfig, collection, service, callObj, ca } else if (!myEngine && !(collection[service][callKey][region].data.length)) { collection[service][callKey][region].data = []; } - resultItems = setData(collection[service][callKey][region], data.data, postCall, parent); + resultItems = setData(collection[service][callKey][region], data.data, postCall, parent, {'service': service, 'callKey': callKey}); } else { set = false; myEngine ? collection[service][myEngine][callKey][region].data = [] : collection[service][callKey][region].data = []; @@ -374,7 +373,8 @@ function makeApiCall(client, originalUrl, callCb, nextToken, config) { }); } -function setData(collection, dataToAdd, postCall, parent) { +function setData(collection, dataToAdd, postCall, parent, serviceInfo) { + console.log(`[PLUGINCHECK] ${JSON.stringify(serviceInfo, null, 2)}`); if (postCall && !!parent) { if (dataToAdd && dataToAdd.length) { dataToAdd.map(item => { diff --git a/plugins/aws/autoscaling/asgMultiAz.js b/plugins/aws/autoscaling/asgMultiAz.js index 9d775d6247..04250446b2 100644 --- a/plugins/aws/autoscaling/asgMultiAz.js +++ b/plugins/aws/autoscaling/asgMultiAz.js @@ -36,17 +36,16 @@ module.exports = { // loop through autoscaling Instances describeAutoScalingGroups.data.forEach(function(Asg){ - var resource = Asg.AutoScalingGroupARN; if (Asg.AvailabilityZones.length <=1) { helpers.addResult(results, 2, 'Auto scaling group is only using ' + Asg.AvailabilityZones.length + ' availability zones', - region, resource); + region, Asg.AutoScalingGroupName); } else { helpers.addResult(results, 0, 'Auto scaling group using ' + Asg.AvailabilityZones.length + ' availability zones', - region, resource); + region, Asg.AutoScalingGroupName); } }); rcb(); diff --git a/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js b/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js index 18fadb4a1f..1fd47a8f6f 100644 --- a/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js +++ b/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js @@ -41,7 +41,7 @@ module.exports = { if (listTopics.err || !listTopics.data) { helpers.addResult(results, 3, - `Unable to list SNS topics: ${helpers.addError(listTopics)}`, region); + `Unable to query for SNS topics: ${helpers.addError(listTopics)}`, region); return rcb(); } @@ -53,14 +53,19 @@ module.exports = { var getTopicAttributes = helpers.addSource(cache, source, ['sns', 'getTopicAttributes', region, trail.SnsTopicARN]); - if (!getTopicAttributes) { + if (getTopicAttributes && getTopicAttributes.err && getTopicAttributes.err.code && + getTopicAttributes.err.code == 'NotFound') { helpers.addResult(results, 2, 'CloudTrail trail SNS topic not found', region, resource); - } else if (getTopicAttributes.err || !getTopicAttributes.data) { + continue; + } + + if (!getTopicAttributes || getTopicAttributes.err || + !getTopicAttributes.data) { helpers.addResult(results, 3, - `Unable to query for SNS topic: ${helpers.addError(getTopicAttributes)}`, + `Unable to query for SNS topic: ${helpers.addError(describeTrails)}`, region, resource); - } else { + } else { helpers.addResult(results, 0, 'CloudTrail trail is using active SNS topic', region, resource); diff --git a/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.spec.js b/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.spec.js index 1009df1875..844d49d8a4 100644 --- a/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.spec.js +++ b/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.spec.js @@ -89,33 +89,6 @@ const createCache = (describeTrails, listTopics, getTopicAttributes, describeTra } } }; -const createNullCache = (describeTrails, listTopics, describeTrailsErr, listTopicsErr) => { - let Arn = (describeTrails && describeTrails.length) ? describeTrails[0].SnsTopicARN : null; - return { - cloudtrail: { - describeTrails: { - 'us-east-1': { - data: describeTrails, - err: describeTrailsErr - } - }, - }, - sns: { - listTopics: { - 'us-east-1': { - data: listTopics, - err: listTopicsErr - } - }, - getTopicAttributes: { - 'us-east-1': { - [Arn]: null - } - } - - } - } -}; describe('cloudtrailNotificationsEnabled', function () { describe('run', function () { @@ -131,7 +104,7 @@ describe('cloudtrailNotificationsEnabled', function () { }); it('should FAIL if CloudTrail trail SNS topic not found', function (done) { - const cache = createNullCache([describeTrails[1]], listTopics[2]); + const cache = createCache([describeTrails[1]], listTopics[2], null, null, null, { message: 'An error occurred (NotFound) when calling the GetTopicAttributes operation: Topic does not exist', code : 'NotFound' } ); cloudtrailNotificationsEnabled.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); @@ -162,12 +135,12 @@ describe('cloudtrailNotificationsEnabled', function () { }); }); - it('should UNKNOWN if unable to list SNS topics', function (done) { + it('should UNKNOWN if unable to query for SNS topics', function (done) { const cache = createCache([describeTrails[1]], [], null, null, { message: 'Unable to query for SNS topics' }); cloudtrailNotificationsEnabled.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 list SNS topics') + expect(results[0].message).to.include('Unable to query for SNS topics') done(); }); }); diff --git a/plugins/aws/configservice/configServiceMissingBucket.js b/plugins/aws/configservice/configServiceMissingBucket.js index f0279cc2c6..c2877c0f7f 100644 --- a/plugins/aws/configservice/configServiceMissingBucket.js +++ b/plugins/aws/configservice/configServiceMissingBucket.js @@ -46,7 +46,7 @@ module.exports = { deletedBuckets.push(record); } else if (!headBucket || headBucket.err) { helpers.addResult(results, 3, - 'Unable to query S3 bucket: ' + helpers.addError(headBucket), region, 'arn:aws:s3:::' + record.s3BucketName); + 'Unable to query S3 bucket: ' + helpers.addError(headBucket), region); continue; } } diff --git a/plugins/aws/ec2/flowLogsEnabled.js b/plugins/aws/ec2/flowLogsEnabled.js index c4827e15e0..0e5aaaa13f 100644 --- a/plugins/aws/ec2/flowLogsEnabled.js +++ b/plugins/aws/ec2/flowLogsEnabled.js @@ -10,7 +10,7 @@ module.exports = { more_info: 'VPC flow logs record all traffic flowing in to and out of a VPC. These logs are critical for auditing and review after security incidents.', link: 'http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/flow-logs.html', recommended_action: 'Enable VPC flow logs for each VPC', - apis: ['EC2:describeVpcs', 'EC2:describeFlowLogs', 'STS:getCallerIdentity'], + apis: ['EC2:describeVpcs', 'EC2:describeFlowLogs'], compliance: { hipaa: 'VPC Flow Logs provide a detailed traffic log of a VPC network ' + 'containing HIPAA data. Flow Logs should be enabled to satisfy ' + @@ -25,10 +25,6 @@ module.exports = { var source = {}; var regions = helpers.regions(settings); - var acctRegion = helpers.defaultRegion(settings); - var awsOrGov = helpers.defaultPartition(settings); - var accountId = helpers.addSource(cache, source, ['sts', 'getCallerIdentity', acctRegion, 'data']); - async.each(regions.flowlogs, function(region, rcb){ var describeVpcs = helpers.addSource(cache, source, ['ec2', 'describeVpcs', region]); @@ -71,10 +67,9 @@ module.exports = { } // Loop through VPCs and add results - for (var v in vpcMap) { - var resource = 'arn:' + awsOrGov + ':ec2:' + region + ':' + accountId + ':vpc/' + v; + for (var v in vpcMap) { if (!vpcMap[v].length) { - helpers.addResult(results, 2, 'VPC flow logs are not enabled', region, resource); + helpers.addResult(results, 2, 'VPC flow logs are not enabled', region, v); } else { var activeLogs = false; @@ -86,9 +81,9 @@ module.exports = { } if (activeLogs) { - helpers.addResult(results, 0, 'VPC flow logs are enabled', region, resource); + helpers.addResult(results, 0, 'VPC flow logs are enabled', region, v); } else { - helpers.addResult(results, 2, 'VPC flow logs are enabled, but not active', region, resource); + helpers.addResult(results, 2, 'VPC flow logs are enabled, but not active', region, v); } } } diff --git a/plugins/aws/ec2/multipleSubnets.js b/plugins/aws/ec2/multipleSubnets.js index d3f07c4ef2..2fbaf7eb30 100644 --- a/plugins/aws/ec2/multipleSubnets.js +++ b/plugins/aws/ec2/multipleSubnets.js @@ -9,17 +9,13 @@ module.exports = { more_info: 'VPCs should be designed to have separate public and private subnets, ideally across availability zones, enabling a DMZ-style architecture.', link: 'https://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Subnets.html#SubnetSecurity', recommended_action: 'Create at least two subnets in each VPC, utilizing one for public traffic and the other for private traffic.', - apis: ['EC2:describeVpcs', 'EC2:describeSubnets', 'STS:getCallerIdentity'], + apis: ['EC2:describeVpcs', 'EC2:describeSubnets'], run: function(cache, settings, callback) { var results = []; var source = {}; var regions = helpers.regions(settings); - var acctRegion = helpers.defaultRegion(settings); - var awsOrGov = helpers.defaultPartition(settings); - var accountId = helpers.addSource(cache, source, ['sts', 'getCallerIdentity', acctRegion, 'data']); - async.each(regions.ec2, function(region, rcb){ var describeVpcs = helpers.addSource(cache, source, ['ec2', 'describeVpcs', region]); @@ -59,20 +55,18 @@ module.exports = { return rcb(); } - var resource = 'arn:' + awsOrGov + ':ec2:' + region + ':' + accountId + ':vpc/' + vpcId; - if (describeSubnets.data.Subnets.length > 1) { helpers.addResult(results, 0, 'There are ' + describeSubnets.data.Subnets.length + ' subnets used in one VPC.', - region, resource); + region, vpcId); } else if (describeSubnets.data.Subnets.length === 1) { helpers.addResult(results, 2, 'Only one subnet (' + describeSubnets.data.Subnets[0].SubnetId + ') in one VPC is used.', - region, resource); + region, vpcId); } else { helpers.addResult(results, 0, 'The VPC does not contain any subnets', - region, resource); + region, vpcId); } rcb(); diff --git a/plugins/aws/elb/insecureCiphers.js b/plugins/aws/elb/insecureCiphers.js index efeb7bf2fe..c8e8791712 100644 --- a/plugins/aws/elb/insecureCiphers.js +++ b/plugins/aws/elb/insecureCiphers.js @@ -83,7 +83,7 @@ module.exports = { more_info: 'Various security vulnerabilities have rendered several ciphers insecure. Only the recommended ciphers should be used.', link: 'http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-security-policy-options.html', recommended_action: 'Update your ELBs to use the recommended cipher suites', - apis: ['ELB:describeLoadBalancers', 'ELB:describeLoadBalancerPolicies', 'STS:getCallerIdentity'], + apis: ['ELB:describeLoadBalancers', 'ELB:describeLoadBalancerPolicies'], compliance: { hipaa: 'All HIPAA data should be encrypted in transit. Using secure ciphers ' + 'is a critical aspect of this requirement. Using outdated ciphers with ' + @@ -98,10 +98,6 @@ module.exports = { var source = {}; var regions = helpers.regions(settings); - var acctRegion = helpers.defaultRegion(settings); - var accountId = helpers.addSource(cache, source, ['sts', 'getCallerIdentity', acctRegion, 'data']); - var awsOrGov = helpers.defaultPartition(settings); - async.each(regions.elb, function(region, rcb){ var describeLoadBalancers = helpers.addSource(cache, source, ['elb', 'describeLoadBalancers', region]); @@ -121,7 +117,6 @@ module.exports = { async.each(describeLoadBalancers.data, function(lb, cb){ if (!lb.DNSName) return cb(); - var resource = `arn:${awsOrGov}:elasticloadbalancing:${region}:${accountId}:loadbalancer/${lb.LoadBalancerName}`; var describeLoadBalancerPolicies = helpers.addSource(cache, source, ['elb', 'describeLoadBalancerPolicies', region, lb.DNSName]); @@ -134,7 +129,7 @@ module.exports = { helpers.addResult(results, 3, 'Unable to query load balancer policies for ELB: ' + lb.LoadBalancerName + ': ' + helpers.addError(describeLoadBalancerPolicies), - region, resource); + region, lb.DNSName); return cb(); } @@ -156,11 +151,11 @@ module.exports = { if (elbBad.length) { helpers.addResult(results, 1, 'ELB: ' + lb.LoadBalancerName + ' uses insecure protocols or ciphers: ' + elbBad.join(', '), - region, resource); + region, lb.DNSName); } else { helpers.addResult(results, 0, 'ELB: ' + lb.LoadBalancerName + ' uses secure protocols and ciphers', - region, resource); + region, lb.DNSName); } } diff --git a/plugins/aws/redshift/redshiftEncryptionEnabled.js b/plugins/aws/redshift/redshiftEncryptionEnabled.js index 744f8b33e5..19b6d6ac6c 100644 --- a/plugins/aws/redshift/redshiftEncryptionEnabled.js +++ b/plugins/aws/redshift/redshiftEncryptionEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'AWS provides at-read encryption for Redshift clusters which should be enabled to ensure the integrity of data stored within the cluster.', link: 'http://docs.aws.amazon.com/redshift/latest/mgmt/working-with-db-encryption.html', recommended_action: 'Redshift does not currently allow modifications to encryption after the cluster has been launched, so a new cluster will need to be created with encryption enabled.', - apis: ['Redshift:describeClusters', 'STS:getCallerIdentity'], + apis: ['Redshift:describeClusters'], compliance: { hipaa: 'All data in HIPAA environments must be encrypted, including ' + 'data at rest. Redshift encryption ensures that this HIPAA control ' + @@ -22,11 +22,6 @@ module.exports = { var source = {}; var regions = helpers.regions(settings); - var acctRegion = helpers.defaultRegion(settings); - var accountId = helpers.addSource(cache, source, - ['sts', 'getCallerIdentity', acctRegion, 'data']); - var awsOrGov = helpers.defaultPartition(settings); - async.each(regions.redshift, function(region, rcb){ var describeClusters = helpers.addSource(cache, source, ['redshift', 'describeClusters', region]); @@ -47,13 +42,12 @@ module.exports = { for (var i in describeClusters.data) { // For resource, attempt to use the endpoint address (more specific) but fallback to the instance identifier var cluster = describeClusters.data[i]; - var clusterIdentifier = cluster.ClusterIdentifier; - var resource = `arn:${awsOrGov}:redshift:${region}:${accountId}:cluster:${clusterIdentifier}`; + var clusterResource = (cluster.Endpoint && cluster.Endpoint.Address) ? cluster.Endpoint.Address : cluster.ClusterIdentifier; if (cluster.Encrypted) { - helpers.addResult(results, 0, 'Redshift cluster is encrypted', region, resource); + helpers.addResult(results, 0, 'Redshift cluster is encrypted', region, clusterResource); } else { - helpers.addResult(results, 1, 'Redshift cluster is not encrypted', region, resource); + helpers.addResult(results, 1, 'Redshift cluster is not encrypted', region, clusterResource); } } diff --git a/plugins/aws/redshift/redshiftPubliclyAccessible.js b/plugins/aws/redshift/redshiftPubliclyAccessible.js index 1379cf26de..42b0888f86 100644 --- a/plugins/aws/redshift/redshiftPubliclyAccessible.js +++ b/plugins/aws/redshift/redshiftPubliclyAccessible.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Unless there is a specific business requirement, Redshift clusters should not have a public endpoint and should be accessed from within a VPC only.', link: 'http://docs.aws.amazon.com/redshift/latest/mgmt/getting-started-cluster-in-vpc.html', recommended_action: 'Remove the public endpoint from the Redshift cluster', - apis: ['Redshift:describeClusters', 'STS:getCallerIdentity'], + apis: ['Redshift:describeClusters'], compliance: { hipaa: 'Redshift instances should only be launched in VPC environments and ' + 'accessed through private endpoints. Exposing Redshift instances to ' + @@ -26,11 +26,6 @@ module.exports = { var source = {}; var regions = helpers.regions(settings); - var acctRegion = helpers.defaultRegion(settings); - var accountId = helpers.addSource(cache, source, - ['sts', 'getCallerIdentity', acctRegion, 'data']); - var awsOrGov = helpers.defaultPartition(settings); - async.each(regions.redshift, function(region, rcb){ var describeClusters = helpers.addSource(cache, source, ['redshift', 'describeClusters', region]); @@ -51,13 +46,12 @@ module.exports = { for (var i in describeClusters.data) { // For resource, attempt to use the endpoint address (more specific) but fallback to the instance identifier var cluster = describeClusters.data[i]; - var clusterIdentifier = cluster.ClusterIdentifier; - var resource = `arn:${awsOrGov}:redshift:${region}:${accountId}:cluster:${clusterIdentifier}`; + var clusterResource = (cluster.Endpoint && cluster.Endpoint.Address) ? cluster.Endpoint.Address : cluster.ClusterIdentifier; if (cluster.PubliclyAccessible) { - helpers.addResult(results, 1, 'Redshift cluster is publicly accessible', region, resource); + helpers.addResult(results, 1, 'Redshift cluster is publicly accessible', region, clusterResource); } else { - helpers.addResult(results, 0, 'Redshift cluster is not publicly accessible', region, resource); + helpers.addResult(results, 0, 'Redshift cluster is not publicly accessible', region, clusterResource); } } diff --git a/plugins/aws/redshift/redshiftUnusedReservedNodes.js b/plugins/aws/redshift/redshiftUnusedReservedNodes.js index da5309454b..74b9c8748d 100644 --- a/plugins/aws/redshift/redshiftUnusedReservedNodes.js +++ b/plugins/aws/redshift/redshiftUnusedReservedNodes.js @@ -9,18 +9,13 @@ module.exports = { more_info: 'Amazon Redshift reserved nodes must be utilized to avoid unnecessary billing.', link: 'https://docs.aws.amazon.com/redshift/latest/mgmt/purchase-reserved-node-instance.html', recommended_action: 'Provision new Redshift clusters matching the criteria of reserved nodes', - apis: ['Redshift:describeClusters', 'Redshift:describeReservedNodes', 'STS:getCallerIdentity'], + apis: ['Redshift:describeClusters', 'Redshift:describeReservedNodes'], run: function(cache, settings, callback) { var results = []; var source = {}; var regions = helpers.regions(settings); - var acctRegion = helpers.defaultRegion(settings); - var accountId = helpers.addSource(cache, source, - ['sts', 'getCallerIdentity', acctRegion, 'data']); - var awsOrGov = helpers.defaultPartition(settings); - async.each(regions.redshift, function(region, rcb){ var describeClusters = helpers.addSource(cache, source, ['redshift', 'describeClusters', region]); @@ -57,15 +52,14 @@ module.exports = { }); describeReservedNodes.data.forEach(node => { - var resource = `arn:${awsOrGov}:redshift:${region}:${accountId}:reserved-node:${node.ReservedNodeId}`; if (usedReservedNodes.includes(node.NodeType)) { helpers.addResult(results, 0, `Redshift reserved node "${node.ReservedNodeId}" is being used`, - region, resource); + region, node.ReservedNodeId); } else { helpers.addResult(results, 2, `Redshift reserved node "${node.ReservedNodeId}" is not being used`, - region, resource); + region, node.ReservedNodeId); } }); diff --git a/plugins/aws/s3/bucketPolicyCloudFrontOai.js b/plugins/aws/s3/bucketPolicyCloudFrontOai.js index 5a32653497..a4bce3da35 100644 --- a/plugins/aws/s3/bucketPolicyCloudFrontOai.js +++ b/plugins/aws/s3/bucketPolicyCloudFrontOai.js @@ -50,11 +50,10 @@ module.exports = { distribution.Origins.Items.length) { for (let origin of distribution.Origins.Items) { - if (origin.S3OriginConfig && origin.DomainName) { + if (origin.S3OriginConfig) { s3OriginFound = true; - let bucketName = origin.DomainName.replace(/.s3.*.com/, ''); - if (bucketName && - origin.S3OriginConfig.OriginAccessIdentity && + let bucketName = origin.DomainName.substring(0, origin.DomainName.indexOf('.s3.amazonaws.com')); + if (origin.S3OriginConfig.OriginAccessIdentity && origin.S3OriginConfig.OriginAccessIdentity.length) { let oaiId = origin.S3OriginConfig.OriginAccessIdentity.substring(origin.S3OriginConfig.OriginAccessIdentity.lastIndexOf('/') + 1); diff --git a/plugins/aws/s3/versionedBucketsLC.js b/plugins/aws/s3/versionedBucketsLC.js index e72735bcbd..cc947a9136 100644 --- a/plugins/aws/s3/versionedBucketsLC.js +++ b/plugins/aws/s3/versionedBucketsLC.js @@ -32,6 +32,11 @@ module.exports = { return callback(null, results, source); } + var nonCurrentVersionRules = [ + 'NoncurrentVersionTransitions', + 'NoncurrentVersionExpiration' + ]; + listBuckets.data.forEach(function(bucket){ var bucketLocation = helpers.getS3BucketLocation(cache, region, bucket.Name); @@ -63,8 +68,7 @@ module.exports = { if (ruleExists) { var ruleForNonCurrent = getBucketLifecycleConfiguration.data.Rules.find(rule => rule.Status && rule.Status.toUpperCase() === 'ENABLED' && - Object.keys(rule).some(key => (key == 'NoncurrentVersionTransitions' && rule[key].length) || - key == 'NoncurrentVersionExpiration' && Object.keys(rule[key]).length)); + Object.keys(rule).some(key => nonCurrentVersionRules.includes(key) && rule[key].length)); if (ruleForNonCurrent) { helpers.addResult(results, 0, `S3 bucket ${bucket.Name} has versioning and lifecycle configuration enabled for non-current versions`, diff --git a/plugins/aws/ses/dkimEnabled.js b/plugins/aws/ses/dkimEnabled.js index 37cd717c3d..0ef852a038 100644 --- a/plugins/aws/ses/dkimEnabled.js +++ b/plugins/aws/ses/dkimEnabled.js @@ -9,18 +9,13 @@ module.exports = { more_info: 'DKIM is a security feature that allows recipients of an email to veriy that the sender domain has authorized the message and that it has not been spoofed.', recommended_action: 'Enable DKIM for all domains and addresses in all regions used to send email through SES.', link: 'http://docs.aws.amazon.com/ses/latest/DeveloperGuide/easy-dkim.html', - apis: ['SES:listIdentities', 'SES:getIdentityDkimAttributes', 'STS:getCallerIdentity'], + apis: ['SES:listIdentities', 'SES:getIdentityDkimAttributes'], run: function(cache, settings, callback) { var results = []; var source = {}; var regions = helpers.regions(settings); - var acctRegion = helpers.defaultRegion(settings); - var accountId = helpers.addSource(cache, source, - ['sts', 'getCallerIdentity', acctRegion, 'data']); - var awsOrGov = helpers.defaultPartition(settings); - async.each(regions.ses, function(region, rcb){ var listIdentities = helpers.addSource(cache, source, ['ses', 'listIdentities', region]); @@ -50,17 +45,16 @@ module.exports = { } for (var i in getIdentityDkimAttributes.data.DkimAttributes) { - var resource = `arn:${awsOrGov}:ses:${region}:${accountId}:identity/${i}`; var identity = getIdentityDkimAttributes.data.DkimAttributes[i]; if (!identity.DkimEnabled) { - helpers.addResult(results, 2, 'DKIM is not enabled', region, resource); + helpers.addResult(results, 2, 'DKIM is not enabled', region, i); } else if (identity.DkimVerificationStatus !== 'Success') { helpers.addResult(results, 1, - 'DKIM is enabled, but not configured properly', region, resource); + 'DKIM is enabled, but not configured properly', region, i); } else { helpers.addResult(results, 0, - 'DKIM is enabled and configured properly', region, resource); + 'DKIM is enabled and configured properly', region, i); } } diff --git a/plugins/aws/sns/snsCrossAccount.js b/plugins/aws/sns/snsCrossAccount.js index c0a9e5a91c..0740a41c99 100644 --- a/plugins/aws/sns/snsCrossAccount.js +++ b/plugins/aws/sns/snsCrossAccount.js @@ -27,7 +27,7 @@ module.exports = { name: 'SNS Topic Policy Allowed Condition Keys', description: 'Comma separated list of AWS IAM condition keys that should be allowed i.e. aws:SourceAccount,aws:PrincipalArn', regex: '^.*$', - default: 'aws:PrincipalArn,aws:PrincipalAccount,aws:PrincipalOrgID,aws:SourceAccount,aws:SourceArn,aws:SourceOwner,sns:Endpoint' + default: 'aws:PrincipalArn,aws:PrincipalAccount,aws:PrincipalOrgID,aws:SourceAccount,aws:SourceArn,aws:SourceOwner' }, }, diff --git a/plugins/aws/sns/topicPolicies.js b/plugins/aws/sns/topicPolicies.js index 5405d5dcd3..56b390e168 100644 --- a/plugins/aws/sns/topicPolicies.js +++ b/plugins/aws/sns/topicPolicies.js @@ -19,7 +19,7 @@ module.exports = { '2. IAM condition keys which work with "Numeric" or "Date" operators are not used' + '3. Bool values are set to "true" with "Allow" and "false" with "Deny"', regex: '^.*$', - default: 'aws:PrincipalArn,aws:PrincipalAccount,aws:PrincipalOrgID,aws:SourceOwner,aws:SourceArn,aws:SourceAccount,sns:Endpoint' + default: 'aws:PrincipalArn,aws:PrincipalAccount,aws:PrincipalOrgID,aws:SourceOwner,aws:SourceArn,aws:SourceAccount' } }, diff --git a/plugins/azure/networksecuritygroups/openAllPorts.js b/plugins/azure/networksecuritygroups/openAllPorts.js index a53556db8e..2f4e3c8c7e 100644 --- a/plugins/azure/networksecuritygroups/openAllPorts.js +++ b/plugins/azure/networksecuritygroups/openAllPorts.js @@ -45,7 +45,7 @@ module.exports = { let ports = { 'TCP': ['*'], - 'UDP': ['*'], + 'UCP': ['*'], '*' : ['*'] }; From f5fbaab1c05efd17a340b5325e25d31d9d1ef072 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 23 May 2022 01:28:56 +0500 Subject: [PATCH 189/350] Added plugin enableDefenderForSqlServers --- exports.js | 1 + .../defender/enableDefenderForSqlServers.js | 53 +++++++++++ .../enableDefenderForSqlServers.spec.js | 87 +++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 plugins/azure/defender/enableDefenderForSqlServers.js create mode 100644 plugins/azure/defender/enableDefenderForSqlServers.spec.js diff --git a/exports.js b/exports.js index 3a4c78a858..7db3f9b568 100644 --- a/exports.js +++ b/exports.js @@ -766,6 +766,7 @@ module.exports = { 'enableDefenderForStorage' : require(__dirname + '/plugins/azure/defender/enableDefenderForStorage.js'), 'enableDefenderForContainers' : require(__dirname + '/plugins/azure/defender/enableDefenderForContainers.js'), + 'enableDefenderForSqlServers' : require(__dirname + '/plugins/azure/defender/enableDefenderForSqlServers.js'), }, github: { 'publicKeysRotated' : require(__dirname + '/plugins/github/users/publicKeysRotated.js'), diff --git a/plugins/azure/defender/enableDefenderForSqlServers.js b/plugins/azure/defender/enableDefenderForSqlServers.js new file mode 100644 index 0000000000..bca9c10360 --- /dev/null +++ b/plugins/azure/defender/enableDefenderForSqlServers.js @@ -0,0 +1,53 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Enable Defender For SQL Servers', + category: 'Defender', + domain: 'Management and Governance', + description: 'Ensures that Microsoft Defender is enabled for Azure SQL Server Databases.', + more_info: 'Turning on Microsoft Defender for Azure SQL Server Databases enables threat detection for Azure SQL database servers, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.', + recommended_action: 'Turning on Microsoft Defender for Azure SQL Databases incurs an additional cost per resource.', + link: 'https://docs.microsoft.com/en-us/azure/security-center/security-center-detection-capabilities', + apis: ['pricings:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.pricings, function(location, rcb) { + var pricings = helpers.addSource(cache, source, + ['pricings', 'list', location]); + + if (!pricings) return rcb(); + + if (pricings.err || !pricings.data) { + helpers.addResult(results, 3, + 'Unable to query for Pricing: ' + helpers.addError(pricings), location); + return rcb(); + } + + if (!pricings.data.length) { + helpers.addResult(results, 0, 'No Pricing information found', location); + return rcb(); + } + + let sqlServersPricing = pricings.data.find((pricing) => pricing.name && pricing.name.toLowerCase() === 'sqlservers'); + + if (sqlServersPricing) { + if (sqlServersPricing.pricingTier.toLowerCase() === 'standard') { + helpers.addResult(results, 0, 'Azure Defender is enabled for SQL Server Databases', location, sqlServersPricing.id); + } else { + helpers.addResult(results, 2, 'Azure Defender is not enabled for SQL Server Databases', location, sqlServersPricing.id); + } + } else { + helpers.addResult(results, 2, 'Azure Defender is not enabled for SQL Server Databases', location); + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/defender/enableDefenderForSqlServers.spec.js b/plugins/azure/defender/enableDefenderForSqlServers.spec.js new file mode 100644 index 0000000000..26a315964e --- /dev/null +++ b/plugins/azure/defender/enableDefenderForSqlServers.spec.js @@ -0,0 +1,87 @@ +var assert = require('assert'); +var expect = require('chai').expect; +var auth = require('./enableDefenderForSqlServers'); + +const createCache = (err, data) => { + return { + pricings: { + list: { + 'global': { + err: err, + data: data + } + } + } + } +}; + +describe('enableDefenderForSqlDatabases', function() { + describe('run', function() { + it('should give passing result if no pricings 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 Pricing information found'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [] + ); + + auth.run(cache, {}, callback); + }); + + it('should give failing result if Azure Defender for SQL Server Databases is not enabled', 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('Azure Defender is not enabled for SQL Server Databases'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [ + { + "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/providers/Microsoft.Security/pricings/default", + "name": "SqlServers", + "type": "Microsoft.Security/pricings", + "pricingTier": "free", + "location": "global" + } + ] + ); + + auth.run(cache, {}, callback); + }); + + it('should give passing result if Azure Defender for SQL Server Databases is enabled', 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('Azure Defender is enabled for SQL Server Databases'); + expect(results[0].region).to.equal('global'); + done() + }; + + const cache = createCache( + null, + [ + { + "id": "/subscriptions/e79d9a03-3ab3-4481-bdcd-c5db1d55420a/providers/Microsoft.Security/pricings/default", + "name": "SqlServers", + "type": "Microsoft.Security/pricings", + "pricingTier": "Standard", + "location": "global" + } + ] + ); + + auth.run(cache, {}, callback); + }) + }) +}); \ No newline at end of file From b905e3b7f2521f2808ee7445b5b054674b91416c Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 01:43:22 +0500 Subject: [PATCH 190/350] Update plugins/oracle/identity/usersPasswordLastUsed.js --- plugins/oracle/identity/usersPasswordLastUsed.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/oracle/identity/usersPasswordLastUsed.js b/plugins/oracle/identity/usersPasswordLastUsed.js index 3289479d51..805e60992e 100644 --- a/plugins/oracle/identity/usersPasswordLastUsed.js +++ b/plugins/oracle/identity/usersPasswordLastUsed.js @@ -10,8 +10,7 @@ module.exports = { recommended_action: 'Delete old user accounts that allow password-based logins and have not been used recently.', apis: ['user:list'], compliance: { - pci: 'PCI requires that all user credentials are rotated every 90 days. If the user password has not been used in the last 90 days, the user should be deactivated.', - cis1: '1.3 Ensure credentials unused for 90 days or greater are disabled' + pci: 'PCI requires that all user credentials are rotated every 90 days. If the user password has not been used in the last 90 days, the user should be deactivated.' }, settings: { identity_users_password_last_used_fail: { From 1034c17265c125eb2e39320332b8047e9437bc31 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 01:45:22 +0500 Subject: [PATCH 191/350] Update plugins/oracle/identity/usersPasswordLastUsed.js --- plugins/oracle/identity/usersPasswordLastUsed.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oracle/identity/usersPasswordLastUsed.js b/plugins/oracle/identity/usersPasswordLastUsed.js index 805e60992e..1a937abfcf 100644 --- a/plugins/oracle/identity/usersPasswordLastUsed.js +++ b/plugins/oracle/identity/usersPasswordLastUsed.js @@ -17,7 +17,7 @@ module.exports = { name: 'Users Password Last Used Fail', description: 'Return a failing result when users with password logins exceed this number of days without being used', regex: '^[1-9]{1}[0-9]{0,3}$', - default: 180 + default: '180' } }, From ff59cdcf963c0862c96007a6b99ffe4b9b7b67df Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 01:46:01 +0500 Subject: [PATCH 192/350] Update plugins/oracle/identity/usersPasswordLastUsed.js --- plugins/oracle/identity/usersPasswordLastUsed.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oracle/identity/usersPasswordLastUsed.js b/plugins/oracle/identity/usersPasswordLastUsed.js index 1a937abfcf..3115401be0 100644 --- a/plugins/oracle/identity/usersPasswordLastUsed.js +++ b/plugins/oracle/identity/usersPasswordLastUsed.js @@ -26,7 +26,7 @@ module.exports = { var results = []; var source = {}; var config = { - identity_users_password_last_used_fail: settings.identity_users_password_last_used_fail || this.settings.identity_users_password_last_used_fail.default, + identity_users_password_last_used_fail: parseInt(settings.identity_users_password_last_used_fail || this.settings.identity_users_password_last_used_fail.default) }; var region = helpers.objectFirstKey(cache['regionSubscription']['list']); From ce5f972888615b708f8c192cbdc79f5efd304de1 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 01:47:45 +0500 Subject: [PATCH 193/350] Update plugins/oracle/identity/usersPasswordLastUsed.js --- plugins/oracle/identity/usersPasswordLastUsed.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oracle/identity/usersPasswordLastUsed.js b/plugins/oracle/identity/usersPasswordLastUsed.js index 3115401be0..d2d2bd7e53 100644 --- a/plugins/oracle/identity/usersPasswordLastUsed.js +++ b/plugins/oracle/identity/usersPasswordLastUsed.js @@ -69,7 +69,7 @@ module.exports = { returnCode = 0; } - helpers.addResult(results, returnCode, returnMsg, 'global', user.name); + helpers.addResult(results, returnCode, returnMsg, 'global', user.id); found = true; } From ba0c747f8bbb8da073800fd625281dce5905644d Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 01:53:01 +0500 Subject: [PATCH 194/350] Update helpers/google/index.js --- helpers/google/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/google/index.js b/helpers/google/index.js index 88c93f6f0b..93139f0e2a 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -160,7 +160,7 @@ var run = function(GoogleConfig, collection, settings, service, callObj, callKey records = collection[callObj.reliesOnService[reliedService]][callObj.reliesOnCall[reliedService]][region].data; if (callObj.subObj) records = records.filter(record => !!record[callObj.subObj]); - async.eachLimit(records, 10, function(record, recordCb) { + async.eachLimit(records, 10, function(record, recordCb) { for (var property in callObj.properties) { callObj.urlToCall = callObj.url.replace(`{${callObj.properties[property]}}`, !callObj.subObj ? record[callObj.properties[property]] : record[callObj.subObj][callObj.properties[property]]); } From 1ed5e22e1390ac527a8eb1c63ba7922539565901 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 02:02:55 +0500 Subject: [PATCH 195/350] Update helpers/google/index.js --- helpers/google/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/google/index.js b/helpers/google/index.js index 88c93f6f0b..93139f0e2a 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -160,7 +160,7 @@ var run = function(GoogleConfig, collection, settings, service, callObj, callKey records = collection[callObj.reliesOnService[reliedService]][callObj.reliesOnCall[reliedService]][region].data; if (callObj.subObj) records = records.filter(record => !!record[callObj.subObj]); - async.eachLimit(records, 10, function(record, recordCb) { + async.eachLimit(records, 10, function(record, recordCb) { for (var property in callObj.properties) { callObj.urlToCall = callObj.url.replace(`{${callObj.properties[property]}}`, !callObj.subObj ? record[callObj.properties[property]] : record[callObj.subObj][callObj.properties[property]]); } From d0944918a3fcea193c087616dded4455a121065b Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 02:03:38 +0500 Subject: [PATCH 196/350] Update plugins/google/api/apiKeyRotation.js --- plugins/google/api/apiKeyRotation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/google/api/apiKeyRotation.js b/plugins/google/api/apiKeyRotation.js index 291477dcd0..09240720ba 100644 --- a/plugins/google/api/apiKeyRotation.js +++ b/plugins/google/api/apiKeyRotation.js @@ -1,7 +1,7 @@ var helpers = require('../../../helpers/google'); module.exports = { - title: 'Restricted API Keys', + title: 'API Key Rotation', category: 'API', domain: 'Identity and Access Management', description: 'Ensure that your Google Cloud API Keys are periodically regenerated.', From 75e605f39f2e5bd4c54a4e25c7c458b3d22c80a0 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 23 May 2022 02:08:29 +0500 Subject: [PATCH 197/350] made small fix --- plugins/google/api/apiKeyRotation.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/google/api/apiKeyRotation.spec.js b/plugins/google/api/apiKeyRotation.spec.js index cb41b3da39..1e5d80bc43 100644 --- a/plugins/google/api/apiKeyRotation.spec.js +++ b/plugins/google/api/apiKeyRotation.spec.js @@ -6,7 +6,7 @@ const apiKeys = [ { "name": "projects/my-project/locations/global/keys/my-key-1", "displayName": "API Key 1", - "createTime": '2022-04-07T17:23:05.126949Z', + "createTime": new Date(), }, { "name": "projects/my-project/locations/global/keys/my-key-2", From 9643cdba1fe38185746cdded3e90eb03aef47638 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 02:47:53 +0500 Subject: [PATCH 198/350] Update plugins/azure/advisor/checkAdvisorRecommendations.js --- plugins/azure/advisor/checkAdvisorRecommendations.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/advisor/checkAdvisorRecommendations.js b/plugins/azure/advisor/checkAdvisorRecommendations.js index d5456bdb4e..b6c94cfff7 100644 --- a/plugins/azure/advisor/checkAdvisorRecommendations.js +++ b/plugins/azure/advisor/checkAdvisorRecommendations.js @@ -2,7 +2,7 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); module.exports = { - title: 'Advisor Recommendations', + title: 'Active Advisor Recommendations', category: 'Advisor', domain: 'Application Integration', description: 'Ensure that all Microsoft Azure Advisor recommendations found are implemented to optimize your cloud deployments, increase security, and reduce costs.', From 1564e7be7f76a76c5f5290ec28a380abb8926d53 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 02:48:29 +0500 Subject: [PATCH 199/350] Update plugins/azure/advisor/checkAdvisorRecommendations.js --- plugins/azure/advisor/checkAdvisorRecommendations.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/advisor/checkAdvisorRecommendations.js b/plugins/azure/advisor/checkAdvisorRecommendations.js index b6c94cfff7..27e02324a6 100644 --- a/plugins/azure/advisor/checkAdvisorRecommendations.js +++ b/plugins/azure/advisor/checkAdvisorRecommendations.js @@ -31,7 +31,7 @@ module.exports = { helpers.addResult(results, 0, 'No Advisor Recommendations found', location); return rcb(); } else { - helpers.addResult(results, 2, 'Advisor Recommendations found', location); + helpers.addResult(results, 2, 'Active Advisor Recommendations found', location); } rcb(); From b28f83a3600494e7ee7a4f62fc3e3f8ac4d3a1f7 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Mon, 23 May 2022 12:36:54 +0500 Subject: [PATCH 200/350] Added check for only main service --- plugins/aws/iam/checkAllUsedServices.js | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/plugins/aws/iam/checkAllUsedServices.js b/plugins/aws/iam/checkAllUsedServices.js index 3b109ae8cb..847eb642b6 100644 --- a/plugins/aws/iam/checkAllUsedServices.js +++ b/plugins/aws/iam/checkAllUsedServices.js @@ -142,14 +142,17 @@ module.exports = { return callback(null, results, source); } - allResources = allResources.map((resource) => { + allResources = allResources.reduce((result, resource) => { let arr = resource.resourceType.split(':'); - return { - service: arr[2].toLowerCase(), - subService: arr[4].toLowerCase(), - count: resource.count - }; - }); + let key = arr[2].toLowerCase(); + result[key] = result[key] || []; + + if (resource.count > 0) { + result[key].push(arr[4]); + } + + return result; + }, {}); var listRoles = helpers.addSource(cache, source, ['iam', 'listRoles', iamRegion]); @@ -248,8 +251,7 @@ module.exports = { let service = statements.find((doc) => doc.Resource[0].includes('arn:')); if (service) { let serviceName = service.Resource[0].split(':')[2]; - let serviceFound = allResources.find((resource) => resource.service === serviceName && resource.count > 0); - if (!serviceFound) { + if (!(serviceName in allResources)) { if (policyFailures.indexOf(serviceName) === -1) policyFailures.push(serviceName); } } @@ -278,8 +280,7 @@ module.exports = { for (let statement of statements) { let services = [... new Set(statement.Action.map((action) => action.split(':')[0].toLowerCase()))]; services.forEach((service) => { - let serviceFound = allResources.find((resource) => resource.service === service && resource.count > 0); - if (!serviceFound) { + if (!(service in allResources)) { if (policyFailures.indexOf(service) === -1) policyFailures.push(service); } }); From 9fdf8b6453bbf8a12ad65f66aa1a5c1b8f32bbf9 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 13:29:47 +0500 Subject: [PATCH 201/350] Update plugins/azure/appservice/ftpsOnlyAccessEnabled.js --- plugins/azure/appservice/ftpsOnlyAccessEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/appservice/ftpsOnlyAccessEnabled.js b/plugins/azure/appservice/ftpsOnlyAccessEnabled.js index 6d82403a15..5db3eaf339 100644 --- a/plugins/azure/appservice/ftpsOnlyAccessEnabled.js +++ b/plugins/azure/appservice/ftpsOnlyAccessEnabled.js @@ -2,7 +2,7 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); module.exports = { - title: 'Web Apps FTPS-only access Enabled', + title: 'FTPS Only Access Enabled', category: 'App Service', domain: 'Application Integration', description: 'Ensures that Azure Web Apps have FTPS only access enabled.', From 367c549a5d7e5925235272469faeda8929dc55a9 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 13:32:15 +0500 Subject: [PATCH 202/350] Update plugins/azure/appservice/ftpsOnlyAccessEnabled.js --- plugins/azure/appservice/ftpsOnlyAccessEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/appservice/ftpsOnlyAccessEnabled.js b/plugins/azure/appservice/ftpsOnlyAccessEnabled.js index 5db3eaf339..578a99629f 100644 --- a/plugins/azure/appservice/ftpsOnlyAccessEnabled.js +++ b/plugins/azure/appservice/ftpsOnlyAccessEnabled.js @@ -46,7 +46,7 @@ module.exports = { return scb(); } - const ftpsOnlyAcces = configs.data[0] && configs.data[0].ftpsState; + const ftpsOnlyAcces = configs.data.every(config => config.ftpsState && config.ftpsState.toLowerCase() == 'ftpsonly'); if (ftpsOnlyAcces && ftpsOnlyAcces.toLowerCase() === 'ftpsonly') { helpers.addResult(results, 0, 'FTPS-only access is enabled for the Web App', location, webApp.id); From 145a86dd39624d113fc37e8ad6cdbb9e7c9ac75b Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 13:32:34 +0500 Subject: [PATCH 203/350] Update plugins/azure/appservice/ftpsOnlyAccessEnabled.js --- plugins/azure/appservice/ftpsOnlyAccessEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/appservice/ftpsOnlyAccessEnabled.js b/plugins/azure/appservice/ftpsOnlyAccessEnabled.js index 578a99629f..29bf42ad7f 100644 --- a/plugins/azure/appservice/ftpsOnlyAccessEnabled.js +++ b/plugins/azure/appservice/ftpsOnlyAccessEnabled.js @@ -48,7 +48,7 @@ module.exports = { const ftpsOnlyAcces = configs.data.every(config => config.ftpsState && config.ftpsState.toLowerCase() == 'ftpsonly'); - if (ftpsOnlyAcces && ftpsOnlyAcces.toLowerCase() === 'ftpsonly') { + if (ftpsOnlyAcces) { helpers.addResult(results, 0, 'FTPS-only access is enabled for the Web App', location, webApp.id); } else { helpers.addResult(results, 2, 'FTPS-only access is disabled for the Web App', location, webApp.id); From 6caffb0465b235bb67e026a492c48eb772485c19 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 13:40:23 +0500 Subject: [PATCH 204/350] Apply suggestions from code review --- plugins/azure/appservice/automatedBackupsEnabled.js | 4 ++-- plugins/azure/appservice/automatedBackupsEnabled.spec.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/azure/appservice/automatedBackupsEnabled.js b/plugins/azure/appservice/automatedBackupsEnabled.js index 08a3627945..1881b4131d 100644 --- a/plugins/azure/appservice/automatedBackupsEnabled.js +++ b/plugins/azure/appservice/automatedBackupsEnabled.js @@ -42,12 +42,12 @@ module.exports = { ['webApps', 'getBackupConfiguration', location, webApp.id]); if (configs && configs.err) { - helpers.addResult(results, 3, 'Unable to query for Web App Backup Configs: ' + helpers.addError(configs), location); + helpers.addResult(results, 3, 'Unable to query for Web App backup configs: ' + helpers.addError(configs), location); return scb(); } if (!configs || !configs.data) { - helpers.addResult(results, 2, 'Backups are not configured for this WebApp', location, webApp.id); + helpers.addResult(results, 2, 'Backups are not configured for WebApp', location, webApp.id); } else { helpers.addResult(results, 0, 'Backups are configured for this WebApp', location, webApp.id); } diff --git a/plugins/azure/appservice/automatedBackupsEnabled.spec.js b/plugins/azure/appservice/automatedBackupsEnabled.spec.js index 4be2f3a7e5..66b3d35368 100644 --- a/plugins/azure/appservice/automatedBackupsEnabled.spec.js +++ b/plugins/azure/appservice/automatedBackupsEnabled.spec.js @@ -103,7 +103,7 @@ describe('automatedBackupsEnabled', function() { automatedBackupsEnabled.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('Backups are not configured for this WebApp'); + expect(results[0].message).to.include('Backups are not configured for WebApp'); expect(results[0].region).to.equal('eastus'); done(); }); @@ -114,7 +114,7 @@ describe('automatedBackupsEnabled', function() { automatedBackupsEnabled.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('Backups are configured for this WebApp'); + expect(results[0].message).to.include('Backups are configured for WebApp'); expect(results[0].region).to.equal('eastus'); done(); }); From 2530f77b6cfe4d6ba79d4e5f1da5bc6f80e985cf Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 13:40:37 +0500 Subject: [PATCH 205/350] Update plugins/azure/appservice/automatedBackupsEnabled.js --- plugins/azure/appservice/automatedBackupsEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/appservice/automatedBackupsEnabled.js b/plugins/azure/appservice/automatedBackupsEnabled.js index 1881b4131d..0d6020d30d 100644 --- a/plugins/azure/appservice/automatedBackupsEnabled.js +++ b/plugins/azure/appservice/automatedBackupsEnabled.js @@ -49,7 +49,7 @@ module.exports = { if (!configs || !configs.data) { helpers.addResult(results, 2, 'Backups are not configured for WebApp', location, webApp.id); } else { - helpers.addResult(results, 0, 'Backups are configured for this WebApp', location, webApp.id); + helpers.addResult(results, 0, 'Backups are configured for WebApp', location, webApp.id); } scb(); From 00c51cbc30ad725bb3398b2210ad8c86c28e9eec Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 13:58:40 +0500 Subject: [PATCH 206/350] Apply suggestions from code review --- plugins/azure/appservice/webAppsADEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/appservice/webAppsADEnabled.js b/plugins/azure/appservice/webAppsADEnabled.js index 255a6f62a4..cc4d3266d4 100644 --- a/plugins/azure/appservice/webAppsADEnabled.js +++ b/plugins/azure/appservice/webAppsADEnabled.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Application Integration', description: 'Ensures that Azure Web Apps have registration with Azure Active Directory.', more_info: 'Registration with Azure Active Directory (AAD) enables App Service web applications to connect to other Azure cloud services securely without the need of access credentials such as user names and passwords.', - recommended_action: 'Enable Registration with Azure Active Directory for Azure Web Apps', + recommended_action: 'Enable registration with Azure Active Directory for Azure Web Apps.', link: 'https://docs.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=portal%2Chttp#add-a-system-assigned-identity', apis: ['webApps:list'], From 83881eb119cbba22ce81afb9d1bd42611368d9c1 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 14:01:47 +0500 Subject: [PATCH 207/350] Update plugins/azure/keyvaults/appTierCmkInUse.js --- plugins/azure/keyvaults/appTierCmkInUse.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/keyvaults/appTierCmkInUse.js b/plugins/azure/keyvaults/appTierCmkInUse.js index 5270ff8c94..a3e019f702 100644 --- a/plugins/azure/keyvaults/appTierCmkInUse.js +++ b/plugins/azure/keyvaults/appTierCmkInUse.js @@ -2,7 +2,7 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); module.exports = { - title: 'CMK Creation for App Tier Enabled', + title: 'App Tier CMK In Use', category: 'Key Vaults', domain: 'Application Integration', description: 'Ensure that a Customer-Managed Key (CMK) is created and configured for your Microsoft Azure application tier.', From 03cafff06d3e61eaef412847560f1ab733c3b56c Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 14:02:31 +0500 Subject: [PATCH 208/350] Update collectors/azure/collector.js --- collectors/azure/collector.js | 1 - 1 file changed, 1 deletion(-) diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index 4258a7ccf9..8255577059 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -446,7 +446,6 @@ var postcalls = { url: '{vaultUri}certificates?api-version=7.3', vault: true } - }, databases: { listByServer: { From 2482a15f21fffad28359b4ebb19b7bc33e84360e Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 15:53:39 +0500 Subject: [PATCH 209/350] Delete rsaCertificateAllowedKeySizes.js duplicate file --- .../rsaCertificateAllowedKeySizes.js | 83 ------------------- 1 file changed, 83 deletions(-) delete mode 100644 plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.js diff --git a/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.js b/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.js deleted file mode 100644 index 504820a91e..0000000000 --- a/plugins/azure/keyvaults/rsaCertificateAllowedKeySizes.js +++ /dev/null @@ -1,83 +0,0 @@ -var async = require('async'); -var helpers = require('../../../helpers/azure'); - -module.exports = { - title: 'RSA Certificate Allowed Key Size', - category: 'Key Vaults', - domain: 'Application Integration', - description: 'Ensures that Microsoft Azure Key Vault RSA certificates are using the allowed key size.', - more_info: 'Having the right key type size for your Azure Key Vault RSA certificates will enforce the best practices as specified in the security and compliance regulations implemented within your organization.', - recommended_action: 'Ensure that Key Vault RSA certificates are using the allowed key types.', - link: 'https://docs.microsoft.com/en-us/azure/key-vault/certificates/about-certificates', - apis: ['vaults:list', 'vaults:getCertificates', 'getCertificatePolicy:get'], - settings: { - min_rsa_certificate_key_size: { - name: 'Minimum RSA Certificate Allowed Key Size', - description: 'Key sizes supported for rsa certificates in Azure Key Vault', - regex: '^(2048|3072|4096)$', - default: '2048' - } - }, - - run: function(cache, settings, callback) { - var results = []; - var source = {}; - var locations = helpers.locations(settings.govcloud); - var config = { - min_rsa_certificate_key_size: parseInt(settings.min_rsa_certificate_key_size || this.settings.min_rsa_certificate_key_size.default) - }; - - async.each(locations.vaults, function(location, rcb) { - var vaults = helpers.addSource(cache, source, - ['vaults', 'list', location]); - - if (!vaults) return rcb(); - - if (vaults.err || !vaults.data) { - helpers.addResult(results, 3, 'Unable to query for Key Vaults: ' + helpers.addError(vaults), location); - return rcb(); - } - - if (!vaults.data.length) { - helpers.addResult(results, 0, 'No Key Vaults found', location); - return rcb(); - } - - vaults.data.forEach((vault) => { - var certificates = helpers.addSource(cache, source, - ['vaults', 'getCertificates', location, vault.id]); - - if (!certificates || certificates.err || !certificates.data) { - helpers.addResult(results, 3, 'Unable to query for Key Vault certificates: ' + helpers.addError(certificates), location, vault.id); - } else if (!certificates.data.length) { - helpers.addResult(results, 0, 'No Key Vault Certificates found', location, vault.id); - } else { - certificates.data.forEach((certificate) => { - var certificatePolicy = helpers.addSource(cache, source, - ['getCertificatePolicy', 'get', location, certificate.id]); - - if (!certificatePolicy || certificatePolicy.err || !certificatePolicy.data) { - helpers.addResult(results, 3, 'Unable to query for Certificate Policy: ' + helpers.addError(certificatePolicy), location, certificate.id); - } else { - const certificateKeys = certificatePolicy.data.key_props; - - if (certificateKeys && certificateKeys.kty) { - if (certificateKeys.key_size >= config.min_rsa_certificate_key_size) { - helpers.addResult(results, 0, `RSA Certificate key size is ${certificateKeys.key_size}`, location, certificate.id); - } else { - helpers.addResult(results, 2, `RSA Certificate key size is ${certificateKeys.key_size}`, location, certificate.id); - } - } else { - helpers.addResult(results, 3, 'Unable to list key type for Key Vault Certificate: ' + helpers.addError(certificatePolicy), location, certificate.id); - } - } - }); - } - }); - - rcb(); - }, function() { - callback(null, results, source); - }); - } -}; From 9a2c246ce6d0743d0ab49fb813f934c29fc614cf Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 16:10:37 +0500 Subject: [PATCH 210/350] Apply suggestions from code review --- plugins/aws/cloudformation/stackTerminationProtection.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/aws/cloudformation/stackTerminationProtection.js b/plugins/aws/cloudformation/stackTerminationProtection.js index 6dcf365d71..43b5d1146e 100644 --- a/plugins/aws/cloudformation/stackTerminationProtection.js +++ b/plugins/aws/cloudformation/stackTerminationProtection.js @@ -10,7 +10,7 @@ module.exports = { link: 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-protect-stacks.html', recommended_action: 'Enable termination protection for CloudFormation stack', apis: ['CloudFormation:listStacks', 'CloudFormation:describeStacks'], - remediation_description: 'Stack Termination protection will be enabled.', + remediation_description: 'Stack termination protection will be enabled for affected stacks.', remediation_min_version: '202205161341', apis_remediate: ['CloudFormation:listStacks', 'CloudFormation:describeStacks'], actions: { @@ -91,7 +91,7 @@ module.exports = { var stackLocation = stackNameArr[3]; - // add the location of the parameter group to the config + // add the location of the cloudformation stack to the config config.region = stackLocation; var params = {}; From 3fcb64ca1bbc33d31a5fe40719b71f3af6560ca2 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 23 May 2022 16:21:38 +0500 Subject: [PATCH 211/350] Update plugins/aws/cloudformation/stackTerminationProtection.js --- plugins/aws/cloudformation/stackTerminationProtection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/cloudformation/stackTerminationProtection.js b/plugins/aws/cloudformation/stackTerminationProtection.js index 43b5d1146e..41f74d5f66 100644 --- a/plugins/aws/cloudformation/stackTerminationProtection.js +++ b/plugins/aws/cloudformation/stackTerminationProtection.js @@ -21,7 +21,7 @@ module.exports = { remediate: ['cloudformation:UpdateTerminationProtection'], rollback: ['cloudformation:UpdateTerminationProtection'] }, - realtime_triggers: ['cloudformation:UpdateTerminationProtection'], + realtime_triggers: ['cloudformation:UpdateTerminationProtection', cloudformation:createStack], run: function(cache, settings, callback) { var results = []; From 87857fc6bc736034889f03670f89b2006dacf059 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 23 May 2022 16:22:20 +0500 Subject: [PATCH 212/350] Update plugins/aws/cloudformation/stackTerminationProtection.js --- plugins/aws/cloudformation/stackTerminationProtection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/cloudformation/stackTerminationProtection.js b/plugins/aws/cloudformation/stackTerminationProtection.js index 41f74d5f66..cae406c456 100644 --- a/plugins/aws/cloudformation/stackTerminationProtection.js +++ b/plugins/aws/cloudformation/stackTerminationProtection.js @@ -21,7 +21,7 @@ module.exports = { remediate: ['cloudformation:UpdateTerminationProtection'], rollback: ['cloudformation:UpdateTerminationProtection'] }, - realtime_triggers: ['cloudformation:UpdateTerminationProtection', cloudformation:createStack], + realtime_triggers: ['cloudformation:UpdateTerminationProtection', 'cloudformation:createStack'], run: function(cache, settings, callback) { var results = []; From f88019dacb3116fe73d8e9f93891b4099a058137 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 23 May 2022 16:25:00 +0500 Subject: [PATCH 213/350] added azure sqlServerSendScanReports plugin --- exports.js | 1 + .../sqlserver/sqlServerSendScanReports.js | 67 ++++++++ .../sqlServerSendScanReports.spec.js | 157 ++++++++++++++++++ 3 files changed, 225 insertions(+) create mode 100644 plugins/azure/sqlserver/sqlServerSendScanReports.js create mode 100644 plugins/azure/sqlserver/sqlServerSendScanReports.spec.js diff --git a/exports.js b/exports.js index 8093729f24..54cf7160ed 100644 --- a/exports.js +++ b/exports.js @@ -712,6 +712,7 @@ module.exports = { 'automaticTuningEnabled' : require(__dirname + '/plugins/azure/sqlserver/automaticTuningEnabled.js'), 'serverSendEmailToAdmins' : require(__dirname + '/plugins/azure/sqlserver/serverSendEmailToAdmins.js'), 'sqlServerRecurringScans' : require(__dirname + '/plugins/azure/sqlserver/sqlServerRecurringScans.js'), + 'sqlServerSendScanReports' : require(__dirname + '/plugins/azure/sqlserver/sqlServerSendScanReports.js'), 'javaVersion' : require(__dirname + '/plugins/azure/appservice/javaVersion.js'), 'phpVersion' : require(__dirname + '/plugins/azure/appservice/phpVersion.js'), diff --git a/plugins/azure/sqlserver/sqlServerSendScanReports.js b/plugins/azure/sqlserver/sqlServerSendScanReports.js new file mode 100644 index 0000000000..8c09149dd5 --- /dev/null +++ b/plugins/azure/sqlserver/sqlServerSendScanReports.js @@ -0,0 +1,67 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'SQL Server Send Scan Reports', + category: 'SQL Server', + domain: 'Databases', + description: 'Ensures that Send Scan Reports is enabled for SQL Servers.', + more_info: 'Vulnerability Assessment (VA) scan reports and alerts will be sent to email ids configured at Send scan reports to. This may help in reducing time required for identifying risks and taking corrective measures.', + recommended_action: 'Configure Send scan reports to with email ids of concerned data owners/stakeholders for a critical SQL servers.', + link: 'https://docs.microsoft.com/en-us/azure/sql-database/sql-vulnerability-assessment', + apis: ['servers:listSql', 'vulnerabilityAssessments:listByServer'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + + async.each(locations.servers, function(location, rcb) { + + var servers = helpers.addSource(cache, source, + ['servers', 'listSql', location]); + + if (!servers) return rcb(); + + if (servers.err || !servers.data) { + helpers.addResult(results, 3, + 'Unable to query for SQL servers: ' + helpers.addError(servers), location); + return rcb(); + } + + if (!servers.data.length) { + helpers.addResult(results, 0, 'No SQL servers found', location); + return rcb(); + } + + servers.data.forEach(function(server) { + const vulnerabilityAssessments = helpers.addSource(cache, source, + ['vulnerabilityAssessments', 'listByServer', location, server.id]); + + if (!vulnerabilityAssessments || vulnerabilityAssessments.err || !vulnerabilityAssessments.data) { + helpers.addResult(results, 3, + 'Unable to query for Vulnerability Assessments setting: ' + helpers.addError(vulnerabilityAssessments), location, server.id); + } else { + if (!vulnerabilityAssessments.data.length) { + helpers.addResult(results, 2, 'No Vulnerability Assessments setting found', location, server.id); + } else { + vulnerabilityAssessments.data.forEach(vulnerabilityAssessment => { + if (vulnerabilityAssessment.recurringScans && vulnerabilityAssessment.recurringScans.emails + && vulnerabilityAssessment.recurringScans.emails.length) { + helpers.addResult(results, 0, + 'Send Scan Reports for the SQL server is enabled', location, server.id); + } else { + helpers.addResult(results, 2, + 'Send Scan Reports for the SQL server is disabled', location, server.id); + } + }); + } + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/sqlserver/sqlServerSendScanReports.spec.js b/plugins/azure/sqlserver/sqlServerSendScanReports.spec.js new file mode 100644 index 0000000000..b565f22349 --- /dev/null +++ b/plugins/azure/sqlserver/sqlServerSendScanReports.spec.js @@ -0,0 +1,157 @@ +var expect = require('chai').expect; +var sqlServerSendScanReports = require('./sqlServerSendScanReports'); + +const servers = [ + { + "id": "/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server", + } +]; + +const vulnerabilityAssessments = [ + { + id: '/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server/vulnerabilityAssessments/Default', + name: 'Default', + type: 'Microsoft.Sql/servers/vulnerabilityAssessments', + storageContainerPath: 'https://sqlvadfi44mwgvnjki.blob.core.windows.net/vulnerability-assessment/', + recurringScans: { isEnabled: true, emailSubscriptionAdmins: true, emails: [ 'test@gmail.com' ] } + }, + { + id: '/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server/vulnerabilityAssessments/Default', + name: 'Default', + type: 'Microsoft.Sql/servers/vulnerabilityAssessments', + storageContainerPath: 'https://sqlvadfi44mwgvnjki.blob.core.windows.net/vulnerability-assessment/', + recurringScans: { isEnabled: false, emailSubscriptionAdmins: true, emails: [] } + } +]; + +const createCache = (servers, policies, serversErr, policiesErr) => { + const serverId = (servers && servers.length) ? servers[0].id : null; + return { + servers: { + listSql: { + 'eastus': { + err: serversErr, + data: servers + } + } + }, + vulnerabilityAssessments: { + listByServer: { + 'eastus': { + [serverId]: { + err: policiesErr, + data: policies + } + } + } + } + } +}; + +describe('sqlServerSendScanReports', function() { + describe('run', function() { + it('should give passing result if no SQL 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 SQL servers found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + [] + ); + + sqlServerSendScanReports.run(cache, {}, callback); + }); + + it('should give failing result if No Vulnerability Assessments setting found', 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('No Vulnerability Assessments setting found'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [] + ); + + sqlServerSendScanReports.run(cache, {}, callback); + }); + + it('should give failing result if Send Scan Reports for the SQL server is disabled', 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('Send Scan Reports for the SQL server is disabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [vulnerabilityAssessments[1]] + ); + + sqlServerSendScanReports.run(cache, {}, callback); + }); + + it('should give passing result if Send Scan Reports for the SQL server is enabled', 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('Send Scan Reports for the SQL server is enabled'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [vulnerabilityAssessments[0]] + ); + + sqlServerSendScanReports.run(cache, {}, callback); + }); + + it('should give unknown result if unable to query for SQL servers', 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 SQL servers'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [], + { message: 'unable to query servers'} + ); + + sqlServerSendScanReports.run(cache, {}, callback); + }); + + it('should give unknown result if Unable to query for Vulnerability Assessments setting', 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 Vulnerability Assessments setting'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [], + null, + { message: 'Unable to query for Vulnerability Assessments setting'} + ); + + sqlServerSendScanReports.run(cache, {}, callback); + }); + }) +}); \ No newline at end of file From 72a110042ae2a037ebdf08bf7c90b76bc2b1c47d Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Mon, 23 May 2022 16:25:38 +0500 Subject: [PATCH 214/350] Updated plugin --- plugins/aws/iam/checkAllUsedServices.spec.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 plugins/aws/iam/checkAllUsedServices.spec.js diff --git a/plugins/aws/iam/checkAllUsedServices.spec.js b/plugins/aws/iam/checkAllUsedServices.spec.js deleted file mode 100644 index e69de29bb2..0000000000 From da250a83a58e69f80a3462ceeb678808309294ae Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Mon, 23 May 2022 17:09:01 +0500 Subject: [PATCH 215/350] Updated plugin description and recommended action --- exports.js | 2 +- ...TPIntegration.js => enableEndpointIntegration.js} | 12 ++++++------ ...ion.spec.js => enableEndpointIntegration.spec.js} | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) rename plugins/azure/defender/{enableWDATPIntegration.js => enableEndpointIntegration.js} (77%) rename plugins/azure/defender/{enableWDATPIntegration.spec.js => enableEndpointIntegration.spec.js} (81%) diff --git a/exports.js b/exports.js index 17e8c5f018..676c118ba2 100644 --- a/exports.js +++ b/exports.js @@ -781,10 +781,10 @@ module.exports = { 'checkAdvisorRecommendations' : require(__dirname + '/plugins/azure/advisor/checkAdvisorRecommendations.js'), - 'enableWDATPIntegration' : require(__dirname + '/plugins/azure/defender/enableWDATPIntegration.js'), 'enableDefenderForStorage' : require(__dirname + '/plugins/azure/defender/enableDefenderForStorage.js'), 'enableDefenderForContainers' : require(__dirname + '/plugins/azure/defender/enableDefenderForContainers.js'), 'enableDefenderForSqlServers' : require(__dirname + '/plugins/azure/defender/enableDefenderForSqlServers.js'), + 'enableEndpointIntegration' : require(__dirname + '/plugins/azure/defender/enableEndpointIntegration.js'), }, github: { 'publicKeysRotated' : require(__dirname + '/plugins/github/users/publicKeysRotated.js'), diff --git a/plugins/azure/defender/enableWDATPIntegration.js b/plugins/azure/defender/enableEndpointIntegration.js similarity index 77% rename from plugins/azure/defender/enableWDATPIntegration.js rename to plugins/azure/defender/enableEndpointIntegration.js index c732120f23..92331a72cb 100644 --- a/plugins/azure/defender/enableWDATPIntegration.js +++ b/plugins/azure/defender/enableEndpointIntegration.js @@ -2,12 +2,12 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); module.exports = { - title: 'Enable WDATP Integration', + title: 'Enable Defender Endpoint Integration', category: 'Defender', - domain: 'Management and Governance', - description: 'Ensures that WDATP integration is enabled for Microsoft Defender for Cloud.', + domain: 'Security', + description: 'Ensures that Microsoft Defender for Endpoint integration is enabled.', more_info: 'WDATP integration brings comprehensive Endpoint Detection and Response (EDR) capabilities within Microsoft Defender for Cloud. This integration helps to spot abnormalities, detect and respond to advanced attacks on Windows server endpoints monitored by Microsoft Defender for Cloud. Windows Defender ATP in Microsoft Defender for Cloud supports detection on Windows Server 2016, 2012 R2, and 2008 R2 SP1 operating systems in a Standard service subscription.', - recommended_action: 'Ensure that Microsoft Defender for Endpoint integration is selected with Microsoft Defender for Cloud.', + recommended_action: 'Enable "Allow Microsoft Defender for Endpoint to access my data setting" in Defender environment settings.', link: 'https://docs.microsoft.com/en-in/azure/defender-for-cloud/integration-defender-for-endpoint?tabs=windows', apis: ['securityCenter:list'], @@ -35,9 +35,9 @@ module.exports = { const wdatpIntegration = defenderSettings.data.find((settings) => settings.name && settings.name.toLowerCase() === 'wdatp'); if (wdatpIntegration && wdatpIntegration.enabled) { - helpers.addResult(results, 0, 'WDATP integration is enabled for Microsoft Defender', location, wdatpIntegration.id); + helpers.addResult(results, 0, 'Endpoint integration is enabled for Microsoft Defender', location, wdatpIntegration.id); } else { - helpers.addResult(results, 2, 'WDATP integration is not enabled for Microsoft Defender', location); + helpers.addResult(results, 2, 'Endpoint integration is not enabled for Microsoft Defender', location); } rcb(); diff --git a/plugins/azure/defender/enableWDATPIntegration.spec.js b/plugins/azure/defender/enableEndpointIntegration.spec.js similarity index 81% rename from plugins/azure/defender/enableWDATPIntegration.spec.js rename to plugins/azure/defender/enableEndpointIntegration.spec.js index 9084e394dc..b847881b89 100644 --- a/plugins/azure/defender/enableWDATPIntegration.spec.js +++ b/plugins/azure/defender/enableEndpointIntegration.spec.js @@ -1,6 +1,6 @@ var assert = require('assert'); var expect = require('chai').expect; -var auth = require('./enableWDATPIntegration'); +var auth = require('./enableEndpointIntegration'); const createCache = (err, data) => { return { @@ -15,7 +15,7 @@ const createCache = (err, data) => { } }; -describe('enableWDATPIntegration', function() { +describe('enableEndpointIntegration', function() { describe('run', function() { it('should give passing result if no settings found', function(done) { const callback = (err, results) => { @@ -34,11 +34,11 @@ describe('enableWDATPIntegration', function() { auth.run(cache, {}, callback); }); - it('should give failing result if WDATP integration is not enabled for Azure Defender', function(done) { + it('should give failing result if Endpoint integration is not enabled for Azure Defender', 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('WDATP integration is not enabled for Microsoft Defender'); + expect(results[0].message).to.include('Endpoint integration is not enabled for Microsoft Defender'); expect(results[0].region).to.equal('global'); done() }; @@ -59,11 +59,11 @@ describe('enableWDATPIntegration', function() { auth.run(cache, {}, callback); }); - it('should give passing result if WDATP integration is enabled for Azure Defender', function(done) { + it('should give passing result if Endpoint integration is enabled for Azure Defender', 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('WDATP integration is enabled for Microsoft Defender'); + expect(results[0].message).to.include('Endpoint integration is enabled for Microsoft Defender'); expect(results[0].region).to.equal('global'); done() }; From 83e13c729592166a9324c32922ceccd74657c20f Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 17:30:52 +0500 Subject: [PATCH 216/350] Update plugins/azure/defender/enableEndpointIntegration.js --- plugins/azure/defender/enableEndpointIntegration.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/defender/enableEndpointIntegration.js b/plugins/azure/defender/enableEndpointIntegration.js index 92331a72cb..4b8cc52ab2 100644 --- a/plugins/azure/defender/enableEndpointIntegration.js +++ b/plugins/azure/defender/enableEndpointIntegration.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/azure'); module.exports = { title: 'Enable Defender Endpoint Integration', category: 'Defender', - domain: 'Security', + domain: 'Management and Governance', description: 'Ensures that Microsoft Defender for Endpoint integration is enabled.', more_info: 'WDATP integration brings comprehensive Endpoint Detection and Response (EDR) capabilities within Microsoft Defender for Cloud. This integration helps to spot abnormalities, detect and respond to advanced attacks on Windows server endpoints monitored by Microsoft Defender for Cloud. Windows Defender ATP in Microsoft Defender for Cloud supports detection on Windows Server 2016, 2012 R2, and 2008 R2 SP1 operating systems in a Standard service subscription.', recommended_action: 'Enable "Allow Microsoft Defender for Endpoint to access my data setting" in Defender environment settings.', From e8fd1a3f52bf9c00af457fa40481561394fefba5 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 17:31:44 +0500 Subject: [PATCH 217/350] Update plugins/azure/defender/enableEndpointIntegration.js --- plugins/azure/defender/enableEndpointIntegration.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/defender/enableEndpointIntegration.js b/plugins/azure/defender/enableEndpointIntegration.js index 4b8cc52ab2..295ff8a696 100644 --- a/plugins/azure/defender/enableEndpointIntegration.js +++ b/plugins/azure/defender/enableEndpointIntegration.js @@ -6,7 +6,7 @@ module.exports = { category: 'Defender', domain: 'Management and Governance', description: 'Ensures that Microsoft Defender for Endpoint integration is enabled.', - more_info: 'WDATP integration brings comprehensive Endpoint Detection and Response (EDR) capabilities within Microsoft Defender for Cloud. This integration helps to spot abnormalities, detect and respond to advanced attacks on Windows server endpoints monitored by Microsoft Defender for Cloud. Windows Defender ATP in Microsoft Defender for Cloud supports detection on Windows Server 2016, 2012 R2, and 2008 R2 SP1 operating systems in a Standard service subscription.', + more_info: 'Window Defender ATP integration brings comprehensive Endpoint Detection and Response (EDR) capabilities within Microsoft Defender for Cloud. This integration helps to spot abnormalities, detect and respond to advanced attacks on Windows server endpoints monitored by Microsoft Defender for Cloud.', recommended_action: 'Enable "Allow Microsoft Defender for Endpoint to access my data setting" in Defender environment settings.', link: 'https://docs.microsoft.com/en-in/azure/defender-for-cloud/integration-defender-for-endpoint?tabs=windows', apis: ['securityCenter:list'], From 866899fb7b26b3ebccd14e4ecf2029b753e353cb Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 23 May 2022 17:32:22 +0500 Subject: [PATCH 218/350] Update plugins/aws/cloudformation/stackTerminationProtection.js --- plugins/aws/cloudformation/stackTerminationProtection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/cloudformation/stackTerminationProtection.js b/plugins/aws/cloudformation/stackTerminationProtection.js index cae406c456..861be034fe 100644 --- a/plugins/aws/cloudformation/stackTerminationProtection.js +++ b/plugins/aws/cloudformation/stackTerminationProtection.js @@ -21,7 +21,7 @@ module.exports = { remediate: ['cloudformation:UpdateTerminationProtection'], rollback: ['cloudformation:UpdateTerminationProtection'] }, - realtime_triggers: ['cloudformation:UpdateTerminationProtection', 'cloudformation:createStack'], + realtime_triggers: ['cloudformation:UpdateTerminationProtection', 'cloudformation:CreateStack'], run: function(cache, settings, callback) { var results = []; From 2c7732181467ddc19265bca45de1ea66be110093 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 23 May 2022 18:23:27 +0500 Subject: [PATCH 219/350] made few fixes --- .../azure/keyvaults/rsaCertificateKeySize.js | 16 +++++++----- .../keyvaults/rsaCertificateKeySize.spec.js | 2 +- .../keyvaults/sslCertificateAutoRenewal.js | 22 +++++++++------- .../sqlserver/emailAccountAdminsEnabled.js | 22 ++++++++-------- plugins/azure/sqlserver/enableATP.js | 20 +++++++------- plugins/azure/sqlserver/sendAlertsEnabled.js | 26 +++++++++---------- .../azure/sqlserver/serverAuditingEnabled.js | 16 ++++++------ .../sqlserver/serverSendEmailToAdmins.js | 18 ++++++------- .../sqlserver/sqlServerRecurringScans.js | 19 +++++++------- .../sqlserver/sqlServerSendScanReports.js | 21 ++++++++------- 10 files changed, 96 insertions(+), 86 deletions(-) diff --git a/plugins/azure/keyvaults/rsaCertificateKeySize.js b/plugins/azure/keyvaults/rsaCertificateKeySize.js index 02912604b8..7bd79a457e 100644 --- a/plugins/azure/keyvaults/rsaCertificateKeySize.js +++ b/plugins/azure/keyvaults/rsaCertificateKeySize.js @@ -59,16 +59,20 @@ module.exports = { if (!certificatePolicy || certificatePolicy.err || !certificatePolicy.data) { helpers.addResult(results, 3, 'Unable to query for Certificate Policy: ' + helpers.addError(certificatePolicy), location, certificate.id); } else { - const certificateKeys = certificatePolicy.data.key_props; + if (certificatePolicy.data.attributes && certificatePolicy.data.attributes.enabled) { + const certificateKeys = certificatePolicy.data.key_props; - if (certificateKeys && certificateKeys.kty) { - if (certificateKeys.key_size >= config.min_rsa_certificate_key_size) { - helpers.addResult(results, 0, `RSA Certificate key size is ${certificateKeys.key_size}`, location, certificate.id); + if (certificateKeys && certificateKeys.kty) { + if (certificateKeys.key_size >= config.min_rsa_certificate_key_size) { + helpers.addResult(results, 0, `RSA Certificate key size is ${certificateKeys.key_size}`, location, certificate.id); + } else { + helpers.addResult(results, 2, `RSA Certificate key size is ${certificateKeys.key_size}`, location, certificate.id); + } } else { - helpers.addResult(results, 2, `RSA Certificate key size is ${certificateKeys.key_size}`, location, certificate.id); + helpers.addResult(results, 3, 'Unable to list key type for Key Vault Certificate: ' + helpers.addError(certificatePolicy), location, certificate.id); } } else { - helpers.addResult(results, 3, 'Unable to list key type for Key Vault Certificate: ' + helpers.addError(certificatePolicy), location, certificate.id); + helpers.addResult(results, 0, 'RSA Certificate is not enabled', location, certificate.id); } } }); diff --git a/plugins/azure/keyvaults/rsaCertificateKeySize.spec.js b/plugins/azure/keyvaults/rsaCertificateKeySize.spec.js index 46c07c66ff..2ce275f0ca 100644 --- a/plugins/azure/keyvaults/rsaCertificateKeySize.spec.js +++ b/plugins/azure/keyvaults/rsaCertificateKeySize.spec.js @@ -167,7 +167,7 @@ describe('rsaCertificateKeySize', function() { done() }; - auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [certificates] } }, { data: [certificatePolicy[1]] } ), {}, callback); + auth.run(createCache(null, [listVaults[0]], { "/subscriptions/abcdef123-ebf6-437f-a3b0-28fc0d22117e/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.KeyVault/vaults/testvault": { data: [certificates] } }, { data: certificatePolicy[1] } ), {}, callback); }); it('should give passing result if certificate has allowed key type', function(done) { diff --git a/plugins/azure/keyvaults/sslCertificateAutoRenewal.js b/plugins/azure/keyvaults/sslCertificateAutoRenewal.js index 918ebf36db..dd9af8504b 100644 --- a/plugins/azure/keyvaults/sslCertificateAutoRenewal.js +++ b/plugins/azure/keyvaults/sslCertificateAutoRenewal.js @@ -48,16 +48,20 @@ module.exports = { if (!certificatePolicy || certificatePolicy.err || !certificatePolicy.data) { helpers.addResult(results, 3, 'Unable to query for Certificate Policy: ' + helpers.addError(certificatePolicy), location, certificate.id); } else { - const lifetimeActions = certificatePolicy.data.lifetime_actions; - - let autoRenew = lifetimeActions && lifetimeActions.find(lifetimeAction => - lifetimeAction.action && lifetimeAction.action.action_type && - lifetimeAction.action.action_type.toLowerCase() == 'autorenew'); - - if (autoRenew) { - helpers.addResult(results, 0, 'SSL Certificate auto renewal is enabled', location, certificate.id); + if (certificatePolicy.data.attributes && certificatePolicy.data.attributes.enabled) { + const lifetimeActions = certificatePolicy.data.lifetime_actions; + + let autoRenew = lifetimeActions && lifetimeActions.find(lifetimeAction => + lifetimeAction.action && lifetimeAction.action.action_type && + lifetimeAction.action.action_type.toLowerCase() == 'autorenew'); + + if (autoRenew) { + helpers.addResult(results, 0, 'SSL Certificate auto renewal is enabled', location, certificate.id); + } else { + helpers.addResult(results, 2, 'SSL Certificate auto renewal is not enabled', location, certificate.id); + } } else { - helpers.addResult(results, 2, 'SSL Certificate auto renewal is not enabled', location, certificate.id); + helpers.addResult(results, 0, 'SSL Certificate is not enabled', location, certificate.id); } } }); diff --git a/plugins/azure/sqlserver/emailAccountAdminsEnabled.js b/plugins/azure/sqlserver/emailAccountAdminsEnabled.js index d9d891e592..13a214da5c 100644 --- a/plugins/azure/sqlserver/emailAccountAdminsEnabled.js +++ b/plugins/azure/sqlserver/emailAccountAdminsEnabled.js @@ -45,17 +45,17 @@ module.exports = { if (!serverSecurityAlertPolicies.data.length) { helpers.addResult(results, 2, 'Database Threat Detection Policies are not enabled on the server', location, server.id); } else { - serverSecurityAlertPolicies.data.forEach(serverSecurityAlertPolicy => { - if (serverSecurityAlertPolicy.state && - serverSecurityAlertPolicy.state.toLowerCase() == 'enabled' && - serverSecurityAlertPolicy.emailAccountAdmins) { - helpers.addResult(results, 0, - 'Email Account Admins is enabled on the SQL server', location, server.id); - } else { - helpers.addResult(results, 2, - 'Email Account Admins is not enabled on the SQL server', location, server.id); - } - }); + let emailAccountsAdmins = serverSecurityAlertPolicies.data.find(serverSecurityAlertPolicy => + serverSecurityAlertPolicy.state && + serverSecurityAlertPolicy.state.toLowerCase() == 'enabled' && + serverSecurityAlertPolicy.emailAccountAdmins); + if (emailAccountsAdmins) { + helpers.addResult(results, 0, + 'Email Account Admins is enabled on the SQL server', location, server.id); + } else { + helpers.addResult(results, 2, + 'Email Account Admins is not enabled on the SQL server', location, server.id); + } } } }); diff --git a/plugins/azure/sqlserver/enableATP.js b/plugins/azure/sqlserver/enableATP.js index d083259b6f..a660401bd6 100644 --- a/plugins/azure/sqlserver/enableATP.js +++ b/plugins/azure/sqlserver/enableATP.js @@ -45,16 +45,16 @@ module.exports = { if (!advancedThreatProtectionSettings.data.length) { helpers.addResult(results, 2, 'No Advanced Threat Protection setting found', location, server.id); } else { - advancedThreatProtectionSettings.data.forEach(threadProtectionSetting => { - if (threadProtectionSetting.state && - threadProtectionSetting.state.toLowerCase() == 'enabled') { - helpers.addResult(results, 0, - 'Advanced Threat Protection for the SQL server is enabled', location, server.id); - } else { - helpers.addResult(results, 2, - 'Advanced Threat Protection for the SQL server is disabled', location, server.id); - } - }); + let atpEnabled = advancedThreatProtectionSettings.data.find(threadProtectionSetting => + threadProtectionSetting.state && + threadProtectionSetting.state.toLowerCase() == 'enabled'); + if (atpEnabled) { + helpers.addResult(results, 0, + 'Advanced Threat Protection for the SQL server is enabled', location, server.id); + } else { + helpers.addResult(results, 2, + 'Advanced Threat Protection for the SQL server is disabled', location, server.id); + } } } }); diff --git a/plugins/azure/sqlserver/sendAlertsEnabled.js b/plugins/azure/sqlserver/sendAlertsEnabled.js index 72a6288987..dc77cd4442 100644 --- a/plugins/azure/sqlserver/sendAlertsEnabled.js +++ b/plugins/azure/sqlserver/sendAlertsEnabled.js @@ -45,19 +45,19 @@ module.exports = { if (!serverSecurityAlertPolicies.data.length) { helpers.addResult(results, 2, 'Database Threat Detection Policies are not enabled on the server', location, server.id); } else { - serverSecurityAlertPolicies.data.forEach(serverSecurityAlertPolicy => { - if (serverSecurityAlertPolicy.state && - serverSecurityAlertPolicy.state.toLowerCase() == 'enabled' && - serverSecurityAlertPolicy.emailAddresses && - serverSecurityAlertPolicy.emailAddresses[0] && - serverSecurityAlertPolicy.emailAddresses[0] != '') { - helpers.addResult(results, 0, - 'Send alerts is enabled on the SQL server', location, server.id); - } else { - helpers.addResult(results, 2, - 'Send alerts is not enabled on the SQL server', location, server.id); - } - }); + let alertsEnabled = serverSecurityAlertPolicies.data.find(serverSecurityAlertPolicy => + serverSecurityAlertPolicy.state && + serverSecurityAlertPolicy.state.toLowerCase() == 'enabled' && + serverSecurityAlertPolicy.emailAddresses && + serverSecurityAlertPolicy.emailAddresses[0] && + serverSecurityAlertPolicy.emailAddresses[0] != ''); + if (alertsEnabled) { + helpers.addResult(results, 0, + 'Send alerts is enabled on the SQL server', location, server.id); + } else { + helpers.addResult(results, 2, + 'Send alerts is not enabled on the SQL server', location, server.id); + } } } }); diff --git a/plugins/azure/sqlserver/serverAuditingEnabled.js b/plugins/azure/sqlserver/serverAuditingEnabled.js index 6d873a4fb1..c8b324fc40 100644 --- a/plugins/azure/sqlserver/serverAuditingEnabled.js +++ b/plugins/azure/sqlserver/serverAuditingEnabled.js @@ -50,14 +50,14 @@ module.exports = { if (!serverBlobAuditingPolicies.data.length) { helpers.addResult(results, 2, 'No Server Auditing policies found', location, server.id); } else { - serverBlobAuditingPolicies.data.forEach(serverBlobAuditingPolicy => { - if (serverBlobAuditingPolicy.state && - serverBlobAuditingPolicy.state.toLowerCase() === 'enabled') { - helpers.addResult(results, 0, 'Server auditing is enabled on the SQL Server', location, server.id); - } else { - helpers.addResult(results, 2, 'Server auditing is not enabled on the SQL Server', location, server.id); - } - }); + let auditingEnabled = serverBlobAuditingPolicies.data.find(serverBlobAuditingPolicy => + serverBlobAuditingPolicy.state && + serverBlobAuditingPolicy.state.toLowerCase() === 'enabled'); + if (auditingEnabled) { + helpers.addResult(results, 0, 'Server auditing is enabled on the SQL Server', location, server.id); + } else { + helpers.addResult(results, 2, 'Server auditing is not enabled on the SQL Server', location, server.id); + } } } }); diff --git a/plugins/azure/sqlserver/serverSendEmailToAdmins.js b/plugins/azure/sqlserver/serverSendEmailToAdmins.js index 700dfc192d..caf50f03f5 100644 --- a/plugins/azure/sqlserver/serverSendEmailToAdmins.js +++ b/plugins/azure/sqlserver/serverSendEmailToAdmins.js @@ -44,15 +44,15 @@ module.exports = { if (!vulnerabilityAssessments.data.length) { helpers.addResult(results, 2, 'No Vulnerability Assessments setting found', location, server.id); } else { - vulnerabilityAssessments.data.forEach(vulnerabilityAssessment => { - if (vulnerabilityAssessment.recurringScans && vulnerabilityAssessment.recurringScans.emailSubscriptionAdmins) { - helpers.addResult(results, 0, - 'Send Email notifications to admins for the SQL server is enabled', location, server.id); - } else { - helpers.addResult(results, 2, - 'Send Email notifications to admins for the SQL server is disabled', location, server.id); - } - }); + let emailNotificationEnabled = vulnerabilityAssessments.data.find(vulnerabilityAssessment => + vulnerabilityAssessment.recurringScans && vulnerabilityAssessment.recurringScans.emailSubscriptionAdmins); + if (emailNotificationEnabled) { + helpers.addResult(results, 0, + 'Send Email notifications to admins for the SQL server is enabled', location, server.id); + } else { + helpers.addResult(results, 2, + 'Send Email notifications to admins for the SQL server is disabled', location, server.id); + } } } }); diff --git a/plugins/azure/sqlserver/sqlServerRecurringScans.js b/plugins/azure/sqlserver/sqlServerRecurringScans.js index 2d612db9c3..2f2c5ae015 100644 --- a/plugins/azure/sqlserver/sqlServerRecurringScans.js +++ b/plugins/azure/sqlserver/sqlServerRecurringScans.js @@ -45,15 +45,16 @@ module.exports = { if (!vulnerabilityAssessments.data.length) { helpers.addResult(results, 2, 'No Vulnerability Assessments setting found', location, server.id); } else { - vulnerabilityAssessments.data.forEach(vulnerabilityAssessment => { - if (vulnerabilityAssessment.recurringScans && vulnerabilityAssessment.recurringScans.isEnabled) { - helpers.addResult(results, 0, - 'Recurring Scans for the SQL server is enabled', location, server.id); - } else { - helpers.addResult(results, 2, - 'Recurring Scans for the SQL server is disabled', location, server.id); - } - }); + let recScansEnabled = vulnerabilityAssessments.data.find(vulnerabilityAssessment => + vulnerabilityAssessment.recurringScans && vulnerabilityAssessment.recurringScans.isEnabled); + + if (recScansEnabled) { + helpers.addResult(results, 0, + 'Recurring Scans for the SQL server is enabled', location, server.id); + } else { + helpers.addResult(results, 2, + 'Recurring Scans for the SQL server is disabled', location, server.id); + } } } }); diff --git a/plugins/azure/sqlserver/sqlServerSendScanReports.js b/plugins/azure/sqlserver/sqlServerSendScanReports.js index 8c09149dd5..25a8704dd7 100644 --- a/plugins/azure/sqlserver/sqlServerSendScanReports.js +++ b/plugins/azure/sqlserver/sqlServerSendScanReports.js @@ -45,16 +45,17 @@ module.exports = { if (!vulnerabilityAssessments.data.length) { helpers.addResult(results, 2, 'No Vulnerability Assessments setting found', location, server.id); } else { - vulnerabilityAssessments.data.forEach(vulnerabilityAssessment => { - if (vulnerabilityAssessment.recurringScans && vulnerabilityAssessment.recurringScans.emails - && vulnerabilityAssessment.recurringScans.emails.length) { - helpers.addResult(results, 0, - 'Send Scan Reports for the SQL server is enabled', location, server.id); - } else { - helpers.addResult(results, 2, - 'Send Scan Reports for the SQL server is disabled', location, server.id); - } - }); + let scanReports = vulnerabilityAssessments.data.find(vulnerabilityAssessment => + vulnerabilityAssessment.recurringScans && + vulnerabilityAssessment.recurringScans.emails&& + vulnerabilityAssessment.recurringScans.emails.length); + if (scanReports) { + helpers.addResult(results, 0, + 'Send Scan Reports for the SQL server is enabled', location, server.id); + } else { + helpers.addResult(results, 2, + 'Send Scan Reports for the SQL server is disabled', location, server.id); + } } } }); From 998ed550b6a6e3947c9c64bc73c588b7f609bb4b Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 23 May 2022 18:44:55 +0500 Subject: [PATCH 220/350] Added result for empty security rules --- plugins/azure/networksecuritygroups/openUDP.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/azure/networksecuritygroups/openUDP.js b/plugins/azure/networksecuritygroups/openUDP.js index 00ff708717..1a3f2605f7 100644 --- a/plugins/azure/networksecuritygroups/openUDP.js +++ b/plugins/azure/networksecuritygroups/openUDP.js @@ -37,7 +37,6 @@ module.exports = { for (let s in networkSecurityGroups.data) { var sg = networkSecurityGroups.data[s]; - let openUdpPorts = false; if (sg.securityRules && sg.securityRules.length) { @@ -69,6 +68,9 @@ module.exports = { helpers.addResult(results, 0, 'The security group: ' + sg.name + ' does not have open UDP ports for internet access', location, sg.id); } + } else { + helpers.addResult(results, 0, + 'The security group: ' + sg.name + ' does not have any security rules', location, sg.id); } } rcb(); From 2ccb42f059d01853ab251bcc87a44eedd1370c83 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 23 May 2022 20:52:52 +0500 Subject: [PATCH 221/350] Update plugins/aws/iam/checkAllUsedServices.js --- plugins/aws/iam/checkAllUsedServices.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/iam/checkAllUsedServices.js b/plugins/aws/iam/checkAllUsedServices.js index 847eb642b6..5f0572d784 100644 --- a/plugins/aws/iam/checkAllUsedServices.js +++ b/plugins/aws/iam/checkAllUsedServices.js @@ -7,7 +7,7 @@ module.exports = { title: 'Check All Used Services', category: 'IAM', domain: 'Identity and Access management', - description: 'Ensures IAM role policies are properly scoped with specific permissions', + description: 'Ensure that IAM role policies are scoped properly as to not provide access to unused AWS services.', more_info: 'Policies attached to IAM roles should be scoped to least-privileged access and avoid the use of wildcards.', link: 'https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html', recommended_action: 'Ensure that all IAM roles are scoped to specific services and API calls.', From 2da0265c7a4932890fd822fe40bef7065919663d Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Wed, 25 May 2022 22:33:19 +0500 Subject: [PATCH 222/350] Added Missing Specs For AWS Plugins --- plugins/aws/acm/acmValidation.spec.js | 218 ++++++++++++++++++ .../redshiftEncryptionEnabled.spec.js | 121 ++++++++++ .../redshiftPubliclyAccessible.spec.js | 121 ++++++++++ plugins/aws/route53/domainAutoRenew.spec.js | 81 +++++++ plugins/aws/route53/domainExpiry.spec.js | 125 ++++++++++ .../aws/route53/domainTransferLock.spec.js | 101 ++++++++ 6 files changed, 767 insertions(+) create mode 100644 plugins/aws/acm/acmValidation.spec.js create mode 100644 plugins/aws/redshift/redshiftEncryptionEnabled.spec.js create mode 100644 plugins/aws/redshift/redshiftPubliclyAccessible.spec.js create mode 100644 plugins/aws/route53/domainAutoRenew.spec.js create mode 100644 plugins/aws/route53/domainExpiry.spec.js create mode 100644 plugins/aws/route53/domainTransferLock.spec.js diff --git a/plugins/aws/acm/acmValidation.spec.js b/plugins/aws/acm/acmValidation.spec.js new file mode 100644 index 0000000000..237d343984 --- /dev/null +++ b/plugins/aws/acm/acmValidation.spec.js @@ -0,0 +1,218 @@ +var expect = require('chai').expect; +var acmValidation = require('./acmValidation'); + +const listCertificates = [ + { + "CertificateArn": "arn:aws:acm:us-east-1:000011122222:certificate/4eb67297-7e64-4f9b-bfd1-38f962df491c", + "DomainName": "CoolDude69.com" + }, + { + "CertificateArn": "arn:aws:acm:us-east-1:000011122222:certificate/8951d876-8417-4d5c-8caa-5f73a3b1211e", + "DomainName": "*.viteace.com" + } +]; + +const describeCertificate = [ + { + "Certificate": { + "CertificateArn": "arn:aws:acm:us-east-1:000011122222:certificate/4eb67297-7e64-4f9b-bfd1-38f962df491c", + "DomainName": "cooldude69.com", + "SubjectAlternativeNames": [ + "cooldude69.com" + ], + "DomainValidationOptions": [ + { + "DomainName": "cooldude69.com", + "ValidationDomain": "cooldude69.com", + "ValidationStatus": "SUCCESS", + "ResourceRecord": { + "Name": "_fe4c0c0adae010605a723ccc178d8c77.cooldude69.com.", + "Type": "CNAME", + "Value": "_788985d4b083a63504b1d46c7db65abb.gbwdrhjxvn.acm-validations.aws." + }, + "ValidationMethod": "DNS" + } + ], + "Subject": "CN=cooldude69.com", + "Issuer": "Amazon", + "CreatedAt": "2022-03-09T17:39:31.095000+05:00", + "Status": "PENDING_VALIDATION", + "KeyAlgorithm": "RSA-2048", + "SignatureAlgorithm": "SHA256WITHRSA", + "InUseBy": [], + "Type": "AMAZON_ISSUED", + "KeyUsages": [], + "ExtendedKeyUsages": [], + "RenewalEligibility": "INELIGIBLE", + "Options": { + "CertificateTransparencyLoggingPreference": "ENABLED" + } + } + }, + { + + "Certificate": { + "CertificateArn": "arn:aws:acm:us-east-1:000011122222:certificate/8951d876-8417-4d5c-8caa-5f73a3b1211e", + "DomainName": "*.viteace.com", + "SubjectAlternativeNames": [ + "*.viteace.com" + ], + "DomainValidationOptions": [ + { + "DomainName": "*.viteace.com", + "ValidationDomain": "*.viteace.com", + "ValidationStatus": "PENDING_VALIDATION", + "ResourceRecord": { + "Name": "_4f0a6aaf33ac9cc46e53f8ca0a6f9763.viteace.com.", + "Type": "CNAME", + "Value": "_2711d4a887c089c7518bfdb01655daf3.gbwdrhjxvn.acm-validations.aws." + }, + "ValidationMethod": "DNS" + } + ], + "Subject": "CN=*.viteace.com", + "Issuer": "Amazon", + "CreatedAt": "2022-03-09T17:58:27.078000+05:00", + "Status": "PENDING_VALIDATION", + "KeyAlgorithm": "RSA-2048", + "SignatureAlgorithm": "SHA256WITHRSA", + "InUseBy": [], + "Type": "AMAZON_ISSUED", + "KeyUsages": [], + "ExtendedKeyUsages": [], + "RenewalEligibility": "INELIGIBLE", + "Options": { + "CertificateTransparencyLoggingPreference": "ENABLED" + } + } + }, + { + + "Certificate": { + "CertificateArn": "arn:aws:acm:us-east-1:000011122222:certificate/8951d876-8417-4d5c-8caa-5f73a3b1211e", + "DomainName": "*.viteace.com", + "SubjectAlternativeNames": [ + "*.viteace.com" + ], + "DomainValidationOptions": [ + { + "DomainName": "*.viteace.com", + "ValidationDomain": "*.viteace.com", + "ValidationStatus": "SUCCESS", + "ResourceRecord": { + "Name": "_4f0a6aaf33ac9cc46e53f8ca0a6f9763.viteace.com.", + "Type": "CNAME", + "Value": "_2711d4a887c089c7518bfdb01655daf3.gbwdrhjxvn.acm-validations.aws." + }, + "ValidationMethod": "EMAIL" + } + ], + "Subject": "CN=*.viteace.com", + "Issuer": "Amazon", + "CreatedAt": "2022-03-09T17:58:27.078000+05:00", + "Status": "PENDING_VALIDATION", + "KeyAlgorithm": "RSA-2048", + "SignatureAlgorithm": "SHA256WITHRSA", + "InUseBy": [], + "Type": "AMAZON_ISSUED", + "KeyUsages": [], + "ExtendedKeyUsages": [], + "RenewalEligibility": "INELIGIBLE", + "Options": { + "CertificateTransparencyLoggingPreference": "ENABLED" + } + } +} +]; + +const createCache = (listData, listErr, describeData, describeErr) => { + var certArn = (listData && listData.length) ? listData[0].CertificateArn : null; + return { + acm: { + listCertificates: { + 'us-east-1': { + data: listData, + err: listErr + }, + }, + describeCertificate: { + 'us-east-1': { + [certArn]: { + data: describeData, + err: describeErr + }, + }, + } + }, + }; +}; + +describe('acmValidation', function () { + describe('run', function () { + it('should PASS if ACM certificate is using DNS validations', function (done) { + const cache = createCache([listCertificates[0]], null, describeCertificate[0]); + acmValidation.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('is using DNS validation') + done(); + }); + }); + + it('should FAIL if ACM certificate has failed validations', function (done) { + const cache = createCache([listCertificates[0]], null, describeCertificate[1]); + acmValidation.run(cache, { acm_certificate_expiry_warn: '35' }, (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('has failed DNS validation') + done(); + }); + }); + + it('should WARN if ACM certificate is using EMAIL validation', function (done) { + const cache = createCache([listCertificates[0]], null, describeCertificate[2]); + acmValidation.run(cache, { acm_certificate_expiry_warn: '35' }, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(1); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('is using EMAIL validation') + done(); + }); + }); + + it('should PASS if No ACM certificates found', function (done) { + const cache = createCache([]); + acmValidation.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 ACM certificates found') + done(); + }); + }); + + it('should UNKNOWN if unable to list ACM certificates', function (done) { + const cache = createCache(null, { message: 'err' }); + acmValidation.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 ACM certificates') + done(); + }); + }); + + it('should UNKNOWN if unable to describe ACM certificate', function (done) { + const cache = createCache([listCertificates[0]], null, null, { message: 'err' }); + acmValidation.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 describe ACM certificate') + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/aws/redshift/redshiftEncryptionEnabled.spec.js b/plugins/aws/redshift/redshiftEncryptionEnabled.spec.js new file mode 100644 index 0000000000..3d3469ae91 --- /dev/null +++ b/plugins/aws/redshift/redshiftEncryptionEnabled.spec.js @@ -0,0 +1,121 @@ +var expect = require('chai').expect; +const redshiftEncryptionEnabled = require('./redshiftEncryptionEnabled'); + +const describeClusters = [ + { + "ClusterIdentifier": "redshift-cluster-1", + "NodeType": "ds2.xlarge", + "ClusterStatus": "available", + "ClusterAvailabilityStatus": "Available", + "ClusterVersion": "1.0", + "AllowVersionUpgrade": true, + "NumberOfNodes": 1, + "PubliclyAccessible": false, + "Encrypted": false + }, + { + "ClusterIdentifier": "redshift-cluster-1", + "NodeType": "ds2.xlarge", + "ClusterStatus": "available", + "ClusterAvailabilityStatus": "Available", + "ClusterVersion": "1.0", + "AllowVersionUpgrade": true, + "NumberOfNodes": 1, + "PubliclyAccessible": false, + "Encrypted": true + } +]; + + +const createCache = (clusters) => { + return { + redshift:{ + describeClusters: { + 'us-east-1': { + data: clusters + }, + }, + }, + }; +}; + +const createErrorCache = () => { + return { + redshift:{ + describeClusters: { + 'us-east-1': { + err: { + message: 'error describing redshift clusters' + }, + }, + }, + }, + }; +}; + +const createNullCache = () => { + return { + redshift:{ + describeClusters: { + 'us-east-1': null, + }, + }, + }; +}; + +describe('redshiftEncryptionEnabled', function () { + describe('run', function () { + it('should PASS if Redshift cluster is encrypted', function (done) { + const cache = createCache([describeClusters[1]]); + redshiftEncryptionEnabled.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('Redshift cluster is encrypted'); + done(); + }); + }); + + it('should WARN if Redshift cluster is not encrypted', function (done) { + const cache = createCache([describeClusters[0]]); + redshiftEncryptionEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(1); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('Redshift cluster is not encrypted'); + done(); + }); + }); + + it('should PASS if no Redshift clusters found', function (done) { + const cache = createCache([]); + redshiftEncryptionEnabled.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 Redshift clusters found'); + done(); + }); + }); + + it('should UNKNOWN if Unable to query for Redshift clusters', function (done) { + const cache = createErrorCache(); + redshiftEncryptionEnabled.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 Redshift clusters'); + done(); + }); + }); + + it('should not return anything if describe clusters response is not found', function (done) { + const cache = createNullCache(); + redshiftEncryptionEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + + }); +}); \ No newline at end of file diff --git a/plugins/aws/redshift/redshiftPubliclyAccessible.spec.js b/plugins/aws/redshift/redshiftPubliclyAccessible.spec.js new file mode 100644 index 0000000000..dfe9f8f683 --- /dev/null +++ b/plugins/aws/redshift/redshiftPubliclyAccessible.spec.js @@ -0,0 +1,121 @@ +var expect = require('chai').expect; +const redshiftPubliclyAccessible = require('./redshiftPubliclyAccessible'); + +const describeClusters = [ + { + "ClusterIdentifier": "redshift-cluster-1", + "NodeType": "ds2.xlarge", + "ClusterStatus": "available", + "ClusterAvailabilityStatus": "Available", + "ClusterVersion": "1.0", + "AllowVersionUpgrade": true, + "NumberOfNodes": 1, + "PubliclyAccessible": false, + "Encrypted": false + }, + { + "ClusterIdentifier": "redshift-cluster-1", + "NodeType": "ds2.xlarge", + "ClusterStatus": "available", + "ClusterAvailabilityStatus": "Available", + "ClusterVersion": "1.0", + "AllowVersionUpgrade": true, + "NumberOfNodes": 1, + "PubliclyAccessible": true, + "Encrypted": true + } +]; + + +const createCache = (clusters) => { + return { + redshift:{ + describeClusters: { + 'us-east-1': { + data: clusters + }, + }, + }, + }; +}; + +const createErrorCache = () => { + return { + redshift:{ + describeClusters: { + 'us-east-1': { + err: { + message: 'error describing redshift clusters' + }, + }, + }, + }, + }; +}; + +const createNullCache = () => { + return { + redshift:{ + describeClusters: { + 'us-east-1': null, + }, + }, + }; +}; + +describe('redshiftPubliclyAccessible', function () { + describe('run', function () { + it('should PASS if Redshift cluster is not publicly accessible', function (done) { + const cache = createCache([describeClusters[0]]); + redshiftPubliclyAccessible.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('Redshift cluster is not publicly accessible'); + done(); + }); + }); + + it('should WARN if Redshift cluster is publicly accessible', function (done) { + const cache = createCache([describeClusters[1]]); + redshiftPubliclyAccessible.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(1); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('Redshift cluster is publicly accessible'); + done(); + }); + }); + + it('should PASS if no Redshift clusters found', function (done) { + const cache = createCache([]); + redshiftPubliclyAccessible.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 Redshift clusters found'); + done(); + }); + }); + + it('should UNKNOWN if Unable to query for Redshift clusters', function (done) { + const cache = createErrorCache(); + redshiftPubliclyAccessible.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 Redshift clusters'); + done(); + }); + }); + + it('should not return anything if describe clusters response is not found', function (done) { + const cache = createNullCache(); + redshiftPubliclyAccessible.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + + }); +}); \ No newline at end of file diff --git a/plugins/aws/route53/domainAutoRenew.spec.js b/plugins/aws/route53/domainAutoRenew.spec.js new file mode 100644 index 0000000000..3c9a9fab6d --- /dev/null +++ b/plugins/aws/route53/domainAutoRenew.spec.js @@ -0,0 +1,81 @@ +const expect = require('chai').expect; +var domainAutoRenew = require('./domainAutoRenew'); + +const domains = [ + { + "DomainName": "test-domain.com", + "AutoRenew" : true + }, + { + "DomainName": "test-domain.com", + "AutoRenew" : false + } +] + + +const createCache = (domain, domainErr) => { + return { + route53domains: { + listDomains: { + 'us-east-1': { + data: domain, + err: domainErr + } + }, + } + }; +}; + +const createNullCache = () => { + return { + route53domains: { + listDomains: { + 'us-east-1': null + } + } + }; +}; + +describe('domainAutoRenew', function () { + describe('run', function () { + + it('should PASS if Domain has auto renew enabled', function (done) { + const cache = createCache([domains[0]]); + domainAutoRenew.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('has auto renew enabled'); + done(); + }); + }); + + it('should FAIL if Domain does not have auto renew enabled', function (done) { + const cache = createCache([domains[1]]); + domainAutoRenew.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(1); + expect(results[0].message).to.include('does not have auto renew enabled'); + done(); + }); + }); + + it('should UNKNOWN if Unable to query for domains', function (done) { + const cache = createCache([], {}, { message: 'Unable to query for domains' }); + domainAutoRenew.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 domains'); + done(); + }); + }); + + + it('should not return anything if list domains response not found', function (done) { + const cache = createNullCache(); + domainAutoRenew.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/aws/route53/domainExpiry.spec.js b/plugins/aws/route53/domainExpiry.spec.js new file mode 100644 index 0000000000..7842138147 --- /dev/null +++ b/plugins/aws/route53/domainExpiry.spec.js @@ -0,0 +1,125 @@ +const expect = require('chai').expect; +var domainExpiry = require('./domainExpiry'); + + +var domainWarn = new Date(); +domainWarn.setMonth(domainWarn.getMonth() + 1); +var domainPass = new Date(); +domainPass.setMonth(domainPass.getMonth() + 2); +var domainFail = new Date(); +domainFail.setMonth(domainFail.getMonth() - 1); + +const domains = [ + { + "DomainName": "example.com", + "AutoRenew": true, + "TransferLock": true, + "Expiry": domainPass + }, + { + "DomainName": "example.com.ar", + "AutoRenew": true, + "TransferLock": true, + "Expiry": domainPass + }, + { + "DomainName": "example.com", + "AutoRenew": true, + "TransferLock": false, + "Expiry": domainFail + }, + { + "DomainName": "example.com.uk", + "AutoRenew": true, + "TransferLock": true + }, +]; + + +const createCache = (domain, domainErr) => { + return { + route53domains: { + listDomains: { + 'us-east-1': { + data: domain, + err: domainErr + } + }, + } + }; +}; + +const createNullCache = () => { + return { + route53domains: { + listDomains: { + 'us-east-1': null + } + } + }; +}; + +describe('domainExpiry', function () { + describe('run', function () { + + it('should PASS if Domain will expire', function (done) { + const cache = createCache([domains[0]]); + domainExpiry.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('expires in'); + done(); + }); + }); + + it('should FAIL if Domain expired', function (done) { + const cache = createCache([domains[2]]); + domainExpiry.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('expired'); + done(); + }); + }); + + it('should PASS if Domain will expire', function (done) { + const cache = createCache([domains[1]]); + domainExpiry.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('expires in'); + done(); + }); + }); + + + it('should UNKNOWN if Expiration for domain could not be determined', function (done) { + const cache = createCache([domains[3]]); + domainExpiry.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('could not be determined'); + done(); + }); + }); + + it('should UNKNOWN if Unable to query for domains', function (done) { + const cache = createCache([], {}, { message: 'Unable to query for domains' }); + domainExpiry.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 domains'); + done(); + }); + }); + + + it('should not return anything if list domains response not found', function (done) { + const cache = createNullCache(); + domainExpiry.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/plugins/aws/route53/domainTransferLock.spec.js b/plugins/aws/route53/domainTransferLock.spec.js new file mode 100644 index 0000000000..889aee3be5 --- /dev/null +++ b/plugins/aws/route53/domainTransferLock.spec.js @@ -0,0 +1,101 @@ +const expect = require('chai').expect; +var domainTransferLock = require('./domainTransferLock'); + +const domains = [ + { + "DomainName": "example.com", + "AutoRenew": true, + "TransferLock": true, + "Expiry": 1602712345.0 + }, + { + "DomainName": "example.com.", + "AutoRenew": true, + "TransferLock": false, + "Expiry": 1602712345.0 + }, + { + "DomainName": "example.com.uk", + "AutoRenew": true, + "TransferLock": true, + "Expiry": 1602712345.0 + } +] + + +const createCache = (domain, domainErr) => { + return { + route53domains: { + listDomains: { + 'us-east-1': { + data: domain, + err: domainErr + } + }, + } + }; +}; + +const createNullCache = () => { + return { + route53domains: { + listDomains: { + 'us-east-1': null + } + } + }; +}; + +describe('domainTransferLock', function () { + describe('run', function () { + + it('should PASS if Domain has the transfer lock enabled', function (done) { + const cache = createCache([domains[0]]); + domainTransferLock.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('has the transfer lock enabled'); + done(); + }); + }); + + it('should FAIL if Domain does not have the transfer lock enabled', function (done) { + const cache = createCache([domains[1]]); + domainTransferLock.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('does not have the transfer lock enabled'); + done(); + }); + }); + + it('should PASS if Domain does not support transfer locks', function (done) { + const cache = createCache([domains[2]]); + domainTransferLock.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('does not support transfer locks'); + done(); + }); + }); + + it('should UNKNOWN if Unable to query for domains', function (done) { + const cache = createCache([], {}, { message: 'Unable to query for domains' }); + domainTransferLock.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 domains'); + done(); + }); + }); + + + it('should not return anything if list domains response not found', function (done) { + const cache = createNullCache(); + domainTransferLock.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + }); +}); \ No newline at end of file From 0b5d57a96d39c3fd207097530a849e5f02177e8c Mon Sep 17 00:00:00 2001 From: Massimo Prencipe Date: Fri, 27 May 2022 13:38:51 +0300 Subject: [PATCH 223/350] Fix GCP policy typo --- docs/gcp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/gcp.md b/docs/gcp.md index ef972e85dc..157049e671 100644 --- a/docs/gcp.md +++ b/docs/gcp.md @@ -8,7 +8,7 @@ ``` name: roles/AquaCSPMSecurityAudit title: Aqua CSPM Security Audit - - includedPermissions: +includedPermissions: - cloudasset.assets.listResource - cloudkms.cryptoKeys.list - cloudkms.keyRings.list From ab2ee116317be9bf086b8652767a4b431e494b32 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sat, 28 May 2022 21:05:44 +0500 Subject: [PATCH 224/350] OCI Bucket Versioning Plugin --- exports.js | 1 + .../oracle/objectstore/bucketVersioning.js | 51 +++++++ .../objectstore/bucketVersioning.spec.js | 134 ++++++++++++++++++ 3 files changed, 186 insertions(+) create mode 100644 plugins/oracle/objectstore/bucketVersioning.js create mode 100644 plugins/oracle/objectstore/bucketVersioning.spec.js diff --git a/exports.js b/exports.js index c26ec760a8..bb82f749ce 100644 --- a/exports.js +++ b/exports.js @@ -865,6 +865,7 @@ module.exports = { 'preAuthRequestsExpiry' : require(__dirname + '/plugins/oracle/objectstore/preAuthRequestsExpiry.js'), 'preAuthRequestsAccess' : require(__dirname + '/plugins/oracle/objectstore/preAuthRequestsAccess.js'), 'objectPolicyProtection' : require(__dirname + '/plugins/oracle/objectstore/objectPolicyProtection.js'), + 'bucketVersioning' : require(__dirname + '/plugins/oracle/objectstore/bucketVersioning.js'), 'nfsPublicAccess' : require(__dirname + '/plugins/oracle/filestorage/nfsPublicAccess.js'), 'nfsPolicyProtection' : require(__dirname + '/plugins/oracle/filestorage/nfsPolicyProtection.js'), diff --git a/plugins/oracle/objectstore/bucketVersioning.js b/plugins/oracle/objectstore/bucketVersioning.js new file mode 100644 index 0000000000..e9cc09ee9e --- /dev/null +++ b/plugins/oracle/objectstore/bucketVersioning.js @@ -0,0 +1,51 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Bucket Versioning', + category: 'Object Store', + domain: 'Storage', + description: 'Ensures object store buckets have bucket versioning enabled.', + more_info: 'To minimize data loss in case of inadvertent or malicious deletes, make sure that all your object store buckets are configured with object versioning.', + recommended_action: 'Enable bucket versioning for all object store buckets.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Object/Tasks/usingversioning.htm', + apis: ['namespace:get','bucket:list', 'bucket:get'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.bucket, function(region, rcb) { + + if (helpers.checkRegionSubscription(cache, source, results, region)) { + + var getBucket = helpers.addSource(cache, source, + ['bucket', 'get', region]); + + if (!getBucket) return rcb(); + + if (getBucket.err || !getBucket.data) { + helpers.addResult(results, 3, + 'Unable to query for object store bucket details: ' + helpers.addError(getBucket), region); + } else if (!getBucket.data.length) { + helpers.addResult(results, 0, 'No object store bucket details to check', region); + } else { + getBucket.data.forEach(function(bucket) { + if (bucket.versioning && + bucket.versioning === 'Enabled') { + helpers.addResult(results, 0, + `Object store bucket (${bucket.name}) has versioning enabled.`, region, bucket.id); + } else { + helpers.addResult(results, 2, + `Object store bucket (${bucket.name}) does not have versioning enabled.`, region, bucket.id); + } + }); + } + } + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/objectstore/bucketVersioning.spec.js b/plugins/oracle/objectstore/bucketVersioning.spec.js new file mode 100644 index 0000000000..2501b495db --- /dev/null +++ b/plugins/oracle/objectstore/bucketVersioning.spec.js @@ -0,0 +1,134 @@ +var expect = require('chai').expect; +var plugin = require('./bucketVersioning'); + +const getBucket = [ + { + "namespace": 'idacicrnmktm', + "name": 'my-bucket', + "id": 'ocid1.bucket.oc1.iad.111111111111111122222222222222222233333333333333333', + "compartmentId": 'ocid1.tenancy.oc1..11111111111111111222222222222222222333333333333333', + "createdBy": 'ocid1.user.oc1..11111111111111112222222222222223333333333333333', + "timeCreated": '2021-04-28T13:26:51.917Z', + "versioning": 'Disabled', + }, + { + "namespace": 'idacicrnmktm', + "name": 'akhtar-bucket', + "id": 'ocid1.bucket.oc1.iad.111111111111111122222222222222222233333333333333333', + "compartmentId": 'ocid1.tenancy.oc1..11111111111111111222222222222222222333333333333333', + "createdBy": 'ocid1.user.oc1..11111111111111112222222222222223333333333333333', + "timeCreated": '2021-04-28T13:26:51.917Z', + "versioning": 'Enabled' + } +]; + +const createCache = (err, data) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + bucket: { + get: { + 'us-ashburn-1': { + err: err, + data: data + } + } + } + } +}; + +describe('bucketVersioning', function () { + describe('run', function () { + it('should give unknown result if unable to query for object store bucket details', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for object store bucket details') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['hello'], + undefined + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if no object store buckets', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No object store bucket details to check') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if bucket has versioning enabled', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('has versioning enabled') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [getBucket[1]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if bucket does not have versioning enabled', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('does not have versioning enabled') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [getBucket[0]] + ); + + plugin.run(cache, {}, callback); + }); + }); +}); \ No newline at end of file From 94e72e970cb6b9579fc42d36ae17f6abff06614c Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sat, 28 May 2022 23:34:10 +0500 Subject: [PATCH 225/350] OCI Block Volume CMK Encryption Plugin --- exports.js | 1 + .../blockstorage/blockVolumeCMKEncryption.js | 95 +++++++++ .../blockVolumeCMKEncryption.spec.js | 193 ++++++++++++++++++ 3 files changed, 289 insertions(+) create mode 100644 plugins/oracle/blockstorage/blockVolumeCMKEncryption.js create mode 100644 plugins/oracle/blockstorage/blockVolumeCMKEncryption.spec.js diff --git a/exports.js b/exports.js index 89f4d6e1c2..e65e767809 100644 --- a/exports.js +++ b/exports.js @@ -851,6 +851,7 @@ module.exports = { 'blockVolumeBackupEnabled' : require(__dirname + '/plugins/oracle/blockstorage/blockVolumeBackupEnabled.js'), 'volumeGroupsRestorable' : require(__dirname + '/plugins/oracle/blockstorage/volumeGroupsRestorable.js'), 'blockPolicyProtection' : require(__dirname + '/plugins/oracle/blockstorage/blockPolicyProtection.js'), + 'blockVolumeCMKEncryption' : require(__dirname + '/plugins/oracle/blockstorage/blockVolumeCMKEncryption.js'), 'logRetentionPeriod' : require(__dirname + '/plugins/oracle/audit/logRetentionPeriod.js'), diff --git a/plugins/oracle/blockstorage/blockVolumeCMKEncryption.js b/plugins/oracle/blockstorage/blockVolumeCMKEncryption.js new file mode 100644 index 0000000000..d0902a8b5a --- /dev/null +++ b/plugins/oracle/blockstorage/blockVolumeCMKEncryption.js @@ -0,0 +1,95 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle/'); + +module.exports = { + title: 'Block Volume CMK Encryption', + category: 'Block Storage', + domain: 'Storage', + description: 'Ensures that block volumes have encryption enabled using desired protection level.', + more_info: 'By default, block volumes are encrypted using an Oracle-managed master encryption key. To have better control over the encryption process, you can use Customer-Managed Keys (CMKs).', + recommended_action: 'Ensure all block volumes have desired encryption level.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Security/Reference/blockstorage_security.htm#data-encryption', + apis: ['vault:list', 'keys:list', 'volume:list'], + settings: { + volume_encryption_level: { + name: 'Block Volume Encryption Level', + description: 'Desired protection level for block volumes. default: oracle-managed, cloudcmek: customer managed encryption keys, ' + + 'cloudhsm: customer managed HSM encryption key, external: imported or externally managed key', + regex: '^(default|cloudcmek|cloudhsm)$', + default: 'cloudcmek' + } + }, + + run: function (cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + var keysObj = {}; + + let desiredEncryptionLevelStr = settings.volume_encryption_level || this.settings.volume_encryption_level.default; + var desiredEncryptionLevel = helpers.PROTECTION_LEVELS.indexOf(desiredEncryptionLevelStr); + + async.series([ + function (cb) { + async.each(regions.keys, function (region, rcb) { + let keys = helpers.addSource( + cache, source, ['keys', 'list', region]); + if (keys && keys.data && keys.data.length) helpers.listToObj(keysObj, keys.data, 'id'); + rcb(); + }, function () { + cb(); + }); + }, + function (cb) { + async.each(regions.volume, function (region, rcb) { + + if (helpers.checkRegionSubscription(cache, source, results, region)) { + + var blockVolumes = helpers.addSource(cache, source, + ['volume', 'list', region]); + + if (!blockVolumes) return rcb(); + + if (blockVolumes.err || !blockVolumes.data) { + helpers.addResult(results, 3, + 'Unable to query for block volumes: ' + helpers.addError(blockVolumes), region); + return rcb(); + } + + if (!blockVolumes.data.length) { + helpers.addResult(results, 0, 'No block volumes found', region); + return rcb(); + } + + blockVolumes.data.forEach(blockVolume => { + if (blockVolume.lifecycleState && blockVolume.lifecycleState === 'TERMINATED') return; + + let currentEncryptionLevel = 1; //default + + if (blockVolume.kmsKeyId) { + currentEncryptionLevel = helpers.getProtectionLevel(keysObj[blockVolume.kmsKeyId], helpers.PROTECTION_LEVELS); + } + + let currentEncryptionLevelStr = helpers.PROTECTION_LEVELS[currentEncryptionLevel]; + + if (currentEncryptionLevel >= desiredEncryptionLevel) { + helpers.addResult(results, 0, + `Block volume (${blockVolume.displayName}) has encryption level ${currentEncryptionLevelStr} which is greater than or equal to ${desiredEncryptionLevelStr}`, region, blockVolume.id); + } else { + helpers.addResult(results, 2, + `Block volume (${blockVolume.displayName}) has encryption level ${currentEncryptionLevelStr} which is less than ${desiredEncryptionLevelStr}`, region, blockVolume.id); + } + }); + } + + rcb(); + }, function () { + cb(); + }); + } + ], function () { + // Global checking goes here + callback(null, results, source); + }); + } +} \ No newline at end of file diff --git a/plugins/oracle/blockstorage/blockVolumeCMKEncryption.spec.js b/plugins/oracle/blockstorage/blockVolumeCMKEncryption.spec.js new file mode 100644 index 0000000000..8e72ab95ac --- /dev/null +++ b/plugins/oracle/blockstorage/blockVolumeCMKEncryption.spec.js @@ -0,0 +1,193 @@ +var expect = require('chai').expect; +var plugin = require('./blockVolumeCMKEncryption'); + +const blockVolumes = [ + { + "availabilityDomain": "fMgC:US-ASHBURN-AD-1", + "compartmentId": "ocid1.tenancy.oc1..aaaaaaaa111111", + "definedTags": {}, + "displayName": "vol-1", + "freeformTags": {}, + "systemTags": {}, + "id": "ocid1.volume.oc1.aaa.1111111", + "isHydrated": true, + "lifecycleState": "AVAILABLE", + "performanceTier": null, + "vpusPerGB": null, + "sizeInGBs": 1024, + "sizeInMBs": 1048576, + "sourceDetails": null, + "timeCreated": "2019-08-29T21:46:01.836Z", + "volumeGroupId": null, + + }, + { + "availabilityDomain": "fMgC:US-ASHBURN-AD-1", + "compartmentId": "ocid1.tenancy.oc1..aaaaaaaa111111", + "definedTags": {}, + "displayName": "vol-1", + "freeformTags": {}, + "systemTags": {}, + "id": "ocid1.volume.oc1.aaa.1111111", + "isHydrated": true, + "lifecycleState": "AVAILABLE", + "performanceTier": null, + "vpusPerGB": null, + "sizeInGBs": 1024, + "sizeInMBs": 1048576, + "sourceDetails": null, + "timeCreated": "2019-08-29T21:46:01.836Z", + "volumeGroupId": null, + "kmsKeyId": 'key-1' + + } + +]; + +const createCache = (err, data) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + volume: { + list: { + 'us-ashburn-1': { + err: err, + data: data + } + } + }, + vault: { + list: { + 'us-ashburn-1': { + data: [ + { + "compartmentId": "compartment-1", + "displayName": "vault-1", + "freeformTags": {}, + "id": "vault-1", + "lifecycleState": "ACTIVE", + }, + ] + } + } + }, + keys: { + list: { + 'us-ashburn-1': { + data: [ + { + "compartmentId": "compartment-1", + "definedTags": {}, + "displayName": "key-1", + "freeformTags": {}, + "id": "key-1", + "lifecycleState": "ENABLED", + "timeCreated": "2022-04-30T19:49:12.841Z", + "vaultId": "vault-1", + "protectionMode": "SOFTWARE", + "algorithm": "AES" + } + ], + + } + } + } + } +}; + +describe('blockVolumeCMKEncryption', function () { + describe('run', function () { + it('should give unknown result if a block volume error occurs', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for block volumes') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['error'], + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if no block volumes are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No block volumes found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + + it('should give failing result if block volume does not have desired encryption level', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('which is less') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [blockVolumes[0]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if block volume has desired encryption level', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('which is greater than or equal to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [blockVolumes[1]] + ); + + plugin.run(cache, {}, callback); + }); + }); +}); \ No newline at end of file From a33a588e40397d1efe76a6f3fa20244f846c8e12 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sun, 29 May 2022 00:06:19 +0500 Subject: [PATCH 226/350] OCI Boot Volume CMK Encryption Plugin --- exports.js | 1 + .../oracle/compute/bootVolumeCMKEncryption.js | 95 +++++++++ .../compute/bootVolumeCMKEncryption.spec.js | 189 ++++++++++++++++++ 3 files changed, 285 insertions(+) create mode 100644 plugins/oracle/compute/bootVolumeCMKEncryption.js create mode 100644 plugins/oracle/compute/bootVolumeCMKEncryption.spec.js diff --git a/exports.js b/exports.js index 89f4d6e1c2..9cae20eeb8 100644 --- a/exports.js +++ b/exports.js @@ -782,6 +782,7 @@ module.exports = { 'bootVolumeRestorable' : require(__dirname + '/plugins/oracle/compute/bootVolumeRestorable.js'), 'bootVolumeBackupEnabled' : require(__dirname + '/plugins/oracle/compute/bootVolumeBackupEnabled.js'), 'instancePolicyProtection' : require(__dirname + '/plugins/oracle/compute/instancePolicyProtection.js'), + 'bootVolumeCMKEncryption' : require(__dirname + '/plugins/oracle/compute/bootVolumeCMKEncryption.js'), 'usersMfaEnabled' : require(__dirname + '/plugins/oracle/identity/usersMfaEnabled.js'), 'passwordRequiresLowercase' : require(__dirname + '/plugins/oracle/identity/passwordRequiresLowercase.js'), diff --git a/plugins/oracle/compute/bootVolumeCMKEncryption.js b/plugins/oracle/compute/bootVolumeCMKEncryption.js new file mode 100644 index 0000000000..9c15b24e35 --- /dev/null +++ b/plugins/oracle/compute/bootVolumeCMKEncryption.js @@ -0,0 +1,95 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle/'); + +module.exports = { + title: 'Boot Volume CMK Encryption', + category: 'Block Storage', + domain: 'Storage', + description: 'Ensures that boot volumes have encryption enabled using desired protection level.', + more_info: 'By default, boot volumes are encrypted using an Oracle-managed master encryption key. To have better control over the encryption process, you can use Customer-Managed Keys (CMKs).', + recommended_action: 'Ensure all boot volumes have desired encryption level.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Security/Reference/blockstorage_security.htm#data-encryption', + apis: ['vault:list', 'keys:list', 'bootVolume:list'], + settings: { + volume_encryption_level: { + name: 'Boot Volume Encryption Level', + description: 'Desired protection level for boot volumes. default: oracle-managed, cloudcmek: customer managed encryption keys, ' + + 'cloudhsm: customer managed HSM encryption key, external: imported or externally managed key', + regex: '^(default|cloudcmek|cloudhsm)$', + default: 'cloudcmek' + } + }, + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + var keysObj = {}; + + let desiredEncryptionLevelStr = settings.volume_encryption_level || this.settings.volume_encryption_level.default; + var desiredEncryptionLevel = helpers.PROTECTION_LEVELS.indexOf(desiredEncryptionLevelStr); + + async.series([ + function(cb) { + async.each(regions.keys, function(region, rcb) { + let keys = helpers.addSource( + cache, source, ['keys', 'list', region]); + if (keys && keys.data && keys.data.length) helpers.listToObj(keysObj, keys.data, 'id'); + rcb(); + }, function() { + cb(); + }); + }, + function(cb) { + async.each(regions.bootVolume, function(region, rcb) { + + if (helpers.checkRegionSubscription(cache, source, results, region)) { + + var bootVolumes = helpers.addSource(cache, source, + ['bootVolume', 'list', region]); + + if (!bootVolumes) return rcb(); + + if (bootVolumes.err || !bootVolumes.data) { + helpers.addResult(results, 3, + 'Unable to query for boot volumes: ' + helpers.addError(bootVolumes), region); + return rcb(); + } + + if (!bootVolumes.data.length) { + helpers.addResult(results, 0, 'No boot volumes found', region); + return rcb(); + } + + bootVolumes.data.forEach(bootVolume => { + if (bootVolume.lifecycleState && bootVolume.lifecycleState === 'TERMINATED') return; + + let currentEncryptionLevel = 1; //default + + if (bootVolume.kmsKeyId) { + currentEncryptionLevel = helpers.getProtectionLevel(keysObj[bootVolume.kmsKeyId], helpers.PROTECTION_LEVELS); + } + + let currentEncryptionLevelStr = helpers.PROTECTION_LEVELS[currentEncryptionLevel]; + + if (currentEncryptionLevel >= desiredEncryptionLevel) { + helpers.addResult(results, 0, + `Boot volume (${bootVolume.displayName}) has encryption level ${currentEncryptionLevelStr} which is greater than or equal to ${desiredEncryptionLevelStr}`, region, bootVolume.id); + } else { + helpers.addResult(results, 2, + `Boot volume (${bootVolume.displayName}) has encryption level ${currentEncryptionLevelStr} which is less than ${desiredEncryptionLevelStr}`, region, bootVolume.id); + } + }); + } + + rcb(); + }, function() { + cb(); + }); + } + ], function() { + // Global checking goes here + callback(null, results, source); + }); + } +}; diff --git a/plugins/oracle/compute/bootVolumeCMKEncryption.spec.js b/plugins/oracle/compute/bootVolumeCMKEncryption.spec.js new file mode 100644 index 0000000000..bbb13e9521 --- /dev/null +++ b/plugins/oracle/compute/bootVolumeCMKEncryption.spec.js @@ -0,0 +1,189 @@ +var expect = require('chai').expect; +var plugin = require('./bootVolumeCMKEncryption'); + +const bootVolumes = [ + { + "compartmentId": "ocid1.tenancy.oc1.aaaaaa.111111", + "definedTags": {}, + "displayName": "vol-2", + "freeformTags": {}, + "systemTags": {}, + "id": "ocid1.volume.oc1.aaaaaa.1111111", + "isHydrated": true, + "kmsKeyId": null, + "lifecycleState": "AVAILABLE", + "performanceTier": null, + "vpusPerGB": null, + "sizeInGBs": 1024, + "sizeInMBs": 1048576, + "sourceDetails": null, + "timeCreated": "2019-08-29T21:46:01.836Z", + "volumeGroupId": null + }, + { + "compartmentId": "ocid1.tenancy.oc1.aaaaaa.111111", + "definedTags": {}, + "displayName": "vol-2", + "freeformTags": {}, + "systemTags": {}, + "id": "ocid1.volume.oc1.aaaaaa.1111111", + "isHydrated": true, + "lifecycleState": "AVAILABLE", + "performanceTier": null, + "vpusPerGB": null, + "sizeInGBs": 1024, + "sizeInMBs": 1048576, + "sourceDetails": null, + "timeCreated": "2019-08-29T21:46:01.836Z", + "volumeGroupId": null, + "kmsKeyId": 'key-1' + } +]; + +const createCache = (err, data) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + bootVolume: { + list: { + 'us-ashburn-1': { + err: err, + data: data + } + } + }, + vault: { + list: { + 'us-ashburn-1': { + data: [ + { + "compartmentId": "compartment-1", + "displayName": "vault-1", + "freeformTags": {}, + "id": "vault-1", + "lifecycleState": "ACTIVE", + }, + ] + } + } + }, + keys: { + list: { + 'us-ashburn-1': { + data: [ + { + "compartmentId": "compartment-1", + "definedTags": {}, + "displayName": "key-1", + "freeformTags": {}, + "id": "key-1", + "lifecycleState": "ENABLED", + "timeCreated": "2022-04-30T19:49:12.841Z", + "vaultId": "vault-1", + "protectionMode": "SOFTWARE", + "algorithm": "AES" + } + ], + + } + } + } + } +}; + +describe('bootVolumeCMKEncryption', function () { + describe('run', function () { + it('should give unknown result if a boot volume error occurs', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for boot volumes') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['error'], + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if no boot volumes are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No boot volumes found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + + it('should give failing result if boot volume does not have desired encryption level', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('which is less') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [bootVolumes[0]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if boot volume has desired encryption level', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('which is greater than or equal to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [bootVolumes[1]] + ); + + plugin.run(cache, {}, callback); + }); + }); +}); \ No newline at end of file From 0c23c366483f34ac71ebe108c9833e88ae9cbe3c Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Mon, 30 May 2022 02:40:12 +0500 Subject: [PATCH 227/350] OCI File System CMK Encryption Plugin --- collectors/oracle/collector.js | 8 + exports.js | 1 + helpers/oracle/regions.js | 1 + other_modules/oci/services.json | 10 ++ .../filestorage/fileSystemsCMKEncryption.js | 93 ++++++++++ .../fileSystemsCMKEncryption.spec.js | 169 ++++++++++++++++++ 6 files changed, 282 insertions(+) create mode 100644 plugins/oracle/filestorage/fileSystemsCMKEncryption.js create mode 100644 plugins/oracle/filestorage/fileSystemsCMKEncryption.spec.js diff --git a/collectors/oracle/collector.js b/collectors/oracle/collector.js index 7160ae0f6f..1574b2f32b 100644 --- a/collectors/oracle/collector.js +++ b/collectors/oracle/collector.js @@ -114,6 +114,14 @@ var calls = { restVersion: '/20171215', } }, + fileSystem: { + list: { + api: 'fileStorage', + filterKey: ['compartmentId'], + filterValue: ['compartmentId'], + restVersion: '/20171215', + } + }, mountTarget: { list: { api: 'fileStorage', diff --git a/exports.js b/exports.js index fd6836f08b..c9c126cce3 100644 --- a/exports.js +++ b/exports.js @@ -868,6 +868,7 @@ module.exports = { 'nfsPublicAccess' : require(__dirname + '/plugins/oracle/filestorage/nfsPublicAccess.js'), 'nfsPolicyProtection' : require(__dirname + '/plugins/oracle/filestorage/nfsPolicyProtection.js'), + 'fileSystemsCMKEncryption' : require(__dirname + '/plugins/oracle/filestorage/fileSystemsCMKEncryption.js'), 'dbBackupEnabled' : require(__dirname + '/plugins/oracle/database/dbBackupEnabled.js'), 'dbPrivateSubnetOnly' : require(__dirname + '/plugins/oracle/database/dbPrivateSubnetOnly.js'), diff --git a/helpers/oracle/regions.js b/helpers/oracle/regions.js index 2b9c9f0978..28549f82db 100644 --- a/helpers/oracle/regions.js +++ b/helpers/oracle/regions.js @@ -47,6 +47,7 @@ module.exports = { authenticationPolicy: regions, exprt: regions, exportSummary: regions, + fileSystem: regions, compartment: regions, bucket: regions, waasPolicy: regions, diff --git a/other_modules/oci/services.json b/other_modules/oci/services.json index 0091a31ba2..28952afd45 100644 --- a/other_modules/oci/services.json +++ b/other_modules/oci/services.json @@ -291,6 +291,16 @@ "endpoint": "filestorage.{{region}}.oraclecloud.com" } }, + "fileSystem": { + "list": { + "allowedQueryStrings": [ + "opc-request-id", "displayName", "availabilityDomain", "exportSetId", "id", "compartmentId", "limit", "page", "sortBy", "sortOrder", "lifecycleState" + ], + "method": "GET", + "path": "fileSystems", + "endpoint": "filestorage.{{region}}.oraclecloud.com" + } + }, "mountTarget": { "list": { "allowedQueryStrings": [ diff --git a/plugins/oracle/filestorage/fileSystemsCMKEncryption.js b/plugins/oracle/filestorage/fileSystemsCMKEncryption.js new file mode 100644 index 0000000000..19606ad342 --- /dev/null +++ b/plugins/oracle/filestorage/fileSystemsCMKEncryption.js @@ -0,0 +1,93 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'File Systems CMK Encryption', + category: 'File Storage', + domain: 'Storage', + description: 'Ensures that OCI File Storage file systems have encryption enabled using desired protection level.', + more_info: 'By default, OCI File Storage file systems are encrypted using an Oracle-managed master encryption key. To have better control over the encryption process, you can use Customer-Managed Keys (CMKs).', + recommended_action: 'Ensure all file systems have desired encryption level.', + link: 'https://docs.oracle.com/en-us/iaas/Content/File/Concepts/filestorageoverview.htm#encryption', + apis: ['vault:list', 'keys:list', 'fileSystem:list'], + settings: { + file_system_encryption_level: { + name: 'File System Encryption Level', + description: 'Desired protection level for File Storage file systems. default: oracle-managed, cloudcmek: customer managed encryption keys, ' + + 'cloudhsm: customer managed HSM encryption key, external: imported or externally managed key', + regex: '^(default|cloudcmek|cloudhsm)$', + default: 'cloudcmek' + } + }, + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + var keysObj = {}; + + let desiredEncryptionLevelStr = settings.file_system_encryption_level || this.settings.file_system_encryption_level.default; + var desiredEncryptionLevel = helpers.PROTECTION_LEVELS.indexOf(desiredEncryptionLevelStr); + + async.series([ + function(cb) { + async.each(regions.keys, function(region, rcb) { + let keys = helpers.addSource( + cache, source, ['keys', 'list', region]); + if (keys && keys.data && keys.data.length) helpers.listToObj(keysObj, keys.data, 'id'); + rcb(); + }, function() { + cb(); + }); + }, + function(cb) { + async.each(regions.fileSystem, function(region, rcb) { + + if (helpers.checkRegionSubscription(cache, source, results, region)) { + + var fileSystems = helpers.addSource(cache, source, + ['fileSystem', 'list', region]); + + if (!fileSystems) return rcb(); + + if (fileSystems.err || !fileSystems.data) { + helpers.addResult(results, 3, + 'Unable to query for file systems: ' + helpers.addError(fileSystems), region); + return rcb(); + } + + if (!fileSystems.data.length) { + helpers.addResult(results, 0, 'No file systems found', region); + return rcb(); + } + + fileSystems.data.forEach(fileSystem => { + let currentEncryptionLevel = 1; //default + + if (fileSystem.kmsKeyId) { + currentEncryptionLevel = helpers.getProtectionLevel(keysObj[fileSystem.kmsKeyId], helpers.PROTECTION_LEVELS); + } + + let currentEncryptionLevelStr = helpers.PROTECTION_LEVELS[currentEncryptionLevel]; + + if (currentEncryptionLevel >= desiredEncryptionLevel) { + helpers.addResult(results, 0, + `File System (${fileSystem.displayName}) has encryption level ${currentEncryptionLevelStr} which is greater than or equal to ${desiredEncryptionLevelStr}`, region, fileSystem.id); + } else { + helpers.addResult(results, 2, + `File System (${fileSystem.displayName}) has encryption level ${currentEncryptionLevelStr} which is less than ${desiredEncryptionLevelStr}`, region, fileSystem.id); + } + }); + } + + rcb(); + }, function() { + cb(); + }); + } + ], function() { + // Global checking goes here + callback(null, results, source); + }); + } +}; diff --git a/plugins/oracle/filestorage/fileSystemsCMKEncryption.spec.js b/plugins/oracle/filestorage/fileSystemsCMKEncryption.spec.js new file mode 100644 index 0000000000..434b00d712 --- /dev/null +++ b/plugins/oracle/filestorage/fileSystemsCMKEncryption.spec.js @@ -0,0 +1,169 @@ +var expect = require('chai').expect; +var plugin = require('./fileSystemsCMKEncryption'); + +const fileSystems = [ + { + "compartmentId": 'ocid1.tenancy.oc1.aaaaa.111111', + "displayName": 'FileSystem1', + "id": 'ocid1.filesystem.oc1.iad.1111', + "lifecycleState": 'ACTIVE', + "timeCreated": '2022-05-29T21:12:16.928Z', + "kmsKeyId": '', + }, + { + "compartmentId": 'ocid1.tenancy.oc1.aaaaa.111111', + "displayName": 'FileSystem1', + "id": 'ocid1.filesystem.oc1.iad.1111', + "lifecycleState": 'ACTIVE', + "timeCreated": '2022-05-29T21:12:16.928Z', + "kmsKeyId": 'key-1', + }, +]; + +const createCache = (err, data) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + fileSystem: { + list: { + 'us-ashburn-1': { + err: err, + data: data + } + } + }, + vault: { + list: { + 'us-ashburn-1': { + data: [ + { + "compartmentId": "compartment-1", + "displayName": "vault-1", + "freeformTags": {}, + "id": "vault-1", + "lifecycleState": "ACTIVE", + }, + ] + } + } + }, + keys: { + list: { + 'us-ashburn-1': { + data: [ + { + "compartmentId": "compartment-1", + "definedTags": {}, + "displayName": "key-1", + "freeformTags": {}, + "id": "key-1", + "lifecycleState": "ENABLED", + "timeCreated": "2022-04-30T19:49:12.841Z", + "vaultId": "vault-1", + "protectionMode": "SOFTWARE", + "algorithm": "AES" + } + ], + + } + } + } + } +}; + +describe('fileSystemsCMKEncryption', function () { + describe('run', function () { + it('should give unknown result if a file system error occurs', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for file systems') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['error'], + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if no file systems are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No file systems found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + + it('should give failing result if file system does not have desired encryption level', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('which is less') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [fileSystems[0]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if file system has desired encryption level', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('which is greater than or equal to') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [fileSystems[1]] + ); + + plugin.run(cache, {}, callback); + }); + }); +}); \ No newline at end of file From a9c06e3ee1d5e188c941db66a6c831800f1743db Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Mon, 30 May 2022 14:56:12 +0500 Subject: [PATCH 228/350] Added all whitelisted services --- plugins/aws/iam/checkAllUsedServices.js | 121 +++++++++++++++++++++--- 1 file changed, 108 insertions(+), 13 deletions(-) diff --git a/plugins/aws/iam/checkAllUsedServices.js b/plugins/aws/iam/checkAllUsedServices.js index 5f0572d784..dae229676f 100644 --- a/plugins/aws/iam/checkAllUsedServices.js +++ b/plugins/aws/iam/checkAllUsedServices.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/aws'); var managedAdminPolicy = 'arn:aws:iam::aws:policy/AdministratorAccess'; module.exports = { - title: 'Check All Used Services', + title: 'IAM Role Policy Unused Services', category: 'IAM', domain: 'Identity and Access management', description: 'Ensure that IAM role policies are scoped properly as to not provide access to unused AWS services.', @@ -89,6 +89,57 @@ module.exports = { var iamRegion = helpers.defaultRegion(settings); var allResources = []; + const allServices = { + apigateway: ['stage', 'restapi', 'api'], + cloudfront: ['distribution', 'streamingdistribution'], + cloudwatch: ['Alarm'], + dynamodb: ['table'], + ec2: ['volume', 'host', 'eip', 'instance', 'networkinterface', 'securitygroup', 'natgateway', 'egressonlyinternetgateway', + 'flowlog', 'transitgateway', 'vpcendpoint', 'vpcendpointservice', 'vpcpeeringconnection', 'registeredhainstance', 'launchtemplate', + 'customergateway', 'internetgateway', 'networkacl', 'routetable', 'subnet', 'vpc', 'vpcconnection', 'vpngateway'], + ecr: ['repository', 'publicrepository'], + ecs: ['cluster', 'taskdefinition', 'service'], + efs: ['filesystem', 'accesspoint'], + eks: ['cluster'], + emr: ['securityconfiguration'], + guardduty: ['detector'], + elasticsearch: ['domain'], + opensearch: ['domain'], + qldb: ['ledger'], + kinesis: ['stream', 'streamconsumer'], + redshift: ['cluster', 'clusterparametergroup', 'clustersecuritygroup', 'clustersnapshot', 'clustersubnetgroup', 'eventsubscription'], + rds: ['dbinstance', 'dbsecuritygroup', 'dbsnapshot', 'dbsubnetgroup', 'eventsubscription', 'dbcluster', 'dbclustersnapshot'], + sagemaker: ['coderepository', 'model'], + sns: ['topic'], + sqs: ['queue'], + s3: ['buckets', 'accountpublicaccessblock'], + autoscaling: ['autoscalinggroup', 'launchconfguration', 'scalingpolicy', 'scheduledaction'], + backup: ['backupplan', 'backupselection', 'backupvault', 'recoverypoint'], + acm: ['certificate'], + cloudformation: ['stack'], + cloudtrail: ['trail'], + codebuild: ['project'], + codedeploy: ['application', 'deploymentconfig', 'deploymentgroup'], + codepipeline: ['pipeline'], + config: ['resourcecompliance', 'conformancepackcompliance'], + elasticbeanstalk: ['applicstion', 'applicationversion', 'environment'], + iam: ['user', 'group', 'role', 'policy'], + kms: ['key'], + lambda: ['function'], + networkfirewall: ['firewall', 'firewallpolicy', 'rulegroup'], + secretsmanager: ['secret'], + servicecatalog: ['cloudFormationproduct', 'cloudformationprovisionedproduct', 'portfolio'], + shield: ['protection', 'protection'], + stepfunctions: ['statemachine'], + ssm: ['managedinstanceinventory', 'patchcompliance', 'associationcompliance', 'filedata'], + waf: ['ratebasedrule', 'rule', 'webacl', 'rulegroup', 'ratebasedrule', 'rule', 'webacl'], + wafv2: ['webacl', 'rulegroup', 'managedruleset', 'ipset'], + xray: ['encryptionconfig'], + elasticloadbalancing: ['loadbalancer'], + elasticloadbalancingv2: ['loadbalancer'] + }; + + const customServices = ['s3', 'codepipeline']; async.each(regions.configservice, function(region, rcb) { var configSRecorderStatus = helpers.addSource(cache, source, @@ -144,11 +195,12 @@ module.exports = { allResources = allResources.reduce((result, resource) => { let arr = resource.resourceType.split(':'); - let key = arr[2].toLowerCase(); - result[key] = result[key] || []; + let service = arr[2].toLowerCase(); + let subService = arr[4].toLowerCase(); + result[service] = result[service] || []; - if (resource.count > 0) { - result[key].push(arr[4]); + if (resource.count > 0 && (allServices[service] && allServices[service].includes(subService))) { + result[service].push(subService); } return result; @@ -250,9 +302,27 @@ module.exports = { let service = statements.find((doc) => doc.Resource[0].includes('arn:')); if (service) { - let serviceName = service.Resource[0].split(':')[2]; - if (!(serviceName in allResources)) { - if (policyFailures.indexOf(serviceName) === -1) policyFailures.push(serviceName); + let arr = service.Resource[0].split(':'); + let serviceName = arr[2]; + let subService = arr[5]; + let subServiceName; + + if (subService.indexOf('/') < 0) { + subServiceName = subService; + } else { + let indexOfSlash = subService.indexOf('/'); + let subServicelength = subService.length; + subServiceName = indexOfSlash < 2 ? subService.substring(indexOfSlash + 1, subServicelength) : subService.substring(0, indexOfSlash); + } + + subServiceName = subServiceName.replace(/\/|[*_-]/g, ''); + + if (!(serviceName in allResources) || !allResources[serviceName].includes(subServiceName)) { + if (!(serviceName in allResources) && customServices.includes(serviceName)) { + if (policyFailures.indexOf(serviceName) === -1) policyFailures.push(serviceName); + } else { + if (policyFailures.indexOf(`${serviceName}:${subServiceName}`) === -1) policyFailures.push(`${serviceName}:${subServiceName}`); + } } } @@ -278,12 +348,37 @@ module.exports = { if (!statements) break; for (let statement of statements) { - let services = [... new Set(statement.Action.map((action) => action.split(':')[0].toLowerCase()))]; - services.forEach((service) => { - if (!(service in allResources)) { - if (policyFailures.indexOf(service) === -1) policyFailures.push(service); + if (statement.Resource.indexOf('*') > -1) { + let services = [... new Set(statement.Action.map((action) => action.split(':')[0].toLowerCase()))]; + services.forEach((service) => { + if (!(service in allResources)) { + if (policyFailures.indexOf(service) === -1) policyFailures.push(service); + } + }); + } else { + let arr = statement.Resource[0].split(':'); + let serviceName = arr[2]; + let subService = arr[5]; + let subServiceName; + + if (subService.indexOf('/') < 0) { + subServiceName = subService; + } else { + let indexOfSlash = subService.indexOf('/'); + let subServicelength = subService.length; + subServiceName = indexOfSlash < 2 ? subService.substring(indexOfSlash + 1, subServicelength) : subService.substring(0, indexOfSlash); } - }); + + subServiceName = subServiceName.replace(/\/|[*_-]/g, ''); + + if (!(serviceName in allResources) || !allResources[serviceName].includes(subServiceName)) { + if (!(serviceName in allResources) && customServices.includes(serviceName)) { + if (policyFailures.indexOf(serviceName) === -1) policyFailures.push(serviceName); + } else { + if (policyFailures.indexOf(`${serviceName}:${subServiceName}`) === -1) policyFailures.push(`${serviceName}:${subServiceName}`); + } + } + } } addRoleFailures(roleFailures, statements, 'inline', config.ignore_service_specific_wildcards); From 0215b87165aaaecf97c747a45fb6d494fd3fb7c7 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 30 May 2022 19:34:01 +0500 Subject: [PATCH 229/350] Insecure EC2 Metadata Options Fault Removed --- plugins/aws/ec2/ec2MetadataOptions.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/plugins/aws/ec2/ec2MetadataOptions.js b/plugins/aws/ec2/ec2MetadataOptions.js index f4eb626ae5..a832506adb 100644 --- a/plugins/aws/ec2/ec2MetadataOptions.js +++ b/plugins/aws/ec2/ec2MetadataOptions.js @@ -62,7 +62,7 @@ module.exports = { if (!totalCount) { helpers.addResult(results, 0, 'No instances found', region); - } else if (totalCount <= 20) { + } else { // Add individual results for (var iArn of instancesEndpointDisabled) { helpers.addResult(results, 0, 'Instance has instance metadata endpoint disabled', region, iArn); @@ -75,11 +75,7 @@ module.exports = { for (var kArn of instancesInsecure) { helpers.addResult(results, 2, 'Instance has instance metadata endpoint enabled and does not require HttpTokens', region, kArn); } - } else if (instancesInsecure.length) { - helpers.addResult(results, 2, message, region); - } else { - helpers.addResult(results, 0, message, region); - } + } return rcb(); }, function(){ From b62e2c485256e2383700bdd86a48af96fe9a2f43 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 30 May 2022 19:43:40 +0500 Subject: [PATCH 230/350] Added some changes --- plugins/aws/ec2/ec2MetadataOptions.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/aws/ec2/ec2MetadataOptions.js b/plugins/aws/ec2/ec2MetadataOptions.js index a832506adb..0dc3e84939 100644 --- a/plugins/aws/ec2/ec2MetadataOptions.js +++ b/plugins/aws/ec2/ec2MetadataOptions.js @@ -54,10 +54,6 @@ module.exports = { } } - var message = 'Instances using insecure V1 endpoint: ' + instancesInsecure.length + '; ' + - 'instances using secure V2 endpoint: ' + instancesTokensRequired.length + '; ' + - 'instances with disabled endpoints: ' + instancesEndpointDisabled.length; - var totalCount = instancesInsecure.length + instancesTokensRequired.length + instancesEndpointDisabled.length; if (!totalCount) { From bc527cf273889639a845af7023c327085e68cf35 Mon Sep 17 00:00:00 2001 From: M-Akhtar Date: Mon, 30 May 2022 20:00:46 +0500 Subject: [PATCH 231/350] Modified core logic --- plugins/aws/iam/checkAllUsedServices.js | 144 +++++++++++++++--------- 1 file changed, 92 insertions(+), 52 deletions(-) diff --git a/plugins/aws/iam/checkAllUsedServices.js b/plugins/aws/iam/checkAllUsedServices.js index dae229676f..25c9ada660 100644 --- a/plugins/aws/iam/checkAllUsedServices.js +++ b/plugins/aws/iam/checkAllUsedServices.js @@ -112,7 +112,7 @@ module.exports = { sagemaker: ['coderepository', 'model'], sns: ['topic'], sqs: ['queue'], - s3: ['buckets', 'accountpublicaccessblock'], + s3: ['bucket', 'accountpublicaccessblock'], autoscaling: ['autoscalinggroup', 'launchconfguration', 'scalingpolicy', 'scheduledaction'], backup: ['backupplan', 'backupselection', 'backupvault', 'recoverypoint'], acm: ['certificate'], @@ -222,6 +222,8 @@ module.exports = { return callback(null, results, source); } + console.log(JSON.stringify(allResources, null, 2)); + async.each(listRoles.data, function(role, cb){ if (!role.RoleName) return cb(); @@ -300,31 +302,50 @@ module.exports = { if (!statements) break; - let service = statements.find((doc) => doc.Resource[0].includes('arn:')); - if (service) { - let arr = service.Resource[0].split(':'); - let serviceName = arr[2]; - let subService = arr[5]; - let subServiceName; - - if (subService.indexOf('/') < 0) { - subServiceName = subService; - } else { - let indexOfSlash = subService.indexOf('/'); - let subServicelength = subService.length; - subServiceName = indexOfSlash < 2 ? subService.substring(indexOfSlash + 1, subServicelength) : subService.substring(0, indexOfSlash); - } - - subServiceName = subServiceName.replace(/\/|[*_-]/g, ''); - - if (!(serviceName in allResources) || !allResources[serviceName].includes(subServiceName)) { - if (!(serviceName in allResources) && customServices.includes(serviceName)) { - if (policyFailures.indexOf(serviceName) === -1) policyFailures.push(serviceName); - } else { - if (policyFailures.indexOf(`${serviceName}:${subServiceName}`) === -1) policyFailures.push(`${serviceName}:${subServiceName}`); + for (let statement of statements) { + if (statement.Action && statement.Action.length) { + for (let action of statement.Action) { + // console.log(action); + let service = action.split(':')[0].toLowerCase(); + let resuourceAction = action.split(':')[1].toLowerCase(); + + if (allServices[service]) { + for (let supportedResource of allServices[service]) { + if (resuourceAction.includes(supportedResource)) { + if (!allResources[service] || !allResources[service].includes(supportedResource)) { + if (policyFailures.indexOf(action) === -1) policyFailures.push(action); + } + } + } + } } } } + // let service = statements.find((doc) => doc.Resource[0].includes('arn:')); + // if (service) { + // let arr = service.Resource[0].split(':'); + // let serviceName = arr[2]; + // let subService = arr[5]; + // let subServiceName; + + // if (subService.indexOf('/') < 0) { + // subServiceName = subService; + // } else { + // let indexOfSlash = subService.indexOf('/'); + // let subServicelength = subService.length; + // subServiceName = indexOfSlash < 2 ? subService.substring(indexOfSlash + 1, subServicelength) : subService.substring(0, indexOfSlash); + // } + + // subServiceName = subServiceName.replace(/\/|[*_-]/g, ''); + + // if (!(serviceName in allResources) || !allResources[serviceName].includes(subServiceName)) { + // if (!(serviceName in allResources) && customServices.includes(serviceName)) { + // if (policyFailures.indexOf(serviceName) === -1) policyFailures.push(serviceName); + // } else { + // if (policyFailures.indexOf(`${serviceName}:${subServiceName}`) === -1) policyFailures.push(`${serviceName}:${subServiceName}`); + // } + // } + // } addRoleFailures(roleFailures, statements, 'managed', config.ignore_service_specific_wildcards); } @@ -348,38 +369,57 @@ module.exports = { if (!statements) break; for (let statement of statements) { - if (statement.Resource.indexOf('*') > -1) { - let services = [... new Set(statement.Action.map((action) => action.split(':')[0].toLowerCase()))]; - services.forEach((service) => { - if (!(service in allResources)) { - if (policyFailures.indexOf(service) === -1) policyFailures.push(service); - } - }); - } else { - let arr = statement.Resource[0].split(':'); - let serviceName = arr[2]; - let subService = arr[5]; - let subServiceName; - - if (subService.indexOf('/') < 0) { - subServiceName = subService; - } else { - let indexOfSlash = subService.indexOf('/'); - let subServicelength = subService.length; - subServiceName = indexOfSlash < 2 ? subService.substring(indexOfSlash + 1, subServicelength) : subService.substring(0, indexOfSlash); - } - - subServiceName = subServiceName.replace(/\/|[*_-]/g, ''); - - if (!(serviceName in allResources) || !allResources[serviceName].includes(subServiceName)) { - if (!(serviceName in allResources) && customServices.includes(serviceName)) { - if (policyFailures.indexOf(serviceName) === -1) policyFailures.push(serviceName); - } else { - if (policyFailures.indexOf(`${serviceName}:${subServiceName}`) === -1) policyFailures.push(`${serviceName}:${subServiceName}`); + if (statement.Action && statement.Action.length) { + for (let action of statement.Action) { + // console.log(action); + let service = action.split(':')[0].toLowerCase(); + let resuourceAction = action.split(':')[1].toLowerCase(); + + if (allServices[service]) { + for (let supportedResource of allServices[service]) { + if (resuourceAction.includes(supportedResource)) { + if (!allResources[service] || !allResources[service].includes(supportedResource)) { + if (policyFailures.indexOf(action) === -1) policyFailures.push(action); + } + } + } } } } } + // for (let statement of statements) { + // if (statement.Resource.indexOf('*') > -1) { + // let services = [... new Set(statement.Action.map((action) => action.split(':')[0].toLowerCase()))]; + // services.forEach((service) => { + // if (!(service in allResources)) { + // if (policyFailures.indexOf(service) === -1) policyFailures.push(service); + // } + // }); + // } else { + // let arr = statement.Resource[0].split(':'); + // let serviceName = arr[2]; + // let subService = arr[5]; + // let subServiceName; + + // if (subService.indexOf('/') < 0) { + // subServiceName = subService; + // } else { + // let indexOfSlash = subService.indexOf('/'); + // let subServicelength = subService.length; + // subServiceName = indexOfSlash < 2 ? subService.substring(indexOfSlash + 1, subServicelength) : subService.substring(0, indexOfSlash); + // } + + // subServiceName = subServiceName.replace(/\/|[*_-]/g, ''); + + // if (!(serviceName in allResources) || !allResources[serviceName].includes(subServiceName)) { + // if (!(serviceName in allResources) && customServices.includes(serviceName)) { + // if (policyFailures.indexOf(serviceName) === -1) policyFailures.push(serviceName); + // } else { + // if (policyFailures.indexOf(`${serviceName}:${subServiceName}`) === -1) policyFailures.push(`${serviceName}:${subServiceName}`); + // } + // } + // } + // } addRoleFailures(roleFailures, statements, 'inline', config.ignore_service_specific_wildcards); } @@ -387,7 +427,7 @@ module.exports = { } if (policyFailures.length || roleFailures.length) { - let failureMsg = policyFailures.length ? 'Role has policy with following resources which are not being used in this account: ' + + let failureMsg = policyFailures.length ? 'Role policies contain actions of resource types which are not in use: ' + '[ ' + policyFailures.join(', ') + ' ]' + '\r\n' + roleFailures.join(', ') : roleFailures.join(', '); helpers.addResult(results, 2, failureMsg, 'global', role.Arn, custom); } else { From 4aba76f74330252f38ac299940fa625bfd3ab761 Mon Sep 17 00:00:00 2001 From: M-Akhtar Date: Mon, 30 May 2022 21:30:19 +0500 Subject: [PATCH 232/350] changed plugin name --- exports.js | 2 +- ...ervices.js => rolePolicyUnusedServices.js} | 89 +++---------------- 2 files changed, 15 insertions(+), 76 deletions(-) rename plugins/aws/iam/{checkAllUsedServices.js => rolePolicyUnusedServices.js} (79%) diff --git a/exports.js b/exports.js index 86898c2587..1c9ba8b8f0 100644 --- a/exports.js +++ b/exports.js @@ -296,7 +296,7 @@ module.exports = { 'iamDbAuthenticationEnabled' : require(__dirname + '/plugins/aws/rds/iamDbAuthenticationEnabled.js'), 'iamSupportPolicy' : require(__dirname + '/plugins/aws/iam/iamSupportPolicy.js'), 'iamUserPresent' : require(__dirname + '/plugins/aws/iam/iamUserPresent.js'), - 'checkAllUsedServices' : require(__dirname + '/plugins/aws/iam/checkAllUsedServices.js'), + 'rolePolicyUnusedServices' : require(__dirname + '/plugins/aws/iam/rolePolicyUnusedServices.js'), 'iamUserInUse' : require(__dirname + '/plugins/aws/iam/iamUserInUse.js'), 'kinesisEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisEncrypted.js'), diff --git a/plugins/aws/iam/checkAllUsedServices.js b/plugins/aws/iam/rolePolicyUnusedServices.js similarity index 79% rename from plugins/aws/iam/checkAllUsedServices.js rename to plugins/aws/iam/rolePolicyUnusedServices.js index 25c9ada660..22b57c70f1 100644 --- a/plugins/aws/iam/checkAllUsedServices.js +++ b/plugins/aws/iam/rolePolicyUnusedServices.js @@ -8,9 +8,9 @@ module.exports = { category: 'IAM', domain: 'Identity and Access management', description: 'Ensure that IAM role policies are scoped properly as to not provide access to unused AWS services.', - more_info: 'Policies attached to IAM roles should be scoped to least-privileged access and avoid the use of wildcards.', + more_info: 'IAM role policies should only contain actions for resource types which are being used in your account i.e. dynamodb:ListTables permission should only be given when there are DynamoDB tables to adhere to security best practices and to follow principal of least-privilege.', link: 'https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html', - recommended_action: 'Ensure that all IAM roles are scoped to specific services and API calls.', + recommended_action: 'Ensure that all IAM roles are scoped to specific services and resource types.', apis: ['IAM:listRoles', 'IAM:listRolePolicies', 'IAM:listAttachedRolePolicies', 'IAM:listPolicies', 'IAM:getPolicy', 'IAM:getPolicyVersion', 'IAM:getRolePolicy', 'ConfigService:describeConfigurationRecorderStatus', 'ConfigService:getDiscoveredResourceCounts'], settings: { @@ -139,8 +139,6 @@ module.exports = { elasticloadbalancingv2: ['loadbalancer'] }; - const customServices = ['s3', 'codepipeline']; - async.each(regions.configservice, function(region, rcb) { var configSRecorderStatus = helpers.addSource(cache, source, ['configservice', 'describeConfigurationRecorderStatus', region]); @@ -150,21 +148,22 @@ module.exports = { } if (configSRecorderStatus.err || !configSRecorderStatus.data) { - helpers.addResult(results, 0, - 'Unable to query config service: ' + helpers.addError(configSRecorderStatus)); - return rcb(null, results, source); + helpers.addResult(results, 3, + 'Unable to query config service: ' + helpers.addError(configSRecorderStatus), region); + return rcb(); } if (!configSRecorderStatus.data.length) { helpers.addResult(results, 0, - 'Config service is not configured: ' + helpers.addError(configSRecorderStatus)); - return rcb(null, results, source); + 'Config service is not enabled', region); + return rcb(); } + console.log(JSON.stringify(configSRecorderStatus, null, 2)); if (!configSRecorderStatus.data[0].recording) { helpers.addResult(results, 0, - 'Config service is not configured: ' + helpers.addError(configSRecorderStatus)); - return rcb(null, results, source); + 'Config service is not recording', region); + return rcb(); } if (!configSRecorderStatus.data[0].lastStatus && @@ -172,7 +171,7 @@ module.exports = { configSRecorderStatus.data[0].lastStatus.toUpperCase() !== 'PENDING')) { helpers.addResult(results, 0, 'Config Service is configured, and recording, but not delivering properly', region); - return rcb(null, results, source); + return rcb(); } var discoveredResources = helpers.addSource(cache, source, @@ -181,7 +180,7 @@ module.exports = { if (discoveredResources.err || !discoveredResources.data) { helpers.addResult(results, 3, 'Unable to query for Config Resources: ' + helpers.addError(discoveredResources)); - return rcb(null, results, source); + return rcb(); } allResources.push(...discoveredResources.data); @@ -189,7 +188,7 @@ module.exports = { }); if (!allResources.length) { - helpers.addResult(results, 2, 'No Config Resources found.'); + helpers.addResult(results, 0, 'No Config Resources found.'); return callback(null, results, source); } @@ -222,8 +221,6 @@ module.exports = { return callback(null, results, source); } - console.log(JSON.stringify(allResources, null, 2)); - async.each(listRoles.data, function(role, cb){ if (!role.RoleName) return cb(); @@ -321,31 +318,6 @@ module.exports = { } } } - // let service = statements.find((doc) => doc.Resource[0].includes('arn:')); - // if (service) { - // let arr = service.Resource[0].split(':'); - // let serviceName = arr[2]; - // let subService = arr[5]; - // let subServiceName; - - // if (subService.indexOf('/') < 0) { - // subServiceName = subService; - // } else { - // let indexOfSlash = subService.indexOf('/'); - // let subServicelength = subService.length; - // subServiceName = indexOfSlash < 2 ? subService.substring(indexOfSlash + 1, subServicelength) : subService.substring(0, indexOfSlash); - // } - - // subServiceName = subServiceName.replace(/\/|[*_-]/g, ''); - - // if (!(serviceName in allResources) || !allResources[serviceName].includes(subServiceName)) { - // if (!(serviceName in allResources) && customServices.includes(serviceName)) { - // if (policyFailures.indexOf(serviceName) === -1) policyFailures.push(serviceName); - // } else { - // if (policyFailures.indexOf(`${serviceName}:${subServiceName}`) === -1) policyFailures.push(`${serviceName}:${subServiceName}`); - // } - // } - // } addRoleFailures(roleFailures, statements, 'managed', config.ignore_service_specific_wildcards); } @@ -387,39 +359,6 @@ module.exports = { } } } - // for (let statement of statements) { - // if (statement.Resource.indexOf('*') > -1) { - // let services = [... new Set(statement.Action.map((action) => action.split(':')[0].toLowerCase()))]; - // services.forEach((service) => { - // if (!(service in allResources)) { - // if (policyFailures.indexOf(service) === -1) policyFailures.push(service); - // } - // }); - // } else { - // let arr = statement.Resource[0].split(':'); - // let serviceName = arr[2]; - // let subService = arr[5]; - // let subServiceName; - - // if (subService.indexOf('/') < 0) { - // subServiceName = subService; - // } else { - // let indexOfSlash = subService.indexOf('/'); - // let subServicelength = subService.length; - // subServiceName = indexOfSlash < 2 ? subService.substring(indexOfSlash + 1, subServicelength) : subService.substring(0, indexOfSlash); - // } - - // subServiceName = subServiceName.replace(/\/|[*_-]/g, ''); - - // if (!(serviceName in allResources) || !allResources[serviceName].includes(subServiceName)) { - // if (!(serviceName in allResources) && customServices.includes(serviceName)) { - // if (policyFailures.indexOf(serviceName) === -1) policyFailures.push(serviceName); - // } else { - // if (policyFailures.indexOf(`${serviceName}:${subServiceName}`) === -1) policyFailures.push(`${serviceName}:${subServiceName}`); - // } - // } - // } - // } addRoleFailures(roleFailures, statements, 'inline', config.ignore_service_specific_wildcards); } @@ -427,7 +366,7 @@ module.exports = { } if (policyFailures.length || roleFailures.length) { - let failureMsg = policyFailures.length ? 'Role policies contain actions of resource types which are not in use: ' + + let failureMsg = policyFailures.length ? 'Role policies contain actions for resource types which are not in use: ' + '[ ' + policyFailures.join(', ') + ' ]' + '\r\n' + roleFailures.join(', ') : roleFailures.join(', '); helpers.addResult(results, 2, failureMsg, 'global', role.Arn, custom); } else { From 81654707bc4629cded6c2b63ef3ac048a8c682be Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Tue, 31 May 2022 14:50:47 +0500 Subject: [PATCH 233/350] updated spec --- plugins/aws/iam/rolePolicyUnusedServices.js | 50 +- .../aws/iam/rolePolicyUnusedServices.spec.js | 466 ++++++++++++++++++ 2 files changed, 492 insertions(+), 24 deletions(-) create mode 100644 plugins/aws/iam/rolePolicyUnusedServices.spec.js diff --git a/plugins/aws/iam/rolePolicyUnusedServices.js b/plugins/aws/iam/rolePolicyUnusedServices.js index 22b57c70f1..68d173d255 100644 --- a/plugins/aws/iam/rolePolicyUnusedServices.js +++ b/plugins/aws/iam/rolePolicyUnusedServices.js @@ -89,7 +89,7 @@ module.exports = { var iamRegion = helpers.defaultRegion(settings); var allResources = []; - const allServices = { + const allServices = { apigateway: ['stage', 'restapi', 'api'], cloudfront: ['distribution', 'streamingdistribution'], cloudwatch: ['Alarm'], @@ -140,36 +140,35 @@ module.exports = { }; async.each(regions.configservice, function(region, rcb) { - var configSRecorderStatus = helpers.addSource(cache, source, + var configRecorderStatus = helpers.addSource(cache, source, ['configservice', 'describeConfigurationRecorderStatus', region]); - if (!configSRecorderStatus) { + if (!configRecorderStatus) { return rcb(); } - if (configSRecorderStatus.err || !configSRecorderStatus.data) { + if (configRecorderStatus.err || !configRecorderStatus.data) { helpers.addResult(results, 3, - 'Unable to query config service: ' + helpers.addError(configSRecorderStatus), region); + 'Unable to query config service: ' + helpers.addError(configRecorderStatus), region); return rcb(); } - if (!configSRecorderStatus.data.length) { - helpers.addResult(results, 0, + if (!configRecorderStatus.data.length) { + helpers.addResult(results, 2, 'Config service is not enabled', region); return rcb(); } - console.log(JSON.stringify(configSRecorderStatus, null, 2)); - if (!configSRecorderStatus.data[0].recording) { - helpers.addResult(results, 0, + if (!configRecorderStatus.data[0].recording) { + helpers.addResult(results, 2, 'Config service is not recording', region); return rcb(); } - if (!configSRecorderStatus.data[0].lastStatus && - (configSRecorderStatus.data[0].lastStatus.toUpperCase() !== 'SUCCESS' || - configSRecorderStatus.data[0].lastStatus.toUpperCase() !== 'PENDING')) { - helpers.addResult(results, 0, + if (!configRecorderStatus.data[0].lastStatus || + (configRecorderStatus.data[0].lastStatus.toUpperCase() !== 'SUCCESS' && + configRecorderStatus.data[0].lastStatus.toUpperCase() !== 'PENDING')) { + helpers.addResult(results, 2, 'Config Service is configured, and recording, but not delivering properly', region); return rcb(); } @@ -179,7 +178,7 @@ module.exports = { if (discoveredResources.err || !discoveredResources.data) { helpers.addResult(results, 3, - 'Unable to query for Config Resources: ' + helpers.addError(discoveredResources)); + 'Unable to query for Discovered Resources: ' + helpers.addError(discoveredResources)); return rcb(); } @@ -188,7 +187,7 @@ module.exports = { }); if (!allResources.length) { - helpers.addResult(results, 0, 'No Config Resources found.'); + helpers.addResult(results, 0, 'No Discovered Resources found.'); return callback(null, results, source); } @@ -302,13 +301,12 @@ module.exports = { for (let statement of statements) { if (statement.Action && statement.Action.length) { for (let action of statement.Action) { - // console.log(action); let service = action.split(':')[0].toLowerCase(); - let resuourceAction = action.split(':')[1].toLowerCase(); + let resourceAction = action.split(':')[1].toLowerCase(); if (allServices[service]) { for (let supportedResource of allServices[service]) { - if (resuourceAction.includes(supportedResource)) { + if (resourceAction.includes(supportedResource)) { if (!allResources[service] || !allResources[service].includes(supportedResource)) { if (policyFailures.indexOf(action) === -1) policyFailures.push(action); } @@ -341,15 +339,19 @@ module.exports = { if (!statements) break; for (let statement of statements) { - if (statement.Action && statement.Action.length) { + if ((statement.Action && statement.Action.length === 1 && statement.Action[0] === '*') && (statement.Resource && statement.Resource.length === 1 && statement.Resource[0] === '*')) { + continue; + } + + let service = statement.Resource[0].includes('arn') ? statement.Resource[0].split(':')[2].toLowerCase() : + statement.Action[0].split(':')[1].toLowerCase(); + if (statement.Action.length > 1 || statement.Action[0] !== '*') { for (let action of statement.Action) { - // console.log(action); - let service = action.split(':')[0].toLowerCase(); - let resuourceAction = action.split(':')[1].toLowerCase(); + let resourceAction = action.split(':')[1].toLowerCase(); if (allServices[service]) { for (let supportedResource of allServices[service]) { - if (resuourceAction.includes(supportedResource)) { + if (resourceAction.includes(supportedResource)) { if (!allResources[service] || !allResources[service].includes(supportedResource)) { if (policyFailures.indexOf(action) === -1) policyFailures.push(action); } diff --git a/plugins/aws/iam/rolePolicyUnusedServices.spec.js b/plugins/aws/iam/rolePolicyUnusedServices.spec.js new file mode 100644 index 0000000000..618ed60c8d --- /dev/null +++ b/plugins/aws/iam/rolePolicyUnusedServices.spec.js @@ -0,0 +1,466 @@ +const expect = require('chai').expect; +var rolePolicyUnusedServices = require('./rolePolicyUnusedServices'); + + +const listRoles = [ + { + "Path": "/", + "RoleName": "test-role-1", + "RoleId": "AROAYE32SRU5VIMXXL3BH", + "Arn": "arn:aws:iam::000011112222:role/test-role-1", + "CreateDate": "2020-11-21T23:56:33Z", + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::000011112222:root" + }, + "Action": "sts:AssumeRoleWithSAML", + "Condition": {} + } + ] + }, + "MaxSessionDuration": 3600 + }, + { + "Path": "/", + "RoleName": "test-role-2", + "RoleId": "AROAYE32SRU5VIMXXL3BH", + "Arn": "arn:aws:iam::000011112222:role/test-role-2", + "CreateDate": "2020-11-21T23:56:33Z", + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::000011112222:root" + }, + "Action": "sts:AssumeRoleWithSAML", + "Condition": {} + } + ] + }, + "MaxSessionDuration": 3600 + }, + { + "Path": "/", + "RoleName": "test-role-1", + "RoleId": "AROAYE32SRU5VIMXXL3BH", + "Arn": "arn:aws:iam::000011112222:role/test-role-1", + "CreateDate": "2020-11-21T23:56:33Z", + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::000011112222:root" + }, + "Action": "ec2:DescribeTransitGatewayRouteTables", + "Condition": {} + } + ] + }, + "MaxSessionDuration": 3600 + }, +]; + +const listRolePolicies = [ + { + "PolicyNames": [ + "S3-Full" + ] + }, + { + "PolicyNames": [ + "All-Action-Resources" + ] + } +]; + +const listAttachedRolePolicies = [ + { + "ResponseMetadata": { + "RequestId": 'f7d427cc-970b-47af-9b7d-3e06121f83da' + }, + "AttachedPolicies": [ + { + "PolicyName": 'AdministratorAccess', + "PolicyArn": 'arn:aws:iam::aws:policy/AdministratorAccess' + } + ], + "IsTruncated": false + }, + { + "ResponseMetadata": { + "RequestId": 'b06a66ed-53af-4737-b0d3-7ef9031d2c2e' + }, + "AttachedPolicies": [ + { + "PolicyName": 'EC2-Full', + "PolicyArn": 'arn:aws:iam::000011112222:policy/EC2-Full' + } + ], + "IsTruncated": false + }, + { + "ResponseMetadata": { + "RequestId": 'b06a66ed-53af-4737-b0d3-7ef9031d2c2e' + }, + "AttachedPolicies": [ + { + "PolicyName": 'EC2-Wildcard', + "PolicyArn": 'arn:aws:iam::000011112222:policy/EC2-Wildcard' + } + ], + "IsTruncated": false + } +]; + +const getRolePolicy = [ + { + "RoleName": 'test-role-2', + "PolicyName": 'S3-Full', + "PolicyDocument": '%7B%0A%20%20%20%20%22Version%22%3A%20%222012-10-17%22%2C%0A%20%20%20%20%22Statement%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Sid%22%3A%20%22VisualEditor0%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Effect%22%3A%20%22Allow%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Action%22%3A%20%22s3%3A%2A%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Resource%22%3A%20%22%2A%22%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%5D%0A%7D' + }, + { + "RoleName": 'test-role-2', + "PolicyName": 'S3-WildCard', + "PolicyDocument": '%7B%0A%20%20%20%20%22Version%22%3A%20%222012-10-17%22%2C%0A%20%20%20%20%22Statement%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Sid%22%3A%20%22VisualEditor1%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Effect%22%3A%20%22Allow%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Action%22%3A%20%22s3%3Ag%2A%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Resource%22%3A%20%22%2A%22%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%5D%0A%7D' + }, + { + "RoleName": 'test-role-2', + "PolicyName": 'S3-Limited', + "PolicyDocument": '%7B%0A%20%20%20%20%22Version%22%3A%20%222012-10-17%22%2C%0A%20%20%20%20%22Statement%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Sid%22%3A%20%22VisualEditor1%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Effect%22%3A%20%22Allow%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Action%22%3A%20%22s3%3AGetObject%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Resource%22%3A%20%22%2A%22%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%5D%0A%7D' + }, + { + "RoleName": 'test-role-2', + "PolicyName": 'All-Action-Resources', + "PolicyDocument":'%7B%0A%20%20%20%20%22Version%22%3A%20%222012-10-17%22%2C%0A%20%20%20%20%22Statement%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Sid%22%3A%20%22VisualEditor1%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Effect%22%3A%20%22Allow%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Action%22%3A%20%22%2A%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Resource%22%3A%20%22%2A%22%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%5D%0A%7D' + }, + { + "RoleName": 'test-role-2', + "PolicyName": 'All-Actions', + "PolicyDocument": '%7B%0A%20%20%20%20%22Version%22%3A%20%222012-10-17%22%2C%0A%20%20%20%20%22Statement%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Sid%22%3A%20%22VisualEditor1%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Effect%22%3A%20%22Allow%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Action%22%3A%20%22%2A%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Resource%22%3A%20%22arn%3Aaws%3As3%3A%3A%3A%2A%22%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%5D%0A%7D' + } +]; + +const getPolicy = [ + { + "Policy": { + "PolicyName": 'EC2-Wildcard', + "PolicyId": 'ANPAYE32SRU57UHNCIGCT', + "Arn": 'arn:aws:iam::000011112222:policy/EC2-Wildcard', + "Path": '/', + "DefaultVersionId": 'v5', + "AttachmentCount": 2, + "PermissionsBoundaryUsageCount": 0, + "IsAttachable": true + } + } +]; + +const getPolicyVersion = [ + { + "PolicyVersion": { + "Document": '%7B%0A%20%20%20%20%22Version%22%3A%20%222012-10-17%22%2C%0A%20%20%20%20%22Statement%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Sid%22%3A%20%22VisualEditor1%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Effect%22%3A%20%22Allow%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Action%22%3A%20%22s3%3Ag%2A%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Resource%22%3A%20%22%2A%22%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%5D%0A%7D', + "VersionId": 'v5', + } + } +]; + +const configStatus = [ + { + name: 'default', + lastStartTime: '2022-05-30T16:15:43.358Z', + lastStopTime: '2022-05-30T16:12:18.651Z', + recording: true, + lastStatus: 'SUCCESS', + lastStatusChangeTime: '2022-05-31T05:16:02.486Z' + }, + { + name: 'default', + lastStartTime: '2022-05-30T16:15:43.358Z', + lastStopTime: '2022-05-30T16:12:18.651Z', + recording: false, + lastStatus: 'SUCCESS', + lastStatusChangeTime: '2022-05-31T05:16:02.486Z' + }, + { + name: 'default', + lastStartTime: '2022-05-30T16:15:43.358Z', + lastStopTime: '2022-05-30T16:12:18.651Z', + recording: true, + lastStatus: 'FAILURE', + lastStatusChangeTime: '2022-05-31T05:16:02.486Z' + } +]; + +const discoveredResources = [ + { resourceType: 'AWS::IAM::Role', count: 91 }, + { resourceType: 'AWS::IAM::Policy', count: 38 }, + { resourceType: 'AWS::KMS::Key', count: 28 }, + { resourceType: 'AWS::S3::Bucket', count: 19 }, + { resourceType: 'AWS::EC2::SecurityGroup', count: 17 }, + { resourceType: 'AWS::CodeDeploy::DeploymentConfig', count: 17 }, + { resourceType: 'AWS::IAM::User', count: 8 }, + { resourceType: 'AWS::EC2::Subnet', count: 8 }, + { resourceType: 'AWS::CloudFormation::Stack', count: 6 }, + { resourceType: 'AWS::CloudWatch::Alarm', count: 5 }, + { resourceType: 'AWS::Lambda::Function', count: 4 }, + { resourceType: 'AWS::EC2::RouteTable', count: 4 }, + { resourceType: 'AWS::SNS::Topic', count: 4 }, + { resourceType: 'AWS::EC2::VPC', count: 3 }, + { resourceType: 'AWS::EC2::NetworkInterface', count: 3 }, + { resourceType: 'AWS::ApiGateway::Stage', count: 3 }, + { resourceType: 'AWS::EC2::NetworkAcl', count: 3 }, + { resourceType: 'AWS::EC2::InternetGateway', count: 2 }, + { resourceType: 'AWS::AccessAnalyzer::Analyzer', count: 2 }, + { resourceType: 'AWS::CloudTrail::Trail', count: 2 }, + { resourceType: 'AWS::ApiGatewayV2::Stage', count: 2 }, + { resourceType: 'AWS::Backup::BackupVault', count: 2 }, + { resourceType: 'AWS::ApiGateway::RestApi', count: 2 }, + { resourceType: 'AWS::SQS::Queue', count: 1 }, + { resourceType: 'AWS::EC2::Instance', count: 1 }, + { resourceType: 'AWS::RDS::DBSubnetGroup', count: 1 }, + { resourceType: 'AWS::Redshift::ClusterParameterGroup', count: 1 }, + { resourceType: 'AWS::S3::AccountPublicAccessBlock', count: 1 }, + { resourceType: 'AWS::SecretsManager::Secret', count: 1 }, + { resourceType: 'AWS::RDS::DBSnapshot', count: 1 }, + { resourceType: 'AWS::EC2::LaunchTemplate', count: 1 }, + { resourceType: 'AWS::Redshift::ClusterSubnetGroup', count: 1 }, + { resourceType: 'AWS::RDS::DBSecurityGroup', count: 1 }, + { resourceType: 'AWS::CodeBuild::Project', count: 1 }, + { resourceType: 'AWS::ApiGatewayV2::Api', count: 1 }, + { resourceType: 'AWS::EC2::Volume', count: 1 }, + { resourceType: 'AWS::ECR::Repository', count: 1 } +]; + +const createCache = (configStatus, discoveredResources, listRoles, listAttachedRolePolicies, listRolePolicies, getRolePolicy, getPolicy, getPolicyVersion, configStatusErr, discoveredResourcesErr, listRolesErr, listRolePoliciesErr, listAttachedRolePoliciesErr) => { + var roleName = (listRoles && listRoles.length) ? listRoles[0].RoleName : null; + var policyArn = (listAttachedRolePolicies && listAttachedRolePolicies.AttachedPolicies) ? listAttachedRolePolicies.AttachedPolicies[0].PolicyArn : null; + var policyName = (listRolePolicies && listRolePolicies.PolicyNames) ? listRolePolicies.PolicyNames[0] : null; + return { + configservice: { + describeConfigurationRecorderStatus: { + 'us-east-1': { + err: configStatusErr, + data: configStatus + } + }, + getDiscoveredResourceCounts: { + 'us-east-1': { + err: discoveredResourcesErr, + data: discoveredResources + } + } + }, + iam: { + listRoles: { + 'us-east-1': { + err: listRolesErr, + data: listRoles + } + }, + listAttachedRolePolicies: { + 'us-east-1': { + [roleName]: { + err: listAttachedRolePoliciesErr, + data: listAttachedRolePolicies + } + } + }, + listRolePolicies: { + 'us-east-1': { + [roleName]: { + err: listRolePoliciesErr, + data: listRolePolicies + } + } + }, + getPolicy: { + 'us-east-1': { + [policyArn]: { + data: getPolicy + } + } + }, + getRolePolicy: { + 'us-east-1': { + [roleName]: { + [policyName]: { + data: getRolePolicy + } + } + } + }, + getPolicyVersion: { + 'us-east-1': { + [policyArn]: { + data: getPolicyVersion + } + } + } + } + }; +}; + +describe('rolePolicyUnusedServices', function () { + describe('run', function () { + it('should PASS if role does not have overly-permissive policy', function (done) { + const cache = createCache([configStatus[0]], discoveredResources, [listRoles[0]], listAttachedRolePolicies[2], listRolePolicies[0], getRolePolicy[2]); + rolePolicyUnusedServices.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should FAIL if role policy allows wildcard actions', function (done) { + const cache = createCache([configStatus[0]], discoveredResources, [listRoles[0]], listAttachedRolePolicies[2], null, null, getPolicy[0], getPolicyVersion[0]); + rolePolicyUnusedServices.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + done(); + }); + }); + + it('should PASS if role policy allows wildcard actions but ignore managed iam policies is set to true', function (done) { + const cache = createCache([configStatus[0]], discoveredResources, [listRoles[0]], listAttachedRolePolicies[2], null, null, getPolicy[0], getPolicyVersion[0]); + rolePolicyUnusedServices.run(cache, { ignore_customer_managed_iam_policies : 'true' }, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should FAIL if role policy allows all actions on selected resources', function (done) { + const cache = createCache([configStatus[0]], discoveredResources, [listRoles[0]], {}, listRolePolicies[1], getRolePolicy[4]); + rolePolicyUnusedServices.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + done(); + }); + }); + + it('should FAIL if role policy allows all actions on all resources', function (done) { + const cache = createCache([configStatus[0]], discoveredResources, [listRoles[1]], {}, listRolePolicies[1], getRolePolicy[3]); + rolePolicyUnusedServices.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + done(); + }); + }); + + it('should PASS if role policy allows wildcard actions but ignore service specific roles setting is enabled', function (done) { + const cache = createCache([configStatus[0]], discoveredResources, [listRoles[0]], listAttachedRolePolicies[2], null, null, getPolicy[0], getPolicyVersion[0]); + rolePolicyUnusedServices.run(cache, { ignore_service_specific_wildcards: 'true' }, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should PASS if on IAM roles found', function (done) { + const cache = createCache([configStatus[0]], discoveredResources, []); + rolePolicyUnusedServices.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should UNKNOWN if unable to list IAM roles', function (done) { + const cache = createCache([configStatus[0]], discoveredResources, null, null, null, null, null, null, null, null, { message: 'Unable to list IAM roles'}); + rolePolicyUnusedServices.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should UNKNOWN if unable to list attached role policies', function (done) { + const cache = createCache([configStatus[0]], discoveredResources, [listRoles[1]], {}, null, null, null, null, null, null, null, null, { message: 'Unable to list attached role policies'}); + rolePolicyUnusedServices.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should UNKNOWN if unable to list role policies', function (done) { + const cache = createCache([configStatus[0]], discoveredResources, [listRoles[1]], listAttachedRolePolicies[0], {}, null, null, null, null, null, null, { message: 'Unable to query role policies'}); + rolePolicyUnusedServices.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should UNKNOWN if no unable to query for Config Service', function (done) { + const cache = createCache(null, discoveredResources, [listRoles[1]], listAttachedRolePolicies[0], null, null, null, null, { message: 'Unable to query Config Service'}); + rolePolicyUnusedServices.run(cache, {}, (err, results) => { + expect(results.length).to.equal(2); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should FAIL if Config Service is not enabled', function (done) { + const cache = createCache([], discoveredResources, [listRoles[1]], listAttachedRolePolicies[0]); + rolePolicyUnusedServices.run(cache, {}, (err, results) => { + expect(results.length).to.equal(2); + expect(results[0].status).to.equal(2); + done(); + }); + }); + + it('should FAIL if Config Service is not recording', function (done) { + const cache = createCache([configStatus[1]], discoveredResources, [listRoles[1]], listAttachedRolePolicies[0]); + rolePolicyUnusedServices.run(cache, {}, (err, results) => { + expect(results.length).to.equal(2); + expect(results[0].status).to.equal(2); + done(); + }); + }); + + it('should FAIL if Config Service is recording but not delivering properly', function (done) { + const cache = createCache([configStatus[2]], discoveredResources, [listRoles[1]], listAttachedRolePolicies[0]); + rolePolicyUnusedServices.run(cache, {}, (err, results) => { + expect(results.length).to.equal(2); + expect(results[0].status).to.equal(2); + done(); + }); + }); + + it('should UKNOWN if unable to query for Discovered Resources', function (done) { + const cache = createCache([configStatus[0]], null, [listRoles[1]], listAttachedRolePolicies[0]); + rolePolicyUnusedServices.run(cache, {}, (err, results) => { + expect(results.length).to.equal(2); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should PASS if no Discovered Resources found', function (done) { + const cache = createCache([configStatus[0]], [], [listRoles[1]], listAttachedRolePolicies[0]); + rolePolicyUnusedServices.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should FAIL if Role policies contain actions for resource types which are not in use', function (done) { + const cache = createCache([configStatus[0]], discoveredResources, [listRoles[0]], {}, listRolePolicies[1], getRolePolicy[4]); + rolePolicyUnusedServices.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + done(); + }); + }); + }); +}); From 3ac41fdbef32284db08efb9699a4e3066404bd5c Mon Sep 17 00:00:00 2001 From: Gio Rodriguez Date: Wed, 1 Jun 2022 13:30:50 +0200 Subject: [PATCH 234/350] syncing saas master to open source (#1282) --- plugins/aws/autoscaling/asgMultiAz.js | 5 +++-- .../cloudtrail/cloudtrailNotificationsEnabled.js | 2 +- .../configservice/configServiceMissingBucket.js | 2 +- plugins/aws/ec2/ebsEncryptionEnabled.js | 2 +- plugins/aws/ec2/flowLogsEnabled.js | 15 ++++++++++----- plugins/aws/ec2/multipleSubnets.js | 14 ++++++++++---- plugins/aws/elb/insecureCiphers.js | 13 +++++++++---- plugins/aws/redshift/redshiftEncryptionEnabled.js | 14 ++++++++++---- .../aws/redshift/redshiftPubliclyAccessible.js | 14 ++++++++++---- .../aws/redshift/redshiftUnusedReservedNodes.js | 12 +++++++++--- plugins/aws/s3/bucketPolicyCloudFrontOai.js | 7 ++++--- plugins/aws/s3/versionedBucketsLC.js | 8 ++------ plugins/aws/ses/dkimEnabled.js | 14 ++++++++++---- .../azure/networksecuritygroups/openAllPorts.js | 2 +- plugins/azure/sqlserver/tdeProtectorEncrypted.js | 2 +- .../google/kubernetes/privateClusterEnabled.js | 4 +++- 16 files changed, 85 insertions(+), 45 deletions(-) diff --git a/plugins/aws/autoscaling/asgMultiAz.js b/plugins/aws/autoscaling/asgMultiAz.js index 04250446b2..9d775d6247 100644 --- a/plugins/aws/autoscaling/asgMultiAz.js +++ b/plugins/aws/autoscaling/asgMultiAz.js @@ -36,16 +36,17 @@ module.exports = { // loop through autoscaling Instances describeAutoScalingGroups.data.forEach(function(Asg){ + var resource = Asg.AutoScalingGroupARN; if (Asg.AvailabilityZones.length <=1) { helpers.addResult(results, 2, 'Auto scaling group is only using ' + Asg.AvailabilityZones.length + ' availability zones', - region, Asg.AutoScalingGroupName); + region, resource); } else { helpers.addResult(results, 0, 'Auto scaling group using ' + Asg.AvailabilityZones.length + ' availability zones', - region, Asg.AutoScalingGroupName); + region, resource); } }); rcb(); diff --git a/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js b/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js index 1fd47a8f6f..ca8111db61 100644 --- a/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js +++ b/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js @@ -65,7 +65,7 @@ module.exports = { helpers.addResult(results, 3, `Unable to query for SNS topic: ${helpers.addError(describeTrails)}`, region, resource); - } else { + } else { helpers.addResult(results, 0, 'CloudTrail trail is using active SNS topic', region, resource); diff --git a/plugins/aws/configservice/configServiceMissingBucket.js b/plugins/aws/configservice/configServiceMissingBucket.js index c2877c0f7f..f0279cc2c6 100644 --- a/plugins/aws/configservice/configServiceMissingBucket.js +++ b/plugins/aws/configservice/configServiceMissingBucket.js @@ -46,7 +46,7 @@ module.exports = { deletedBuckets.push(record); } else if (!headBucket || headBucket.err) { helpers.addResult(results, 3, - 'Unable to query S3 bucket: ' + helpers.addError(headBucket), region); + 'Unable to query S3 bucket: ' + helpers.addError(headBucket), region, 'arn:aws:s3:::' + record.s3BucketName); continue; } } diff --git a/plugins/aws/ec2/ebsEncryptionEnabled.js b/plugins/aws/ec2/ebsEncryptionEnabled.js index c741ad1e8c..a86f0ec21c 100644 --- a/plugins/aws/ec2/ebsEncryptionEnabled.js +++ b/plugins/aws/ec2/ebsEncryptionEnabled.js @@ -85,7 +85,7 @@ module.exports = { for (let volume of describeVolumes.data) { var resource = 'arn:' + awsOrGov + ':ec2:' + region + ':' + accountId + ':volume/' + volume.VolumeId; if (!volume.Encrypted || !volume.KmsKeyId){ - helpers.addResult(results, 2, 'EBS volume is unencrypted', region); + helpers.addResult(results, 2, 'EBS volume is unencrypted', region, resource); continue; } diff --git a/plugins/aws/ec2/flowLogsEnabled.js b/plugins/aws/ec2/flowLogsEnabled.js index 0e5aaaa13f..c4827e15e0 100644 --- a/plugins/aws/ec2/flowLogsEnabled.js +++ b/plugins/aws/ec2/flowLogsEnabled.js @@ -10,7 +10,7 @@ module.exports = { more_info: 'VPC flow logs record all traffic flowing in to and out of a VPC. These logs are critical for auditing and review after security incidents.', link: 'http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/flow-logs.html', recommended_action: 'Enable VPC flow logs for each VPC', - apis: ['EC2:describeVpcs', 'EC2:describeFlowLogs'], + apis: ['EC2:describeVpcs', 'EC2:describeFlowLogs', 'STS:getCallerIdentity'], compliance: { hipaa: 'VPC Flow Logs provide a detailed traffic log of a VPC network ' + 'containing HIPAA data. Flow Logs should be enabled to satisfy ' + @@ -25,6 +25,10 @@ module.exports = { var source = {}; var regions = helpers.regions(settings); + var acctRegion = helpers.defaultRegion(settings); + var awsOrGov = helpers.defaultPartition(settings); + var accountId = helpers.addSource(cache, source, ['sts', 'getCallerIdentity', acctRegion, 'data']); + async.each(regions.flowlogs, function(region, rcb){ var describeVpcs = helpers.addSource(cache, source, ['ec2', 'describeVpcs', region]); @@ -67,9 +71,10 @@ module.exports = { } // Loop through VPCs and add results - for (var v in vpcMap) { + for (var v in vpcMap) { + var resource = 'arn:' + awsOrGov + ':ec2:' + region + ':' + accountId + ':vpc/' + v; if (!vpcMap[v].length) { - helpers.addResult(results, 2, 'VPC flow logs are not enabled', region, v); + helpers.addResult(results, 2, 'VPC flow logs are not enabled', region, resource); } else { var activeLogs = false; @@ -81,9 +86,9 @@ module.exports = { } if (activeLogs) { - helpers.addResult(results, 0, 'VPC flow logs are enabled', region, v); + helpers.addResult(results, 0, 'VPC flow logs are enabled', region, resource); } else { - helpers.addResult(results, 2, 'VPC flow logs are enabled, but not active', region, v); + helpers.addResult(results, 2, 'VPC flow logs are enabled, but not active', region, resource); } } } diff --git a/plugins/aws/ec2/multipleSubnets.js b/plugins/aws/ec2/multipleSubnets.js index 2fbaf7eb30..d3f07c4ef2 100644 --- a/plugins/aws/ec2/multipleSubnets.js +++ b/plugins/aws/ec2/multipleSubnets.js @@ -9,13 +9,17 @@ module.exports = { more_info: 'VPCs should be designed to have separate public and private subnets, ideally across availability zones, enabling a DMZ-style architecture.', link: 'https://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Subnets.html#SubnetSecurity', recommended_action: 'Create at least two subnets in each VPC, utilizing one for public traffic and the other for private traffic.', - apis: ['EC2:describeVpcs', 'EC2:describeSubnets'], + apis: ['EC2:describeVpcs', 'EC2:describeSubnets', 'STS:getCallerIdentity'], run: function(cache, settings, callback) { var results = []; var source = {}; var regions = helpers.regions(settings); + var acctRegion = helpers.defaultRegion(settings); + var awsOrGov = helpers.defaultPartition(settings); + var accountId = helpers.addSource(cache, source, ['sts', 'getCallerIdentity', acctRegion, 'data']); + async.each(regions.ec2, function(region, rcb){ var describeVpcs = helpers.addSource(cache, source, ['ec2', 'describeVpcs', region]); @@ -55,18 +59,20 @@ module.exports = { return rcb(); } + var resource = 'arn:' + awsOrGov + ':ec2:' + region + ':' + accountId + ':vpc/' + vpcId; + if (describeSubnets.data.Subnets.length > 1) { helpers.addResult(results, 0, 'There are ' + describeSubnets.data.Subnets.length + ' subnets used in one VPC.', - region, vpcId); + region, resource); } else if (describeSubnets.data.Subnets.length === 1) { helpers.addResult(results, 2, 'Only one subnet (' + describeSubnets.data.Subnets[0].SubnetId + ') in one VPC is used.', - region, vpcId); + region, resource); } else { helpers.addResult(results, 0, 'The VPC does not contain any subnets', - region, vpcId); + region, resource); } rcb(); diff --git a/plugins/aws/elb/insecureCiphers.js b/plugins/aws/elb/insecureCiphers.js index c8e8791712..efeb7bf2fe 100644 --- a/plugins/aws/elb/insecureCiphers.js +++ b/plugins/aws/elb/insecureCiphers.js @@ -83,7 +83,7 @@ module.exports = { more_info: 'Various security vulnerabilities have rendered several ciphers insecure. Only the recommended ciphers should be used.', link: 'http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-security-policy-options.html', recommended_action: 'Update your ELBs to use the recommended cipher suites', - apis: ['ELB:describeLoadBalancers', 'ELB:describeLoadBalancerPolicies'], + apis: ['ELB:describeLoadBalancers', 'ELB:describeLoadBalancerPolicies', 'STS:getCallerIdentity'], compliance: { hipaa: 'All HIPAA data should be encrypted in transit. Using secure ciphers ' + 'is a critical aspect of this requirement. Using outdated ciphers with ' + @@ -98,6 +98,10 @@ module.exports = { var source = {}; var regions = helpers.regions(settings); + var acctRegion = helpers.defaultRegion(settings); + var accountId = helpers.addSource(cache, source, ['sts', 'getCallerIdentity', acctRegion, 'data']); + var awsOrGov = helpers.defaultPartition(settings); + async.each(regions.elb, function(region, rcb){ var describeLoadBalancers = helpers.addSource(cache, source, ['elb', 'describeLoadBalancers', region]); @@ -117,6 +121,7 @@ module.exports = { async.each(describeLoadBalancers.data, function(lb, cb){ if (!lb.DNSName) return cb(); + var resource = `arn:${awsOrGov}:elasticloadbalancing:${region}:${accountId}:loadbalancer/${lb.LoadBalancerName}`; var describeLoadBalancerPolicies = helpers.addSource(cache, source, ['elb', 'describeLoadBalancerPolicies', region, lb.DNSName]); @@ -129,7 +134,7 @@ module.exports = { helpers.addResult(results, 3, 'Unable to query load balancer policies for ELB: ' + lb.LoadBalancerName + ': ' + helpers.addError(describeLoadBalancerPolicies), - region, lb.DNSName); + region, resource); return cb(); } @@ -151,11 +156,11 @@ module.exports = { if (elbBad.length) { helpers.addResult(results, 1, 'ELB: ' + lb.LoadBalancerName + ' uses insecure protocols or ciphers: ' + elbBad.join(', '), - region, lb.DNSName); + region, resource); } else { helpers.addResult(results, 0, 'ELB: ' + lb.LoadBalancerName + ' uses secure protocols and ciphers', - region, lb.DNSName); + region, resource); } } diff --git a/plugins/aws/redshift/redshiftEncryptionEnabled.js b/plugins/aws/redshift/redshiftEncryptionEnabled.js index 19b6d6ac6c..744f8b33e5 100644 --- a/plugins/aws/redshift/redshiftEncryptionEnabled.js +++ b/plugins/aws/redshift/redshiftEncryptionEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'AWS provides at-read encryption for Redshift clusters which should be enabled to ensure the integrity of data stored within the cluster.', link: 'http://docs.aws.amazon.com/redshift/latest/mgmt/working-with-db-encryption.html', recommended_action: 'Redshift does not currently allow modifications to encryption after the cluster has been launched, so a new cluster will need to be created with encryption enabled.', - apis: ['Redshift:describeClusters'], + apis: ['Redshift:describeClusters', 'STS:getCallerIdentity'], compliance: { hipaa: 'All data in HIPAA environments must be encrypted, including ' + 'data at rest. Redshift encryption ensures that this HIPAA control ' + @@ -22,6 +22,11 @@ module.exports = { var source = {}; var regions = helpers.regions(settings); + var acctRegion = helpers.defaultRegion(settings); + var accountId = helpers.addSource(cache, source, + ['sts', 'getCallerIdentity', acctRegion, 'data']); + var awsOrGov = helpers.defaultPartition(settings); + async.each(regions.redshift, function(region, rcb){ var describeClusters = helpers.addSource(cache, source, ['redshift', 'describeClusters', region]); @@ -42,12 +47,13 @@ module.exports = { for (var i in describeClusters.data) { // For resource, attempt to use the endpoint address (more specific) but fallback to the instance identifier var cluster = describeClusters.data[i]; - var clusterResource = (cluster.Endpoint && cluster.Endpoint.Address) ? cluster.Endpoint.Address : cluster.ClusterIdentifier; + var clusterIdentifier = cluster.ClusterIdentifier; + var resource = `arn:${awsOrGov}:redshift:${region}:${accountId}:cluster:${clusterIdentifier}`; if (cluster.Encrypted) { - helpers.addResult(results, 0, 'Redshift cluster is encrypted', region, clusterResource); + helpers.addResult(results, 0, 'Redshift cluster is encrypted', region, resource); } else { - helpers.addResult(results, 1, 'Redshift cluster is not encrypted', region, clusterResource); + helpers.addResult(results, 1, 'Redshift cluster is not encrypted', region, resource); } } diff --git a/plugins/aws/redshift/redshiftPubliclyAccessible.js b/plugins/aws/redshift/redshiftPubliclyAccessible.js index 42b0888f86..1379cf26de 100644 --- a/plugins/aws/redshift/redshiftPubliclyAccessible.js +++ b/plugins/aws/redshift/redshiftPubliclyAccessible.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Unless there is a specific business requirement, Redshift clusters should not have a public endpoint and should be accessed from within a VPC only.', link: 'http://docs.aws.amazon.com/redshift/latest/mgmt/getting-started-cluster-in-vpc.html', recommended_action: 'Remove the public endpoint from the Redshift cluster', - apis: ['Redshift:describeClusters'], + apis: ['Redshift:describeClusters', 'STS:getCallerIdentity'], compliance: { hipaa: 'Redshift instances should only be launched in VPC environments and ' + 'accessed through private endpoints. Exposing Redshift instances to ' + @@ -26,6 +26,11 @@ module.exports = { var source = {}; var regions = helpers.regions(settings); + var acctRegion = helpers.defaultRegion(settings); + var accountId = helpers.addSource(cache, source, + ['sts', 'getCallerIdentity', acctRegion, 'data']); + var awsOrGov = helpers.defaultPartition(settings); + async.each(regions.redshift, function(region, rcb){ var describeClusters = helpers.addSource(cache, source, ['redshift', 'describeClusters', region]); @@ -46,12 +51,13 @@ module.exports = { for (var i in describeClusters.data) { // For resource, attempt to use the endpoint address (more specific) but fallback to the instance identifier var cluster = describeClusters.data[i]; - var clusterResource = (cluster.Endpoint && cluster.Endpoint.Address) ? cluster.Endpoint.Address : cluster.ClusterIdentifier; + var clusterIdentifier = cluster.ClusterIdentifier; + var resource = `arn:${awsOrGov}:redshift:${region}:${accountId}:cluster:${clusterIdentifier}`; if (cluster.PubliclyAccessible) { - helpers.addResult(results, 1, 'Redshift cluster is publicly accessible', region, clusterResource); + helpers.addResult(results, 1, 'Redshift cluster is publicly accessible', region, resource); } else { - helpers.addResult(results, 0, 'Redshift cluster is not publicly accessible', region, clusterResource); + helpers.addResult(results, 0, 'Redshift cluster is not publicly accessible', region, resource); } } diff --git a/plugins/aws/redshift/redshiftUnusedReservedNodes.js b/plugins/aws/redshift/redshiftUnusedReservedNodes.js index 74b9c8748d..da5309454b 100644 --- a/plugins/aws/redshift/redshiftUnusedReservedNodes.js +++ b/plugins/aws/redshift/redshiftUnusedReservedNodes.js @@ -9,13 +9,18 @@ module.exports = { more_info: 'Amazon Redshift reserved nodes must be utilized to avoid unnecessary billing.', link: 'https://docs.aws.amazon.com/redshift/latest/mgmt/purchase-reserved-node-instance.html', recommended_action: 'Provision new Redshift clusters matching the criteria of reserved nodes', - apis: ['Redshift:describeClusters', 'Redshift:describeReservedNodes'], + apis: ['Redshift:describeClusters', 'Redshift:describeReservedNodes', 'STS:getCallerIdentity'], run: function(cache, settings, callback) { var results = []; var source = {}; var regions = helpers.regions(settings); + var acctRegion = helpers.defaultRegion(settings); + var accountId = helpers.addSource(cache, source, + ['sts', 'getCallerIdentity', acctRegion, 'data']); + var awsOrGov = helpers.defaultPartition(settings); + async.each(regions.redshift, function(region, rcb){ var describeClusters = helpers.addSource(cache, source, ['redshift', 'describeClusters', region]); @@ -52,14 +57,15 @@ module.exports = { }); describeReservedNodes.data.forEach(node => { + var resource = `arn:${awsOrGov}:redshift:${region}:${accountId}:reserved-node:${node.ReservedNodeId}`; if (usedReservedNodes.includes(node.NodeType)) { helpers.addResult(results, 0, `Redshift reserved node "${node.ReservedNodeId}" is being used`, - region, node.ReservedNodeId); + region, resource); } else { helpers.addResult(results, 2, `Redshift reserved node "${node.ReservedNodeId}" is not being used`, - region, node.ReservedNodeId); + region, resource); } }); diff --git a/plugins/aws/s3/bucketPolicyCloudFrontOai.js b/plugins/aws/s3/bucketPolicyCloudFrontOai.js index a4bce3da35..5a32653497 100644 --- a/plugins/aws/s3/bucketPolicyCloudFrontOai.js +++ b/plugins/aws/s3/bucketPolicyCloudFrontOai.js @@ -50,10 +50,11 @@ module.exports = { distribution.Origins.Items.length) { for (let origin of distribution.Origins.Items) { - if (origin.S3OriginConfig) { + if (origin.S3OriginConfig && origin.DomainName) { s3OriginFound = true; - let bucketName = origin.DomainName.substring(0, origin.DomainName.indexOf('.s3.amazonaws.com')); - if (origin.S3OriginConfig.OriginAccessIdentity && + let bucketName = origin.DomainName.replace(/.s3.*.com/, ''); + if (bucketName && + origin.S3OriginConfig.OriginAccessIdentity && origin.S3OriginConfig.OriginAccessIdentity.length) { let oaiId = origin.S3OriginConfig.OriginAccessIdentity.substring(origin.S3OriginConfig.OriginAccessIdentity.lastIndexOf('/') + 1); diff --git a/plugins/aws/s3/versionedBucketsLC.js b/plugins/aws/s3/versionedBucketsLC.js index cc947a9136..e72735bcbd 100644 --- a/plugins/aws/s3/versionedBucketsLC.js +++ b/plugins/aws/s3/versionedBucketsLC.js @@ -32,11 +32,6 @@ module.exports = { return callback(null, results, source); } - var nonCurrentVersionRules = [ - 'NoncurrentVersionTransitions', - 'NoncurrentVersionExpiration' - ]; - listBuckets.data.forEach(function(bucket){ var bucketLocation = helpers.getS3BucketLocation(cache, region, bucket.Name); @@ -68,7 +63,8 @@ module.exports = { if (ruleExists) { var ruleForNonCurrent = getBucketLifecycleConfiguration.data.Rules.find(rule => rule.Status && rule.Status.toUpperCase() === 'ENABLED' && - Object.keys(rule).some(key => nonCurrentVersionRules.includes(key) && rule[key].length)); + Object.keys(rule).some(key => (key == 'NoncurrentVersionTransitions' && rule[key].length) || + key == 'NoncurrentVersionExpiration' && Object.keys(rule[key]).length)); if (ruleForNonCurrent) { helpers.addResult(results, 0, `S3 bucket ${bucket.Name} has versioning and lifecycle configuration enabled for non-current versions`, diff --git a/plugins/aws/ses/dkimEnabled.js b/plugins/aws/ses/dkimEnabled.js index 0ef852a038..37cd717c3d 100644 --- a/plugins/aws/ses/dkimEnabled.js +++ b/plugins/aws/ses/dkimEnabled.js @@ -9,13 +9,18 @@ module.exports = { more_info: 'DKIM is a security feature that allows recipients of an email to veriy that the sender domain has authorized the message and that it has not been spoofed.', recommended_action: 'Enable DKIM for all domains and addresses in all regions used to send email through SES.', link: 'http://docs.aws.amazon.com/ses/latest/DeveloperGuide/easy-dkim.html', - apis: ['SES:listIdentities', 'SES:getIdentityDkimAttributes'], + apis: ['SES:listIdentities', 'SES:getIdentityDkimAttributes', 'STS:getCallerIdentity'], run: function(cache, settings, callback) { var results = []; var source = {}; var regions = helpers.regions(settings); + var acctRegion = helpers.defaultRegion(settings); + var accountId = helpers.addSource(cache, source, + ['sts', 'getCallerIdentity', acctRegion, 'data']); + var awsOrGov = helpers.defaultPartition(settings); + async.each(regions.ses, function(region, rcb){ var listIdentities = helpers.addSource(cache, source, ['ses', 'listIdentities', region]); @@ -45,16 +50,17 @@ module.exports = { } for (var i in getIdentityDkimAttributes.data.DkimAttributes) { + var resource = `arn:${awsOrGov}:ses:${region}:${accountId}:identity/${i}`; var identity = getIdentityDkimAttributes.data.DkimAttributes[i]; if (!identity.DkimEnabled) { - helpers.addResult(results, 2, 'DKIM is not enabled', region, i); + helpers.addResult(results, 2, 'DKIM is not enabled', region, resource); } else if (identity.DkimVerificationStatus !== 'Success') { helpers.addResult(results, 1, - 'DKIM is enabled, but not configured properly', region, i); + 'DKIM is enabled, but not configured properly', region, resource); } else { helpers.addResult(results, 0, - 'DKIM is enabled and configured properly', region, i); + 'DKIM is enabled and configured properly', region, resource); } } diff --git a/plugins/azure/networksecuritygroups/openAllPorts.js b/plugins/azure/networksecuritygroups/openAllPorts.js index 2f4e3c8c7e..a53556db8e 100644 --- a/plugins/azure/networksecuritygroups/openAllPorts.js +++ b/plugins/azure/networksecuritygroups/openAllPorts.js @@ -45,7 +45,7 @@ module.exports = { let ports = { 'TCP': ['*'], - 'UCP': ['*'], + 'UDP': ['*'], '*' : ['*'] }; diff --git a/plugins/azure/sqlserver/tdeProtectorEncrypted.js b/plugins/azure/sqlserver/tdeProtectorEncrypted.js index 5d763db7ce..b7faede55c 100644 --- a/plugins/azure/sqlserver/tdeProtectorEncrypted.js +++ b/plugins/azure/sqlserver/tdeProtectorEncrypted.js @@ -48,7 +48,7 @@ module.exports = { encryptionProtectors.data.forEach(encryptionProtector => { if ((encryptionProtector.kind && encryptionProtector.kind.toLowerCase() != 'azurekeyvault') || - (encryptionProtector.serverKeyType || + (encryptionProtector.serverKeyType && encryptionProtector.serverKeyType.toLowerCase() != 'azurekeyvault') || !encryptionProtector.uri) { helpers.addResult(results, 2, diff --git a/plugins/google/kubernetes/privateClusterEnabled.js b/plugins/google/kubernetes/privateClusterEnabled.js index a88bee4c70..6b87ab168b 100644 --- a/plugins/google/kubernetes/privateClusterEnabled.js +++ b/plugins/google/kubernetes/privateClusterEnabled.js @@ -52,7 +52,9 @@ module.exports = { let resource = helpers.createResourceName('clusters', cluster.name, project, 'location', location); - if (cluster.privateCluster) { + if (cluster.privateClusterConfig && + cluster.privateClusterConfig.privateEndpoint && + cluster.privateClusterConfig.privateEndpoint.length) { helpers.addResult(results, 0, 'Private cluster is enabled on the Kubernetes cluster', region, resource); } else { helpers.addResult(results, 2, 'Private cluster is disabled on the Kubernetes cluster', region, resource); From bbb630adf4e7b5100605548713d724cb569fdc4a Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Wed, 1 Jun 2022 16:37:27 +0500 Subject: [PATCH 235/350] Update plugins/aws/iam/rolePolicyUnusedServices.js --- plugins/aws/iam/rolePolicyUnusedServices.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/iam/rolePolicyUnusedServices.js b/plugins/aws/iam/rolePolicyUnusedServices.js index 68d173d255..bd9d2b76e6 100644 --- a/plugins/aws/iam/rolePolicyUnusedServices.js +++ b/plugins/aws/iam/rolePolicyUnusedServices.js @@ -92,7 +92,7 @@ module.exports = { const allServices = { apigateway: ['stage', 'restapi', 'api'], cloudfront: ['distribution', 'streamingdistribution'], - cloudwatch: ['Alarm'], + cloudwatch: ['alarm'], dynamodb: ['table'], ec2: ['volume', 'host', 'eip', 'instance', 'networkinterface', 'securitygroup', 'natgateway', 'egressonlyinternetgateway', 'flowlog', 'transitgateway', 'vpcendpoint', 'vpcendpointservice', 'vpcpeeringconnection', 'registeredhainstance', 'launchtemplate', From 23dd4ae8beec2f560b0b240430902f14637d0b8d Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Wed, 1 Jun 2022 20:21:37 +0500 Subject: [PATCH 236/350] Added a new boolean setting to whitelist AWS AppConfig S3 buckets. --- helpers/aws/api.js | 14 +++++ helpers/aws/regions.js | 3 +- helpers/aws/regions_china.js | 3 +- helpers/aws/regions_gov.js | 3 +- plugins/aws/s3/bucketEncryption.js | 73 ++++++++++++++++++++++++- plugins/aws/s3/bucketEncryption.spec.js | 46 ++++++++++++++++ 6 files changed, 137 insertions(+), 5 deletions(-) diff --git a/helpers/aws/api.js b/helpers/aws/api.js index 7f49e7cc60..954d7a7cf9 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -27,6 +27,12 @@ var calls = { paginate: 'NextToken' } }, + AppConfig: { + listApplications: { + property: 'Items', + paginate: 'NextToken' + } + }, AppMesh: { listMeshes: { property: 'meshes', @@ -1111,6 +1117,14 @@ var postcalls = [ filterValue: 'id' } }, + AppConfig: { + listConfigurationProfiles: { + reliesOnService: 'appconfig', + reliesOnCall: 'listApplications', + filterKey: 'ApplicationId', + filterValue: 'Id' + } + }, AppMesh: { listVirtualGateways: { reliesOnService: 'appmesh', diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index 52d8f9f211..ea7b7c4c7d 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -193,5 +193,6 @@ module.exports = { appmesh: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1'], - frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'] + frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'], + appconfig: [...regions, ...newRegions] }; diff --git a/helpers/aws/regions_china.js b/helpers/aws/regions_china.js index 2a2b9af6de..83ce61cb54 100644 --- a/helpers/aws/regions_china.js +++ b/helpers/aws/regions_china.js @@ -116,5 +116,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + appconfig: regions }; diff --git a/helpers/aws/regions_gov.js b/helpers/aws/regions_gov.js index 1eaf28407b..3dd07b0dee 100644 --- a/helpers/aws/regions_gov.js +++ b/helpers/aws/regions_gov.js @@ -115,5 +115,6 @@ module.exports = { wisdom: regions, voiceid: regions, appmesh: regions, - frauddetector: regions + frauddetector: regions, + appconfig: regions }; diff --git a/plugins/aws/s3/bucketEncryption.js b/plugins/aws/s3/bucketEncryption.js index a710ad20da..a67c82f1ce 100644 --- a/plugins/aws/s3/bucketEncryption.js +++ b/plugins/aws/s3/bucketEncryption.js @@ -9,7 +9,8 @@ module.exports = { more_info: 'S3 object encryption provides fully-managed encryption of all objects uploaded to an S3 bucket.', recommended_action: 'Enable CMK KMS-based encryption for all S3 buckets.', link: 'https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-encryption.html', - apis: ['S3:listBuckets', 'S3:getBucketEncryption', 'KMS:listKeys', 'KMS:describeKey', 'KMS:listAliases', 'CloudFront:listDistributions', 'S3:getBucketWebsite', 'S3:getBucketLocation'], + apis: ['S3:listBuckets', 'S3:getBucketEncryption', 'KMS:listKeys', 'KMS:describeKey', + 'KMS:listAliases', 'CloudFront:listDistributions', 'AppConfig:listApplications', 'AppConfig:listConfigurationProfiles', 'S3:getBucketWebsite', 'S3:getBucketLocation', 'STS:getCallerIdentity'], remediation_description: 'The impacted bucket will be configured to use either AES-256 encryption, or CMK-based encryption if a KMS key ID is provided.', remediation_min_version: '202006020730', apis_remediate: ['S3:listBuckets', 'S3:getBucketEncryption', 'S3:getBucketLocation'], @@ -60,6 +61,12 @@ module.exports = { description: 'Allow buckets having static website enabled to skip encryption', regex: '^(true|false)$', default: 'false', + }, + whitelist_appconfig_s3_buckets: { + name: 'Whitelist AppConfig S3 Buckets', + description: 'When set to true, whitelists buckets which are source to AppConfig configuration profiles', + regex: '^(true|false)$', + default: 'false' } }, @@ -69,12 +76,15 @@ module.exports = { s3_encryption_allow_pattern: settings.s3_encryption_allow_pattern || this.settings.s3_encryption_allow_pattern.default, s3_encryption_kms_alias: settings.s3_encryption_kms_alias || this.settings.s3_encryption_kms_alias.default, s3_encryption_allow_cloudfront: settings.s3_encryption_allow_cloudfront || this.settings.s3_encryption_allow_cloudfront.default, - s3_allow_unencrypted_static_websites: settings.s3_allow_unencrypted_static_websites || this.settings.s3_allow_unencrypted_static_websites.default + s3_allow_unencrypted_static_websites: settings.s3_allow_unencrypted_static_websites || this.settings.s3_allow_unencrypted_static_websites.default, + whitelist_appconfig_s3_buckets: settings.whitelist_appconfig_s3_buckets || this.settings.whitelist_appconfig_s3_buckets.default }; config.s3_encryption_require_cmk = (config.s3_encryption_require_cmk == 'true'); config.s3_encryption_allow_cloudfront = (config.s3_encryption_allow_cloudfront == 'true'); config.s3_allow_unencrypted_static_websites = (config.s3_allow_unencrypted_static_websites == 'true'); + config.whitelist_appconfig_s3_buckets = (config.whitelist_appconfig_s3_buckets == 'true'); + var custom = helpers.isCustom(settings, this.settings); @@ -82,9 +92,14 @@ module.exports = { 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']); + var cloudfrontOrigins = []; var aliasKeyIds = []; var defaultKeyIds = []; + var appConfigBuckets = []; var defaultKeyDesc = 'Default master key that protects my S3 objects'; async.series([ @@ -191,6 +206,53 @@ module.exports = { cb(); }, + //Find Buckets available in AppConfig that are not whitelisted + function(cb){ + if (!config.whitelist_appconfig_s3_buckets) return cb(); + + async.each(regions.appconfig, function(region, rcb) { + var listApplications = helpers.addSource(cache, source, + ['appconfig', 'listApplications', region]); + + if (!listApplications) return rcb(); + + if (listApplications.err || !listApplications.data) { + helpers.addResult(results, 3, + 'Unable to query for AppConfig applications: ' + helpers.addError(listApplications), region); + return rcb(); + } + + if (listApplications.data.length) { + listApplications.data.forEach(function(application){ + if (!application.Id) return; + let resource = `arn:${awsOrGov}:appconfig:${region}:${accountId}:application/${application.Id}`; + + var listConfigurationProfiles = helpers.addSource(cache, source, + ['appconfig', 'listConfigurationProfiles', region, application.Id]); + + if (!listConfigurationProfiles || listConfigurationProfiles.err || + !listConfigurationProfiles.data || !listConfigurationProfiles.data.Items) { + helpers.addResult(results, 3, + `Unable to get configuration profiles description: ${helpers.addError(listConfigurationProfiles)}`, + region, resource); + } + + if (listConfigurationProfiles.data.Items.length) { + for (let config of listConfigurationProfiles.data.Items){ + if (config.LocationUri && config.LocationUri.startsWith('s3://')) { + let bucketName = config.LocationUri.split('/')[2]; + if (!appConfigBuckets.includes(bucketName)) appConfigBuckets.push(bucketName); + } + } + } + }); + } + + rcb(); + }, function(){ + cb(); + }); + }, // Check the S3 buckets for encryption function(cb) { var region = helpers.defaultRegion(settings); @@ -217,6 +279,12 @@ module.exports = { listBuckets.data.forEach(function(bucket){ let bucketResource = 'arn:aws:s3:::' + bucket.Name; var bucketLocation = helpers.getS3BucketLocation(cache, region, bucket.Name); + if (config.whitelist_appconfig_s3_buckets && appConfigBuckets.includes(bucket.Name)) { + helpers.addResult(results, 0, + 'Bucket is a source to AppConfig configuration profile', + bucketLocation, bucketResource); + return; + } if (allowRegex && allowRegex.test(bucket.Name)) { helpers.addResult(results, 0, @@ -417,3 +485,4 @@ module.exports = { }); } }; + diff --git a/plugins/aws/s3/bucketEncryption.spec.js b/plugins/aws/s3/bucketEncryption.spec.js index 9422daedc1..7dc028f2ee 100644 --- a/plugins/aws/s3/bucketEncryption.spec.js +++ b/plugins/aws/s3/bucketEncryption.spec.js @@ -144,6 +144,38 @@ const createCache = (cmk, bucketErr, sseAes, kms, cfMatching) => { ] } } + }, + "appconfig": { + "listApplications": { + "us-east-1": { + data: [ + { + "Id": "wt4b09t", + "Name": "appBucket" + } + ] + } + }, + "listConfigurationProfiles": { + "us-east-1": { + "wt4b09t": { + data: { + "Items": [ + { + "ApplicationId": "wt4b09t", + "Id": "nt17dsn", + "Name": "testConfig", + "LocationUri": "s3://bucket1/mine/AWSLogs/101363889637/Config/test", + "ValidatorTypes": [ + "LAMBDA" + ], + "Type": "AWS.Freeform" + } + ] + } + } + } + } } } }; @@ -178,6 +210,20 @@ describe('bucketEncryption', function () { s3.run(cache, {}, callback); }) + it('should give passing result if S3 bucket is a source to AppConfig configuration profile', 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('Bucket is a source to AppConfig configuration profile') + expect(results[0].region).to.equal('us-east-1'); + done() + }; + + const cache = createCache(false, false, true, false); + + s3.run(cache, { whitelist_appconfig_s3_buckets: 'true' }, callback); + }) + it('should give passing result if S3 bucket has AWS KMS encryption', function (done) { const callback = (err, results) => { expect(results.length).to.equal(1) From 21d91b1b6ebc0ddf001d7eaeafcf072bfb0d2259 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Wed, 1 Jun 2022 21:59:47 +0500 Subject: [PATCH 237/350] Update helpers/aws/regions.js --- helpers/aws/regions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index a19789b07e..a788275d3f 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -145,7 +145,8 @@ module.exports = { finspace: ['us-east-1', 'us-east-2', 'us-west-2', 'ca-central-1','eu-west-1'], codepipeline: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'eu-south-1', 'ap-northeast-1', - 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'sa-east-1'], + 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'ap-east-1', + 'sa-east-1'], codeartifact: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'eu-south-1', 'ap-northeast-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1'], From c4d055bda80f9939e75ac6dfbc4224d402cd912c Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Wed, 1 Jun 2022 22:00:29 +0500 Subject: [PATCH 238/350] Update helpers/aws/regions.js --- helpers/aws/regions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index a788275d3f..846491bf5b 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -177,7 +177,7 @@ module.exports = { 'ap-northeast-1', 'eu-central-1', 'eu-west-1'], location: [ 'us-east-1', 'us-east-2', 'us-west-2', 'eu-central-1', 'eu-west-1', 'eu-north-1', - 'ap-northeast-1', 'ap-southeast-1', 'ap-southeast-2' + 'ap-northeast-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1' ], lookoutvision: ['us-east-1', 'us-east-2', 'ap-northeast-1', 'ap-northeast-2', 'eu-central-1', 'eu-west-1', 'us-west-2'], lookoutmetrics: ['us-east-1', 'us-east-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'eu-central-1', From 4151dfbf75a8832345fcfc4ee2989db5d52c6e73 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Wed, 1 Jun 2022 22:07:01 +0500 Subject: [PATCH 239/350] Update helpers/aws/regions.js --- helpers/aws/regions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index a84e7db14a..e7c009530f 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -190,8 +190,8 @@ module.exports = { wisdom: ['us-east-1', 'us-west-2', 'eu-west-2', 'eu-central-1', 'ap-northeast-1', 'ap-southeast-2'], voiceid: ['us-east-1', 'us-west-2', 'eu-west-2', 'eu-central-1', 'ap-southeast-1', 'ap-northeast-1', 'ap-southeast-2'], appmesh: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', - 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', - 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1'], + 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'ap-northeast-1', 'ap-northeast-2', 'eu-south-1', + 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'ap-east-1', 'me-south-1', 'af-south-1'], frauddetector: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2'], appconfig: [...regions, ...newRegions] }; From 9099618f4eaf8177810bd4b905cf9ae07ac4a83e Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Wed, 1 Jun 2022 22:08:52 +0500 Subject: [PATCH 240/350] Update plugins/aws/s3/bucketEncryption.js --- plugins/aws/s3/bucketEncryption.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/aws/s3/bucketEncryption.js b/plugins/aws/s3/bucketEncryption.js index a67c82f1ce..c0b97a1309 100644 --- a/plugins/aws/s3/bucketEncryption.js +++ b/plugins/aws/s3/bucketEncryption.js @@ -206,7 +206,6 @@ module.exports = { cb(); }, - //Find Buckets available in AppConfig that are not whitelisted function(cb){ if (!config.whitelist_appconfig_s3_buckets) return cb(); From d06b8e0f92ff4b92b3ee824a370d8e8b3195086f Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Fri, 3 Jun 2022 21:45:53 +0500 Subject: [PATCH 241/350] Updated Alibaba RAM Inactive User Disabled date. --- plugins/alibaba/ram/inactiveUserDisabled.spec.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/alibaba/ram/inactiveUserDisabled.spec.js b/plugins/alibaba/ram/inactiveUserDisabled.spec.js index f4e628f6f7..0f05e23e0d 100644 --- a/plugins/alibaba/ram/inactiveUserDisabled.spec.js +++ b/plugins/alibaba/ram/inactiveUserDisabled.spec.js @@ -3,6 +3,8 @@ var helpers = require('../../../helpers/alibaba'); var inactiveUserDisabled = require('./inactiveUserDisabled') const currentDate = new Date(); +var failDate = new Date(); +failDate.setMonth(failDate.getMonth() - 4); const listUsers = [ { "UserName": "aqua", @@ -18,13 +20,13 @@ const getUserData = [ { "UserName": "aqua", "UserId": "214008820731498041", - "LastLoginDate": "2021-01-13T02:11:29Z", + "LastLoginDate": currentDate, "CreateDate": "2021-05-11T11:11:38Z", }, { "UserName": "cloudsploit", "UserId": "214008820731498041", - "LastLoginDate": "2021-05-13T02:11:29Z", + "LastLoginDate": failDate, "CreateDate": "2021-05-11T11:11:38Z", } ]; @@ -79,7 +81,7 @@ describe('inactiveUserDisabled', function () { inactiveUserDisabled.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include(`RAM user inactive for ${diffInDays} days is enabled`); + expect(results[0].message).to.include(`RAM user inactive for`); expect(results[0].region).to.equal('cn-hangzhou'); done(); }); @@ -91,7 +93,7 @@ describe('inactiveUserDisabled', function () { inactiveUserDisabled.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include(`RAM user inactive for ${diffInDays} days is not enabled`); + expect(results[0].message).to.include(`RAM user inactive for`); expect(results[0].region).to.equal('cn-hangzhou'); done(); }); From 644b4cb2ddd060acfe7dd147edc10070e875e1c8 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sun, 5 Jun 2022 23:39:37 +0500 Subject: [PATCH 242/350] GCP remove get projects api call --- collectors/google/collector.js | 15 +++++++++++++++ .../google/api/apiKeyApplicationRestriction.js | 2 +- plugins/google/api/apiKeyRotation.js | 2 +- plugins/google/clb/clbCDNEnabled.js | 2 +- plugins/google/clb/clbSecurityPolicyEnabled.js | 2 +- .../cloudfunctions/httpTriggerRequireHttps.js | 2 +- plugins/google/compute/VMDisksCMKEncrypted.js | 2 +- .../compute/applicationConsistentSnapshots.js | 2 +- plugins/google/compute/automaticRestartEnabled.js | 2 +- plugins/google/compute/autoscaleEnabled.js | 2 +- .../google/compute/autoscaleMinCpuUtilization.js | 2 +- .../google/compute/connectSerialPortsDisabled.js | 2 +- plugins/google/compute/csekEncryptionEnabled.js | 2 +- plugins/google/compute/deprecatedImages.js | 2 +- .../google/compute/diskAutomaticBackupEnabled.js | 2 +- plugins/google/compute/diskInUse.js | 2 +- plugins/google/compute/diskMultiAz.js | 2 +- plugins/google/compute/diskOldSnapshots.js | 2 +- plugins/google/compute/frequentlyUsedSnapshots.js | 2 +- .../google/compute/instanceDeletionProtection.js | 2 +- .../google/compute/instanceDesiredMachineTypes.js | 2 +- .../google/compute/instanceGroupAutoHealing.js | 2 +- plugins/google/compute/instanceLeastPrivilege.js | 2 +- plugins/google/compute/instanceLevelSSHOnly.js | 2 +- .../google/compute/instanceMaintenanceBehavior.js | 2 +- plugins/google/compute/instancePreemptibility.js | 2 +- plugins/google/compute/instancePublicAccess.js | 2 +- .../compute/instanceTemplateMachineTypes.js | 2 +- plugins/google/compute/instancesMultiAz.js | 2 +- plugins/google/compute/ipForwardingDisabled.js | 2 +- plugins/google/compute/osLogin2FAEnabled.js | 2 +- .../google/compute/persistentDisksAutoDelete.js | 2 +- plugins/google/compute/publicDiskImages.js | 2 +- plugins/google/compute/shieldedVmEnabled.js | 2 +- .../deploymentmanager/deleteExpiredDeployments.js | 2 +- plugins/google/dns/dnsSecEnabled.js | 2 +- plugins/google/dns/dnsSecSigningAlgorithm.js | 2 +- plugins/google/iam/kmsUserSeparation.js | 2 +- plugins/google/iam/memberAdmin.js | 2 +- plugins/google/iam/serviceAccountAdmin.js | 2 +- plugins/google/iam/serviceAccountSeparation.js | 2 +- plugins/google/iam/serviceAccountTokenCreator.js | 2 +- plugins/google/iam/serviceAccountUser.js | 2 +- plugins/google/kubernetes/aliasIpRangesEnabled.js | 2 +- .../google/kubernetes/autoNodeRepairEnabled.js | 2 +- .../google/kubernetes/autoNodeUpgradesEnabled.js | 2 +- .../kubernetes/basicAuthenticationDisabled.js | 2 +- plugins/google/kubernetes/clusterEncryption.js | 2 +- plugins/google/kubernetes/clusterLabelsAdded.js | 2 +- .../google/kubernetes/clusterLeastPrivilege.js | 2 +- plugins/google/kubernetes/cosImageEnabled.js | 2 +- .../google/kubernetes/defaultServiceAccount.js | 2 +- .../kubernetes/integrityMonitoringEnabled.js | 2 +- .../google/kubernetes/kubernetesAlphaDisabled.js | 2 +- .../kubernetes/legacyAuthorizationDisabled.js | 2 +- plugins/google/kubernetes/loggingEnabled.js | 2 +- .../google/kubernetes/masterAuthorizedNetwork.js | 2 +- plugins/google/kubernetes/monitoringEnabled.js | 2 +- plugins/google/kubernetes/networkPolicyEnabled.js | 2 +- plugins/google/kubernetes/nodeEncryption.js | 2 +- .../google/kubernetes/podSecurityPolicyEnabled.js | 2 +- .../google/kubernetes/privateClusterEnabled.js | 2 +- plugins/google/kubernetes/privateEndpoint.js | 2 +- plugins/google/kubernetes/secureBootEnabled.js | 2 +- plugins/google/kubernetes/shieldedNodes.js | 2 +- plugins/google/kubernetes/webDashboardDisabled.js | 2 +- plugins/google/logging/logSinksEnabled.js | 2 +- plugins/google/sql/anyHostRootAccess.js | 2 +- plugins/google/sql/dbAutomatedBackups.js | 2 +- plugins/google/sql/dbMultiAz.js | 2 +- plugins/google/sql/dbPubliclyAccessible.js | 2 +- plugins/google/sql/dbRestorable.js | 2 +- plugins/google/sql/dbSSLEnabled.js | 2 +- plugins/google/sql/mysqlLatestVersion.js | 2 +- plugins/google/sql/mysqlLocalInfile.js | 2 +- plugins/google/sql/mysqlSlowQueryLog.js | 2 +- plugins/google/sql/postgresqlLatestVersion.js | 2 +- plugins/google/sql/postgresqlLogCheckpoints.js | 2 +- plugins/google/sql/postgresqlLogConnections.js | 2 +- plugins/google/sql/postgresqlLogDisconnections.js | 2 +- plugins/google/sql/postgresqlLogLockWaits.js | 2 +- plugins/google/sql/postgresqlLogMinDuration.js | 2 +- plugins/google/sql/postgresqlLogMinError.js | 2 +- plugins/google/sql/postgresqlLogTempFiles.js | 2 +- plugins/google/sql/postgresqlMaxConnections.js | 2 +- plugins/google/sql/serverCertificateRotation.js | 2 +- plugins/google/sql/sqlCMKEncryption.js | 2 +- plugins/google/sql/sqlContainedDatabaseAuth.js | 2 +- plugins/google/sql/sqlCrossDbOwnership.js | 2 +- plugins/google/sql/sqlNoPublicIps.js | 2 +- plugins/google/sql/storageAutoIncreaseEnabled.js | 2 +- plugins/google/storage/bucketEncryption.js | 2 +- plugins/google/vpcnetwork/defaultVpcInUse.js | 2 +- plugins/google/vpcnetwork/dnsLoggingEnabled.js | 2 +- .../google/vpcnetwork/firewallLoggingMetadata.js | 2 +- plugins/google/vpcnetwork/flowLogsEnabled.js | 2 +- plugins/google/vpcnetwork/multipleSubnets.js | 2 +- plugins/google/vpcnetwork/openCIFS.js | 2 +- plugins/google/vpcnetwork/openCassandra.js | 2 +- plugins/google/vpcnetwork/openCustomPorts.js | 2 +- plugins/google/vpcnetwork/openDNS.js | 2 +- plugins/google/vpcnetwork/openDocker.js | 2 +- plugins/google/vpcnetwork/openFTP.js | 2 +- plugins/google/vpcnetwork/openHadoopNameNode.js | 2 +- .../google/vpcnetwork/openHadoopNameNodeWebUI.js | 2 +- plugins/google/vpcnetwork/openKibana.js | 2 +- plugins/google/vpcnetwork/openMongo.js | 2 +- plugins/google/vpcnetwork/openMsSQL.js | 2 +- plugins/google/vpcnetwork/openMySQL.js | 2 +- plugins/google/vpcnetwork/openNetBIOS.js | 2 +- plugins/google/vpcnetwork/openOracle.js | 2 +- .../vpcnetwork/openOracleAutoDataWarehouse.js | 2 +- plugins/google/vpcnetwork/openPostgreSQL.js | 2 +- plugins/google/vpcnetwork/openRDP.js | 2 +- plugins/google/vpcnetwork/openRPC.js | 2 +- plugins/google/vpcnetwork/openRedis.js | 2 +- plugins/google/vpcnetwork/openSMBoTCP.js | 2 +- plugins/google/vpcnetwork/openSMTP.js | 2 +- plugins/google/vpcnetwork/openSQLServer.js | 2 +- plugins/google/vpcnetwork/openSSH.js | 2 +- plugins/google/vpcnetwork/openSalt.js | 2 +- plugins/google/vpcnetwork/openTelnet.js | 2 +- plugins/google/vpcnetwork/openVNCClient.js | 2 +- plugins/google/vpcnetwork/openVNCServer.js | 2 +- plugins/google/vpcnetwork/privateAccessEnabled.js | 2 +- 125 files changed, 139 insertions(+), 124 deletions(-) diff --git a/collectors/google/collector.js b/collectors/google/collector.js index 8c967695e2..33b640fe22 100644 --- a/collectors/google/collector.js +++ b/collectors/google/collector.js @@ -478,6 +478,21 @@ var collect = function(GoogleConfig, settings, callback) { tertiaryCallCb(); }); }, function() { + if (collection && collection.projects && !collection.projects.get) { + collection.projects = { + ...collection.projects, + get: { + global: { + data: [ + { + kind: 'compute#project', + name: GoogleConfig.project + } + ] + } + } + }; + } callback(null, collection); }); }); diff --git a/plugins/google/api/apiKeyApplicationRestriction.js b/plugins/google/api/apiKeyApplicationRestriction.js index 174cf6d83b..d10c845409 100644 --- a/plugins/google/api/apiKeyApplicationRestriction.js +++ b/plugins/google/api/apiKeyApplicationRestriction.js @@ -8,7 +8,7 @@ module.exports = { more_info: 'To reduce the risk of attacks, Google Cloud API keys should be restricted only to trusted hosts, HTTP referrers, and Android/iOS mobile applications.', link: 'https://cloud.google.com/docs/authentication/api-keys#adding_application_restrictions', recommended_action: 'Ensure that Application restrictions are set for all Google Cloud API Keys.', - apis: ['apiKeys:list', 'projects:get'], + apis: ['apiKeys:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/api/apiKeyRotation.js b/plugins/google/api/apiKeyRotation.js index 09240720ba..ca4e9abafd 100644 --- a/plugins/google/api/apiKeyRotation.js +++ b/plugins/google/api/apiKeyRotation.js @@ -8,7 +8,7 @@ module.exports = { more_info: 'Make sure that your Google API Keys are regenerated regularly to avoid data leaks and unauthorized access through outdated API Keys.', link: 'https://cloud.google.com/docs/authentication/api-keys', recommended_action: 'Ensure that all your Google Cloud API keys are regenerated (rotated) after a specific period.', - apis: ['apiKeys:list', 'projects:get'], + apis: ['apiKeys:list'], settings: { api_keys_rotation_interval: { name: 'API Keys Rotation Interval', diff --git a/plugins/google/clb/clbCDNEnabled.js b/plugins/google/clb/clbCDNEnabled.js index 9528f81dc1..f761b67628 100644 --- a/plugins/google/clb/clbCDNEnabled.js +++ b/plugins/google/clb/clbCDNEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Cloud CDN increases speed and reliability as well as lowers server costs. Enabling CDN on load balancers creates a highly available system and is part of GCP best practices.', link: 'https://cloud.google.com/cdn/docs/quickstart', recommended_action: 'Enable Cloud CDN on all load balancers from the network services console.', - apis: ['backendServices:list', 'projects:get'], + apis: ['backendServices:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/clb/clbSecurityPolicyEnabled.js b/plugins/google/clb/clbSecurityPolicyEnabled.js index 9357d5e959..cea21ac246 100644 --- a/plugins/google/clb/clbSecurityPolicyEnabled.js +++ b/plugins/google/clb/clbSecurityPolicyEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Security policies on backend services control the traffic on the load balancer. This creates edge security and can deny or allow specified IP addresses.', link: 'https://cloud.google.com/armor/docs/security-policy-concepts', recommended_action: 'Ensure all load balancers have an attached Cloud Armor security policy.', - apis: ['backendServices:list', 'projects:get'], + apis: ['backendServices:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/cloudfunctions/httpTriggerRequireHttps.js b/plugins/google/cloudfunctions/httpTriggerRequireHttps.js index 14fabcff29..7dbab9d9c3 100644 --- a/plugins/google/cloudfunctions/httpTriggerRequireHttps.js +++ b/plugins/google/cloudfunctions/httpTriggerRequireHttps.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'You can make your google cloud functions call secure by making sure that they require HTTPS.', link: 'https://cloud.google.com/functions/docs/writing/http', recommended_action: 'Ensure that your Google Cloud functions always require HTTPS.', - apis: ['functions:list', 'projects:get'], + apis: ['functions:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/VMDisksCMKEncrypted.js b/plugins/google/compute/VMDisksCMKEncrypted.js index c5d639c102..84218e0901 100644 --- a/plugins/google/compute/VMDisksCMKEncrypted.js +++ b/plugins/google/compute/VMDisksCMKEncrypted.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Google encrypts all disks at rest by default. By using CMKs you can have better control over your disk encryption.', link: 'https://cloud.google.com/compute/docs/disks/customer-supplied-encryption', recommended_action: 'Ensure that your VM instances have CMK encryption enabled.', - apis: ['disks:list', 'projects:get', 'keyRings:list', 'cryptoKeys:list'], + apis: ['disks:list', 'keyRings:list', 'cryptoKeys:list'], settings: { disk_encryption_level: { name: 'Disk Encryption Protection Level', diff --git a/plugins/google/compute/applicationConsistentSnapshots.js b/plugins/google/compute/applicationConsistentSnapshots.js index 8bd24d9113..b3d4836692 100644 --- a/plugins/google/compute/applicationConsistentSnapshots.js +++ b/plugins/google/compute/applicationConsistentSnapshots.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Application consistent snapshots are more reliable because they are created after making sure that current operations are temporarily ceased and any data in memory is flushed to disk.', link: 'https://cloud.google.com/compute/docs/disks/snapshot-best-practices#prepare_for_consistency', recommended_action: 'Ensure that all disk snapshot schedules are application consistent.', - apis: ['resourcePolicies:list', 'projects:get'], + apis: ['resourcePolicies:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/automaticRestartEnabled.js b/plugins/google/compute/automaticRestartEnabled.js index 0ea3309d94..a43ecab552 100644 --- a/plugins/google/compute/automaticRestartEnabled.js +++ b/plugins/google/compute/automaticRestartEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Automatic Restart sets the virtual machine restart behavior when an instance is crashed or stopped by the system. If it is enabled, Google Cloud Compute Engine restarts the instance if it crashes or is stopped.', link: 'https://cloud.google.com/compute/docs/instances/setting-instance-scheduling-options#autorestart', recommended_action: 'Ensure automatic restart is enabled for all virtual machine instances.', - apis: ['instances:compute:list', 'projects:get'], + apis: ['instances:compute:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/autoscaleEnabled.js b/plugins/google/compute/autoscaleEnabled.js index c58b5ec088..7691b197f6 100644 --- a/plugins/google/compute/autoscaleEnabled.js +++ b/plugins/google/compute/autoscaleEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Enabling autoscale increases efficiency and improves cost management for resources.', link: 'https://cloud.google.com/compute/docs/autoscaler/', recommended_action: 'Ensure autoscaling is enabled for all instance groups.', - apis: ['instanceGroups:aggregatedList', 'autoscalers:aggregatedList','clusters:list', 'projects:get'], + apis: ['instanceGroups:aggregatedList', 'autoscalers:aggregatedList','clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/autoscaleMinCpuUtilization.js b/plugins/google/compute/autoscaleMinCpuUtilization.js index 0b6519a957..21bcf4eca6 100644 --- a/plugins/google/compute/autoscaleMinCpuUtilization.js +++ b/plugins/google/compute/autoscaleMinCpuUtilization.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'The autoscaler treats the target CPU utilization level as a fraction of the average use of all vCPUs over time in the instance group. If the average utilization of your total vCPUs exceeds the target utilization, the autoscaler adds more VM instances. If the average utilization of your total vCPUs is less than the target utilization, the autoscaler removes instances.', link: 'https://cloud.google.com/compute/docs/autoscaler/scaling-cpu', recommended_action: 'Ensure all instance groups have Minimum CPU Utilization greater than or equal to target value.', - apis: ['instanceGroups:aggregatedList', 'autoscalers:aggregatedList', 'clusters:list', 'projects:get'], + apis: ['instanceGroups:aggregatedList', 'autoscalers:aggregatedList', 'clusters:list'], settings: { minimum_cpu_utilization_target: { name: 'Autoscale Minimum CPU Utilization Target', diff --git a/plugins/google/compute/connectSerialPortsDisabled.js b/plugins/google/compute/connectSerialPortsDisabled.js index a9a3917d9f..45b6438103 100644 --- a/plugins/google/compute/connectSerialPortsDisabled.js +++ b/plugins/google/compute/connectSerialPortsDisabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'The serial console does not allow restricting IP Addresses, which allows any IP address to connect to instance and should therefore be disabled.', link: 'https://cloud.google.com/compute/docs/instances/interacting-with-serial-console', recommended_action: 'Ensure the Enable Connecting to Serial Ports option is disabled for all compute instances.', - apis: ['instances:compute:list', 'projects:get'], + apis: ['instances:compute:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/csekEncryptionEnabled.js b/plugins/google/compute/csekEncryptionEnabled.js index 820783b9ed..9326e141b2 100644 --- a/plugins/google/compute/csekEncryptionEnabled.js +++ b/plugins/google/compute/csekEncryptionEnabled.js @@ -8,7 +8,7 @@ module.exports = { more_info: 'Google encrypts all disks at rest by default. By using CSEK only the users with the key can access the disk. Anyone else, including Google, cannot access the disk data.', link: 'https://cloud.google.com/compute/docs/disks/customer-supplied-encryption', recommended_action: 'CSEK can only be configured when creating a disk. Delete the disk and redeploy with CSEK.', - apis: ['disks:aggregatedList', 'projects:get'], + apis: ['disks:aggregatedList'], compliance: { hipaa: 'HIPAA requires that all data is encrypted, including data at rest. ' + 'Enabling encryption of disk data helps to protect this data.', diff --git a/plugins/google/compute/deprecatedImages.js b/plugins/google/compute/deprecatedImages.js index 95d8ec7d16..00fcab7c11 100644 --- a/plugins/google/compute/deprecatedImages.js +++ b/plugins/google/compute/deprecatedImages.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Deprecated Compute Disk Images should not be used to create VM instances.', link: 'https://cloud.google.com/compute/docs/images/image-management-best-practices', recommended_action: 'Ensure that no compute instances are created from deprecated images.', - apis: ['instances:compute:list', 'disks:list', 'images:list', 'projects:get'], + apis: ['instances:compute:list', 'disks:list', 'images:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/diskAutomaticBackupEnabled.js b/plugins/google/compute/diskAutomaticBackupEnabled.js index 6702e64536..d514b1f78b 100644 --- a/plugins/google/compute/diskAutomaticBackupEnabled.js +++ b/plugins/google/compute/diskAutomaticBackupEnabled.js @@ -8,7 +8,7 @@ module.exports = { more_info: 'Having scheduled snapshots configured for your disks will periodically backup data from your persistent disks.', link: 'https://cloud.google.com/compute/docs/disks/scheduled-snapshots', recommended_action: 'Ensure that all compute disks have a snapshot schedule attached.', - apis: ['disks:aggregatedList', 'projects:get'], + apis: ['disks:aggregatedList'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/diskInUse.js b/plugins/google/compute/diskInUse.js index be5d5239eb..2cf5d7c75a 100644 --- a/plugins/google/compute/diskInUse.js +++ b/plugins/google/compute/diskInUse.js @@ -8,7 +8,7 @@ module.exports = { more_info: 'Unused Compute disks should be deleted to prevent accidental exposure of data and to avoid unnecessary billing.', link: 'https://cloud.google.com/compute/docs/disks', recommended_action: 'Delete unused Compute disks.', - apis: ['disks:aggregatedList', 'projects:get'], + apis: ['disks:aggregatedList'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/diskMultiAz.js b/plugins/google/compute/diskMultiAz.js index b851b6e7ea..c072ed8455 100644 --- a/plugins/google/compute/diskMultiAz.js +++ b/plugins/google/compute/diskMultiAz.js @@ -8,7 +8,7 @@ module.exports = { more_info: 'Enabling regional disk replication will allow you to force attach a regional persistent disk to another VM instance in a different zone in the same region in case of a zonal outage.', link: 'https://cloud.google.com/compute/docs/disks/high-availability-regional-persistent-disk', recommended_action: 'Ensure that all Google compute disks have replica zones configured.', - apis: ['disks:aggregatedList', 'projects:get'], + apis: ['disks:aggregatedList'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/diskOldSnapshots.js b/plugins/google/compute/diskOldSnapshots.js index d374ddd555..40280571e9 100644 --- a/plugins/google/compute/diskOldSnapshots.js +++ b/plugins/google/compute/diskOldSnapshots.js @@ -8,7 +8,7 @@ module.exports = { more_info: 'To optimize storage costs, make sure that there are no old disk snapshots in your GCP project.', link: 'https://cloud.google.com/compute/docs/disks/create-snapshots', recommended_action: 'Ensure that there are no snapshots older than specified number of days.', - apis: ['snapshots:list', 'projects:get'], + apis: ['snapshots:list'], settings: { compute_disk_snapshot_life: { name: 'Disk Snapshot Result Life', diff --git a/plugins/google/compute/frequentlyUsedSnapshots.js b/plugins/google/compute/frequentlyUsedSnapshots.js index 00f6af77eb..88a4fc2c50 100644 --- a/plugins/google/compute/frequentlyUsedSnapshots.js +++ b/plugins/google/compute/frequentlyUsedSnapshots.js @@ -8,7 +8,7 @@ module.exports = { more_info: 'If you are repeatedly using a snapshot in the same zone to create a persistent disk, save networking costs by using the snapshot once and creating an image of that snapshot. Store this image and use it to create your disk and start a VM instance.', link: 'https://cloud.google.com/compute/docs/disks/snapshot-best-practices#prepare_for_consistency', recommended_action: 'Ensure that your disk snapshots have images created from them.', - apis: ['snapshots:list', 'images:list', 'projects:get'], + apis: ['snapshots:list', 'images:list'], settings: { snapshots_to_check: { name: 'Snapshots to Check for Images', diff --git a/plugins/google/compute/instanceDeletionProtection.js b/plugins/google/compute/instanceDeletionProtection.js index 9db58e8f34..a2109ceafb 100644 --- a/plugins/google/compute/instanceDeletionProtection.js +++ b/plugins/google/compute/instanceDeletionProtection.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'VM instances should have deletion protection enabled in order to prevent them for being accidentally deleted.', link: 'https://cloud.google.com/compute/docs/instances/preventing-accidental-vm-deletion', recommended_action: 'Modify VM instances to enable deletion protection', - apis: ['instances:compute:list', 'projects:get'], + apis: ['instances:compute:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/instanceDesiredMachineTypes.js b/plugins/google/compute/instanceDesiredMachineTypes.js index a40c11f148..af7f6bc95c 100644 --- a/plugins/google/compute/instanceDesiredMachineTypes.js +++ b/plugins/google/compute/instanceDesiredMachineTypes.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Virtual Machine instance should be of the given types to ensure the internal compliance and prevent unexpected billing charges.', link: 'https://cloud.google.com/compute/docs/machine-types', recommended_action: 'Stop the Virtual Machine instance, change the machine type to the desired type and restart the instance.', - apis: ['instances:compute:list', 'projects:get'], + apis: ['instances:compute:list'], settings: { instance_desired_machine_types: { name: 'Instance Desired Machine Types', diff --git a/plugins/google/compute/instanceGroupAutoHealing.js b/plugins/google/compute/instanceGroupAutoHealing.js index 84656d899c..b34e10d4f8 100644 --- a/plugins/google/compute/instanceGroupAutoHealing.js +++ b/plugins/google/compute/instanceGroupAutoHealing.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'To improve the availability of your application, configure a health check to verify that the application is responding as expected.', link: 'https://cloud.google.com/compute/docs/instance-groups/autohealing-instances-in-migs', recommended_action: 'Ensure autohealing is enabled for all instance groups.', - apis: ['instanceGroupManagers:list', 'projects:get'], + apis: ['instanceGroupManagers:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/instanceLeastPrivilege.js b/plugins/google/compute/instanceLeastPrivilege.js index b35f7cffdd..4c92c9a3b0 100644 --- a/plugins/google/compute/instanceLeastPrivilege.js +++ b/plugins/google/compute/instanceLeastPrivilege.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'To support the principle of least privilege and prevent potential privilege escalation, it is recommended that instances are not assigned to the default service account, Compute Engine default service account with a scope allowing full access to all cloud APIs.', link: 'https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances', recommended_action: 'For all instances, if the default service account is used, ensure full access to all cloud APIs is not configured.', - apis: ['instances:compute:list', 'projects:get'], + apis: ['instances:compute:list'], compliance: { pci: 'PCI has explicit requirements around default accounts and ' + 'resources. PCI recommends removing all default accounts, ' + diff --git a/plugins/google/compute/instanceLevelSSHOnly.js b/plugins/google/compute/instanceLevelSSHOnly.js index d2dd01937a..8649117e3c 100644 --- a/plugins/google/compute/instanceLevelSSHOnly.js +++ b/plugins/google/compute/instanceLevelSSHOnly.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'To support the principle of least privilege and prevent potential privilege escalation it is recommended that instances are not give access to project-wide SSH keys through instance metadata.', link: 'https://cloud.google.com/compute/docs/instances/adding-removing-ssh-keys', recommended_action: 'Ensure project-wide SSH keys are blocked for all instances.', - apis: ['instances:compute:list', 'projects:get'], + apis: ['instances:compute:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/instanceMaintenanceBehavior.js b/plugins/google/compute/instanceMaintenanceBehavior.js index 58acaea73a..79ff8eb405 100644 --- a/plugins/google/compute/instanceMaintenanceBehavior.js +++ b/plugins/google/compute/instanceMaintenanceBehavior.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'When Google Compute Engine performs regular maintenance of its infrastructure, it migrates your VM instances to other hardware if you have configured the availability policy for the instance to use live migration. This prevents your applications from experiencing disruptions during these events.', link: 'https://cloud.google.com/compute/docs/instances/setting-instance-scheduling-options', recommended_action: 'Ensure that your Google Compute Engine VM instances are configured to use live migration.', - apis: ['instances:compute:list', 'projects:get'], + apis: ['instances:compute:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/instancePreemptibility.js b/plugins/google/compute/instancePreemptibility.js index dad51e5b64..6dd6d318c9 100644 --- a/plugins/google/compute/instancePreemptibility.js +++ b/plugins/google/compute/instancePreemptibility.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Preemptible instances are excess Compute Engine capacity, so their availability varies with usage. Compute Engine can terminate preemptible instances if it requires access to these resources for other tasks.', link: 'https://cloud.google.com/compute/docs/instances/preemptible', recommended_action: 'Ensure that your Google Compute Engine VM instances are not preemptible.', - apis: ['instances:compute:list', 'projects:get'], + apis: ['instances:compute:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/instancePublicAccess.js b/plugins/google/compute/instancePublicAccess.js index 62d5adde76..f6d9faf324 100644 --- a/plugins/google/compute/instancePublicAccess.js +++ b/plugins/google/compute/instancePublicAccess.js @@ -10,7 +10,7 @@ module.exports = { 'in order to minimize the instance\'s exposure to the internet.', link: 'https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address', recommended_action: 'Modify compute instances and set External IP to None for network interface', - apis: ['instances:compute:list', 'projects:get'], + apis: ['instances:compute:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/instanceTemplateMachineTypes.js b/plugins/google/compute/instanceTemplateMachineTypes.js index 4fdf09d92d..9f84e6e7c1 100644 --- a/plugins/google/compute/instanceTemplateMachineTypes.js +++ b/plugins/google/compute/instanceTemplateMachineTypes.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Virtual Machine instance templates should be of the given types to ensure the internal compliance and prevent unexpected billing charges.', link: 'https://cloud.google.com/compute/docs/machine-types', recommended_action: 'Ensure that Virtual Machine instance templates are not using undesired machine types.', - apis: ['instanceTemplates:list', 'projects:get'], + apis: ['instanceTemplates:list'], settings: { instance_template_machine_types: { name: 'Instance Template Machine Types', diff --git a/plugins/google/compute/instancesMultiAz.js b/plugins/google/compute/instancesMultiAz.js index 6a779cb00a..b8e11abdf8 100644 --- a/plugins/google/compute/instancesMultiAz.js +++ b/plugins/google/compute/instancesMultiAz.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Creating instances in a single zone creates a single point of failure for all systems in the VPC. All managed instances should be created as Regional to ensure proper failover.', link: 'https://cloud.google.com/vpc/docs/vpc', recommended_action: 'Launch new instances as regional instance groups.', - apis: ['instanceGroups:aggregatedList', 'instances:compute:list', 'projects:get'], + apis: ['instanceGroups:aggregatedList', 'instances:compute:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/ipForwardingDisabled.js b/plugins/google/compute/ipForwardingDisabled.js index 52666c8b2b..f574b3e31b 100644 --- a/plugins/google/compute/ipForwardingDisabled.js +++ b/plugins/google/compute/ipForwardingDisabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Disabling IP forwarding ensures that the instance only sends and receives packets with matching destination or source IPs.', link: 'https://cloud.google.com/vpc/docs/using-routes', recommended_action: 'IP forwarding settings can only be chosen when creating a new instance. Delete the affected instances and redeploy with IP forwarding disabled.', - apis: ['instances:compute:list', 'projects:get'], + apis: ['instances:compute:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/osLogin2FAEnabled.js b/plugins/google/compute/osLogin2FAEnabled.js index 3e21e89ce5..bb6f94ba2d 100644 --- a/plugins/google/compute/osLogin2FAEnabled.js +++ b/plugins/google/compute/osLogin2FAEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Enable OS login Two-Factor Authentication (2FA) to add an additional security layer to your VM instances. The risk of your VM instances getting attcked is reduced significantly if 2FA is enabled.', link: 'https://cloud.google.com/compute/docs/oslogin/setup-two-factor-authentication', recommended_action: 'Set enable-oslogin-2fa to true in custom metadata for the instance.', - apis: ['instances:compute:list', 'projects:get'], + apis: ['instances:compute:list'], compliance: { pci: 'PCI recommends implementing additional security features for ' + 'any required service. This includes using secured technologies ' + diff --git a/plugins/google/compute/persistentDisksAutoDelete.js b/plugins/google/compute/persistentDisksAutoDelete.js index eda2fb605d..08579a4209 100644 --- a/plugins/google/compute/persistentDisksAutoDelete.js +++ b/plugins/google/compute/persistentDisksAutoDelete.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'When auto-delete is enabled, the attached persistent disk are deleted with VM instance deletion. In cloud environments, you might want to keep the attached persistent disks even when the associated VM instance is deleted.', link: 'https://cloud.google.com/compute/docs/disks', recommended_action: 'Ensure that auto-delete is disabled for all disks associated with your VM instances.', - apis: ['disks:list', 'instances:compute:list', 'projects:get'], + apis: ['disks:list', 'instances:compute:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/publicDiskImages.js b/plugins/google/compute/publicDiskImages.js index 5c80e55790..37b81825e7 100644 --- a/plugins/google/compute/publicDiskImages.js +++ b/plugins/google/compute/publicDiskImages.js @@ -8,7 +8,7 @@ module.exports = { more_info: 'To avoid exposing sensitive information, make sure that your virtual machine disk images are not being publicly shared with all other GCP accounts.', link: 'https://cloud.google.com/compute/docs/images', recommended_action: 'Ensure that your VM disk images are not accessible by allUsers or allAuthenticatedUsers.', - apis: ['images:list', 'images:getIamPolicy', 'projects:get'], + apis: ['images:list', 'images:getIamPolicy'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/compute/shieldedVmEnabled.js b/plugins/google/compute/shieldedVmEnabled.js index 2a5f391c29..cc094f432d 100644 --- a/plugins/google/compute/shieldedVmEnabled.js +++ b/plugins/google/compute/shieldedVmEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Shielded VM option should be configured to defend against the security attacks on the instances.', link: 'https://cloud.google.com/security/shielded-cloud/shielded-vm', recommended_action: 'Enable the shielded VM for all the instances for security reasons.', - apis: ['instances:compute:list', 'projects:get'], + apis: ['instances:compute:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/deploymentmanager/deleteExpiredDeployments.js b/plugins/google/deploymentmanager/deleteExpiredDeployments.js index 7e1a94de4a..8b1105fdce 100644 --- a/plugins/google/deploymentmanager/deleteExpiredDeployments.js +++ b/plugins/google/deploymentmanager/deleteExpiredDeployments.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Cloud Deployment Manager deployments should be deleted after desired time period from their creation time as determined by your governance rules.', link: 'https://cloud.google.com/deployment-manager/docs/deployments/deleting-deployments', recommended_action: 'Delete expired deoplyments from Deployment Manager', - apis: ['deployments:list', 'projects:get'], + apis: ['deployments:list'], settings: { deployments_expiration_time: { name: 'Deployments Expiration Time', diff --git a/plugins/google/dns/dnsSecEnabled.js b/plugins/google/dns/dnsSecEnabled.js index 5ec70b002c..cdf4549a01 100644 --- a/plugins/google/dns/dnsSecEnabled.js +++ b/plugins/google/dns/dnsSecEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'DNS Security is a feature that authenticates all responses to domain name lookups. This prevents attackers from committing DNS hijacking or man in the middle attacks.', link: 'https://cloud.google.com/dns/docs/dnssec', recommended_action: 'Ensure DNSSEC is enabled for all managed zones in the cloud DNS service.', - apis: ['managedZones:list', 'projects:get'], + apis: ['managedZones:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/dns/dnsSecSigningAlgorithm.js b/plugins/google/dns/dnsSecSigningAlgorithm.js index 7de9fa9e69..f0d6debcfa 100644 --- a/plugins/google/dns/dnsSecSigningAlgorithm.js +++ b/plugins/google/dns/dnsSecSigningAlgorithm.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'DNS Security is a feature that authenticates all responses to domain name lookups. This prevents attackers from committing DNS hijacking or man in the middle attacks.', link: 'https://cloud.google.com/dns/docs/dnssec', recommended_action: 'Ensure that all managed zones using DNSSEC are not using the RSASHA1 algorithm for key or zone signing.', - apis: ['managedZones:list', 'projects:get'], + apis: ['managedZones:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/iam/kmsUserSeparation.js b/plugins/google/iam/kmsUserSeparation.js index a11a8b50ff..241c72433c 100644 --- a/plugins/google/iam/kmsUserSeparation.js +++ b/plugins/google/iam/kmsUserSeparation.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Ensuring that no users have the KMS admin role and any one of the CryptoKey roles follows separation of duties, where no user should have access to resources out of the scope of duty.', link: 'https://cloud.google.com/iam/docs/overview', recommended_action: 'Ensure that no service accounts have both the KMS admin role and any of CryptoKey roles attached.', - apis: ['projects:getIamPolicy', 'projects:get'], + apis: ['projects:getIamPolicy'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/iam/memberAdmin.js b/plugins/google/iam/memberAdmin.js index f16f7e901c..b0b9f19176 100644 --- a/plugins/google/iam/memberAdmin.js +++ b/plugins/google/iam/memberAdmin.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'For best security practices, use only predefined IAM roles and do not use primitive roles to prevent any unauthorized access to your resources.', link: 'https://cloud.google.com/iam/docs/overview', recommended_action: 'Ensure that no IAM member has a primitive role.', - apis: ['projects:getIamPolicy', 'projects:get'], + apis: ['projects:getIamPolicy'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/iam/serviceAccountAdmin.js b/plugins/google/iam/serviceAccountAdmin.js index e8a6b1845d..7fee25e4b6 100644 --- a/plugins/google/iam/serviceAccountAdmin.js +++ b/plugins/google/iam/serviceAccountAdmin.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Service accounts are primarily used for API access to Google. It is recommended to not use admin access for service accounts.', link: 'https://cloud.google.com/iam/docs/overview', recommended_action: 'Ensure that no service accounts have admin, owner, or write privileges.', - apis: ['projects:get','projects:getIamPolicy'], + apis: ['projects:getIamPolicy'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/iam/serviceAccountSeparation.js b/plugins/google/iam/serviceAccountSeparation.js index 260fa435b5..9c0ae54d3c 100644 --- a/plugins/google/iam/serviceAccountSeparation.js +++ b/plugins/google/iam/serviceAccountSeparation.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Ensuring that no users have both roles follows separation of duties, where no user should have access to resources out of the scope of duty.', link: 'https://cloud.google.com/iam/docs/overview', recommended_action: 'Ensure that no service accounts have both the Service Account User and Service Account Admin role attached.', - apis: ['projects:getIamPolicy', 'projects:get'], + apis: ['projects:getIamPolicy'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/iam/serviceAccountTokenCreator.js b/plugins/google/iam/serviceAccountTokenCreator.js index eb8102cdaf..aae92db3cf 100644 --- a/plugins/google/iam/serviceAccountTokenCreator.js +++ b/plugins/google/iam/serviceAccountTokenCreator.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'For best security practices, IAM users should not have Service Account Token Creator role.', link: 'https://cloud.google.com/iam/docs/overview', recommended_action: 'Ensure that no IAM user have Service Account Token Creator Role at GCP project level.', - apis: ['projects:getIamPolicy', 'projects:get'], + apis: ['projects:getIamPolicy'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/iam/serviceAccountUser.js b/plugins/google/iam/serviceAccountUser.js index de3d33fa44..006933f866 100644 --- a/plugins/google/iam/serviceAccountUser.js +++ b/plugins/google/iam/serviceAccountUser.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'The Service Account User role gives users the access to all service accounts of a project. This can result in an elevation of privileges and is not recommended.', link: 'https://cloud.google.com/iam/docs/overview', recommended_action: 'Ensure that no service accounts have the Service Account User role attached.', - apis: ['projects:getIamPolicy', 'projects:get'], + apis: ['projects:getIamPolicy'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/aliasIpRangesEnabled.js b/plugins/google/kubernetes/aliasIpRangesEnabled.js index 3a47e01bee..2f73c441c7 100644 --- a/plugins/google/kubernetes/aliasIpRangesEnabled.js +++ b/plugins/google/kubernetes/aliasIpRangesEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Alias IP ranges allow users to assign ranges of internal IP addresses as alias to a network interface.', link: 'https://cloud.google.com/monitoring/kubernetes-engine/', recommended_action: 'Ensure that Kubernetes clusters have alias IP ranges enabled.', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/autoNodeRepairEnabled.js b/plugins/google/kubernetes/autoNodeRepairEnabled.js index e3b87d2f18..f8dacbb366 100644 --- a/plugins/google/kubernetes/autoNodeRepairEnabled.js +++ b/plugins/google/kubernetes/autoNodeRepairEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'When automatic repair on nodes is enabled, the Kubernetes engine performs health checks on all nodes, automatically repairing nodes that fail health checks. This ensures that the Kubernetes environment stays optimal.', link: 'https://cloud.google.com/kubernetes-engine/docs/how-to/node-auto-repair', recommended_action: 'Ensure that automatic node repair is enabled on all node pools in Kubernetes clusters', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/autoNodeUpgradesEnabled.js b/plugins/google/kubernetes/autoNodeUpgradesEnabled.js index 8fa2387a71..bf02554388 100644 --- a/plugins/google/kubernetes/autoNodeUpgradesEnabled.js +++ b/plugins/google/kubernetes/autoNodeUpgradesEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Enabling automatic upgrades on nodes ensures that each node stays current with the latest version of the master branch, also ensuring that the latest security patches are installed to provide the most secure environment.', link: 'https://cloud.google.com/kubernetes-engine/docs/how-to/node-auto-upgrades', recommended_action: 'Ensure that automatic node upgrades are enabled on all node pools in Kubernetes clusters', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/basicAuthenticationDisabled.js b/plugins/google/kubernetes/basicAuthenticationDisabled.js index a822a2003e..3586a4d23b 100644 --- a/plugins/google/kubernetes/basicAuthenticationDisabled.js +++ b/plugins/google/kubernetes/basicAuthenticationDisabled.js @@ -10,7 +10,7 @@ module.exports = { 'the recommended method to authenticate into the Kubernetes API server.', link: 'https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster', recommended_action: 'Disable basic authentication on all clusters', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/clusterEncryption.js b/plugins/google/kubernetes/clusterEncryption.js index d5b336b72f..20ef7bb522 100644 --- a/plugins/google/kubernetes/clusterEncryption.js +++ b/plugins/google/kubernetes/clusterEncryption.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Application-layer secrets encryption adds additional security layer to sensitive data such as Kubernetes secrets stored in etcd.', link: 'https://cloud.google.com/kubernetes-engine/docs/how-to/encrypting-secrets', recommended_action: 'Ensure that all GKE clusters have the desired application-layer secrets encryption level.', - apis: ['clusters:list', 'projects:get', 'keyRings:list', 'cryptoKeys:list'], + apis: ['clusters:list', 'keyRings:list', 'cryptoKeys:list'], settings: { kubernetes_cluster_encryption_level: { name: 'Kubernetes Cluster Encryption Protection Level', diff --git a/plugins/google/kubernetes/clusterLabelsAdded.js b/plugins/google/kubernetes/clusterLabelsAdded.js index 05aacd2180..8c3c0bf94e 100644 --- a/plugins/google/kubernetes/clusterLabelsAdded.js +++ b/plugins/google/kubernetes/clusterLabelsAdded.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'It is recommended to add labels to Kubernetes clusters to apply specific security settings and auto configure objects at creation.', link: 'https://cloud.google.com/kubernetes-engine/docs/how-to/creating-managing-labels', recommended_action: 'Ensure labels are added to Kubernetes clusters', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/clusterLeastPrivilege.js b/plugins/google/kubernetes/clusterLeastPrivilege.js index cd8937093d..ba3a8596b4 100644 --- a/plugins/google/kubernetes/clusterLeastPrivilege.js +++ b/plugins/google/kubernetes/clusterLeastPrivilege.js @@ -10,7 +10,7 @@ module.exports = { 'Kubernetes default service account should be limited to minimal access scopes necessary to operate the clusters.', link: 'https://cloud.google.com/compute/docs/access/service-accounts', recommended_action: 'Ensure that all Kubernetes clusters are created with minimal access scope.', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/cosImageEnabled.js b/plugins/google/kubernetes/cosImageEnabled.js index 84b138e3cf..ae528aae8f 100644 --- a/plugins/google/kubernetes/cosImageEnabled.js +++ b/plugins/google/kubernetes/cosImageEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Container-Optimized OS is optimized to enhance node security. It is backed by a team at Google that can quickly patch it.', link: 'https://cloud.google.com/container-optimized-os/', recommended_action: 'Enable Container-Optimized OS on all Kubernetes cluster nodes', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/defaultServiceAccount.js b/plugins/google/kubernetes/defaultServiceAccount.js index 1c51ee9539..433da6669c 100644 --- a/plugins/google/kubernetes/defaultServiceAccount.js +++ b/plugins/google/kubernetes/defaultServiceAccount.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Kubernetes cluster nodes should use customized service accounts that have minimal privileges to run. This reduces the attack surface in the case of a malicious attack on the cluster.', link: 'https://cloud.google.com/container-optimized-os/', recommended_action: 'Ensure that no Kubernetes cluster nodes are using the default service account', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/integrityMonitoringEnabled.js b/plugins/google/kubernetes/integrityMonitoringEnabled.js index 800c1c83a7..c80b81cd36 100644 --- a/plugins/google/kubernetes/integrityMonitoringEnabled.js +++ b/plugins/google/kubernetes/integrityMonitoringEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Integrity Monitoring feature automatically monitors the integrity of your cluster nodes.', link: 'https://cloud.google.com/kubernetes-engine/docs/how-to/shielded-gke-nodes#integrity_monitoring', recommended_action: 'Enable Integrity Monitoring feature for your cluster nodes', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/kubernetesAlphaDisabled.js b/plugins/google/kubernetes/kubernetesAlphaDisabled.js index c6d0ebda36..e76457a7d5 100644 --- a/plugins/google/kubernetes/kubernetesAlphaDisabled.js +++ b/plugins/google/kubernetes/kubernetesAlphaDisabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'It is recommended to not use Alpha clusters as they expire after thirty days and do not receive security updates.', link: 'https://cloud.google.com/kubernetes-engine/docs/concepts/alpha-clusters', recommended_action: '1. Create a new cluster with the alpha feature disabled. 2. Migrate all required cluster data from the cluster with alpha to this newly created cluster. 3.Delete the engine cluster with alpha enabled.', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/legacyAuthorizationDisabled.js b/plugins/google/kubernetes/legacyAuthorizationDisabled.js index 226fcb470c..8efd95f0a3 100644 --- a/plugins/google/kubernetes/legacyAuthorizationDisabled.js +++ b/plugins/google/kubernetes/legacyAuthorizationDisabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'The legacy authorizer in Kubernetes grants broad, statically defined permissions.', link: 'https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster', recommended_action: 'Disable legacy authorization on all clusters.', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/loggingEnabled.js b/plugins/google/kubernetes/loggingEnabled.js index 611f1ba194..ab78513709 100644 --- a/plugins/google/kubernetes/loggingEnabled.js +++ b/plugins/google/kubernetes/loggingEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'This setting should be enabled to ensure Kubernetes control plane logs are properly recorded.', link: 'https://cloud.google.com/monitoring/kubernetes-engine/legacy-stackdriver/logging', recommended_action: 'Ensure that logging is enabled on all Kubernetes clusters.', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], compliance: { hipaa: 'HIPAA requires the logging of all activity ' + 'including access and all actions taken.' diff --git a/plugins/google/kubernetes/masterAuthorizedNetwork.js b/plugins/google/kubernetes/masterAuthorizedNetwork.js index 7f68b0d1b7..723225f5f6 100644 --- a/plugins/google/kubernetes/masterAuthorizedNetwork.js +++ b/plugins/google/kubernetes/masterAuthorizedNetwork.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Authorized networks are a way of specifying a restricted range of IP addresses that are permitted to access your container clusters Kubernetes master endpoint.', link: 'https://cloud.google.com/kubernetes-engine/docs/how-to/authorized-networks', recommended_action: 'Enable master authorized networks on all clusters.', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/monitoringEnabled.js b/plugins/google/kubernetes/monitoringEnabled.js index 7aaa0bfd41..b5bfb574b5 100644 --- a/plugins/google/kubernetes/monitoringEnabled.js +++ b/plugins/google/kubernetes/monitoringEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Kubernetes supports monitoring through Stackdriver.', link: 'https://cloud.google.com/monitoring/kubernetes-engine/', recommended_action: 'Ensure monitoring is enabled on all Kubernetes clusters.', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/networkPolicyEnabled.js b/plugins/google/kubernetes/networkPolicyEnabled.js index 6f50167764..70999a64ef 100644 --- a/plugins/google/kubernetes/networkPolicyEnabled.js +++ b/plugins/google/kubernetes/networkPolicyEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Kubernetes network policy creates isolation between cluster pods, this creates a more secure environment with only specified connections allowed.', link: 'https://cloud.google.com/kubernetes-engine/docs/how-to/network-policy', recommended_action: 'Enable network policy on all Kubernetes clusters.', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/nodeEncryption.js b/plugins/google/kubernetes/nodeEncryption.js index e85fef5688..a4e7c2067f 100644 --- a/plugins/google/kubernetes/nodeEncryption.js +++ b/plugins/google/kubernetes/nodeEncryption.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Using Customer Managed Keys (CMKs) gives you better control over the encryption/decryption process of your cluster nodes.', link: 'https://cloud.google.com/security/encryption/default-encryption', recommended_action: 'Ensure that all node pools in GKE clusters have the desired encryption level.', - apis: ['clusters:list', 'projects:get', 'keyRings:list', 'cryptoKeys:list'], + apis: ['clusters:list', 'keyRings:list', 'cryptoKeys:list'], settings: { kubernetes_node_encryption_level: { name: 'Kubernetes Node Encryption Protection Level', diff --git a/plugins/google/kubernetes/podSecurityPolicyEnabled.js b/plugins/google/kubernetes/podSecurityPolicyEnabled.js index d65d182ff0..2220414cb2 100644 --- a/plugins/google/kubernetes/podSecurityPolicyEnabled.js +++ b/plugins/google/kubernetes/podSecurityPolicyEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Kubernetes pod security policy is a resource that controls security sensitive aspects of the pod configuration.', link: 'https://cloud.google.com/kubernetes-engine/docs/how-to/pod-security-policies', recommended_action: 'Ensure that all Kubernetes clusters have pod security policy enabled.', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/privateClusterEnabled.js b/plugins/google/kubernetes/privateClusterEnabled.js index 6b87ab168b..649f36c27a 100644 --- a/plugins/google/kubernetes/privateClusterEnabled.js +++ b/plugins/google/kubernetes/privateClusterEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Kubernetes private clusters only have internal ip ranges, which ensures that their workloads are isolated from the public internet.', link: 'https://cloud.google.com/kubernetes-engine/docs/how-to/private-clusters', recommended_action: 'Ensure that all Kubernetes clusters have private cluster enabled.', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/privateEndpoint.js b/plugins/google/kubernetes/privateEndpoint.js index 078aeda67e..782a4e4dc0 100644 --- a/plugins/google/kubernetes/privateEndpoint.js +++ b/plugins/google/kubernetes/privateEndpoint.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'kubernetes private endpoints can be used to route all traffic between the Kubernetes worker and control plane nodes over a private VPC endpoint rather than across the public internet.', link: 'https://cloud.google.com/kubernetes-engine/docs/how-to/private-clusters', recommended_action: 'Enable the private endpoint setting for all GKE clusters when creating the cluster.', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/secureBootEnabled.js b/plugins/google/kubernetes/secureBootEnabled.js index c753282f7b..478908ed55 100644 --- a/plugins/google/kubernetes/secureBootEnabled.js +++ b/plugins/google/kubernetes/secureBootEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Secure Boot feature protects your cluster nodes from malware and makes sure the system runs only authentic software.', link: 'https://cloud.google.com/kubernetes-engine/docs/how-to/shielded-gke-nodes#secure_boot', recommended_action: 'Ensure that Secure Boot feature is enabled for all node pools in your GKE clusters.', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/shieldedNodes.js b/plugins/google/kubernetes/shieldedNodes.js index 4dfb91259c..dc60939c5b 100644 --- a/plugins/google/kubernetes/shieldedNodes.js +++ b/plugins/google/kubernetes/shieldedNodes.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Shielded GKE nodes give strong cryptographic identity. This prevents attackers from being able to impersonate a node in your GKE cluster even if the attacker can extract the node credentials.', link: 'https://cloud.google.com/kubernetes-engine/docs/how-to/shielded-gke-nodes', recommended_action: 'Ensure that shielded nodes setting is enabled in your GKE cluster', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/kubernetes/webDashboardDisabled.js b/plugins/google/kubernetes/webDashboardDisabled.js index 9b141ced1a..87c3500510 100644 --- a/plugins/google/kubernetes/webDashboardDisabled.js +++ b/plugins/google/kubernetes/webDashboardDisabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'It is recommended to disable the web dashboard because it is backed by a highly privileged service account.', link: 'https://cloud.google.com/kubernetes-engine/docs/concepts/dashboards', recommended_action: 'Ensure that no Kubernetes clusters have the web dashboard enabled', - apis: ['clusters:list', 'projects:get'], + apis: ['clusters:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/logging/logSinksEnabled.js b/plugins/google/logging/logSinksEnabled.js index a29bb1c93a..1cb36adcc0 100644 --- a/plugins/google/logging/logSinksEnabled.js +++ b/plugins/google/logging/logSinksEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Log sinks send log data to a storage service for archival and compliance. A log sink with no filter is necessary to ensure that all logs are being properly sent. If logs are sent to a storage bucket, the bucket must exist and bucket versioning should exist.', link: 'https://cloud.google.com/logging/docs/export/', recommended_action: 'Ensure a log sink is configured properly with an empty filter and a destination.', - apis: ['sinks:list', 'buckets:list', 'projects:get'], + apis: ['sinks:list', 'buckets:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/anyHostRootAccess.js b/plugins/google/sql/anyHostRootAccess.js index 5bae3bd201..f5e2d3df4a 100644 --- a/plugins/google/sql/anyHostRootAccess.js +++ b/plugins/google/sql/anyHostRootAccess.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Root access for SQL instance should only be allowed from whitelisted IPs to ensure secure access only from trusted entities.', link: 'https://cloud.google.com/sql/docs/mysql/create-manage-users', recommended_action: 'Ensure that root access for SQL instances are not allowed from any host.', - apis: ['instances:sql:list', 'users:list', 'projects:get'], + apis: ['instances:sql:list', 'users:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/dbAutomatedBackups.js b/plugins/google/sql/dbAutomatedBackups.js index aea28554e6..148e34bed0 100644 --- a/plugins/google/sql/dbAutomatedBackups.js +++ b/plugins/google/sql/dbAutomatedBackups.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Google provides a simple method of backing up SQL instances at a regular interval. This should be enabled to provide an option for restoring data in the event of a database compromise or hardware failure.', link: 'https://cloud.google.com/sql/docs/mysql/instance-settings', recommended_action: 'Ensure that all database instances are configured with automatic backups enabled.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/dbMultiAz.js b/plugins/google/sql/dbMultiAz.js index 95b77ee90e..49c673c347 100644 --- a/plugins/google/sql/dbMultiAz.js +++ b/plugins/google/sql/dbMultiAz.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Creating SQL instances in with a single AZ creates a single point of failure for all systems relying on that database. All SQL instances should be created in multiple AZs to ensure proper failover.', link: 'https://cloud.google.com/sql/docs/mysql/instance-settings', recommended_action: 'Ensure that all database instances have a DB replica enabled in a secondary AZ.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/dbPubliclyAccessible.js b/plugins/google/sql/dbPubliclyAccessible.js index 987590e364..b018cedc67 100644 --- a/plugins/google/sql/dbPubliclyAccessible.js +++ b/plugins/google/sql/dbPubliclyAccessible.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Unless there is a specific business requirement, SQL instances should not have a public endpoint and should only be accessed from within a VPC.', link: 'https://cloud.google.com/sql/docs/mysql/authorize-networks', recommended_action: 'Ensure that SQL instances are configured to prohibit traffic from the public 0.0.0.0 global IP address.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], compliance: { hipaa: 'SQL instances should only be launched in VPC environments and ' + 'accessed through private endpoints. Exposing SQL instances to ' + diff --git a/plugins/google/sql/dbRestorable.js b/plugins/google/sql/dbRestorable.js index 0bb2cfa008..f24eee5fc2 100644 --- a/plugins/google/sql/dbRestorable.js +++ b/plugins/google/sql/dbRestorable.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Google will maintain a point to which the database can be restored. This point should not drift too far into the past, or else the risk of irrecoverable data loss may occur.', link: 'https://cloud.google.com/sql/docs/mysql/instance-settings', recommended_action: 'Ensure all database instances are configured with automatic backups and can be restored to a recent point with binary logging enabled.', - apis: ['instances:sql:list', 'projects:get', 'backupRuns:list'], + apis: ['instances:sql:list', 'backupRuns:list'], compliance: { pci: 'PCI requires that security procedures, including restoration of ' + 'compromised services, be tested frequently. RDS restorable time ' + diff --git a/plugins/google/sql/dbSSLEnabled.js b/plugins/google/sql/dbSSLEnabled.js index fe96341315..0e9e117cdd 100644 --- a/plugins/google/sql/dbSSLEnabled.js +++ b/plugins/google/sql/dbSSLEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Enabling SSL ensures that the sensitive data being transferred from the database is encrypted.', link: 'https://cloud.google.com/sql/docs/mysql/instance-settings', recommended_action: 'Ensure that SSL is enabled on all SQL databases.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], compliance: { pci: 'PCI requires strong cryptographic and security protocols ' + 'when transmitting user data, this includes using SSL.', diff --git a/plugins/google/sql/mysqlLatestVersion.js b/plugins/google/sql/mysqlLatestVersion.js index 9ad01bc741..226e87e6e2 100644 --- a/plugins/google/sql/mysqlLatestVersion.js +++ b/plugins/google/sql/mysqlLatestVersion.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'To make use of the latest database features and benefit from enhanced performance and security, make sure that your MySQL database instances are using the latest major version of MySQL.', link: 'https://cloud.google.com/sql/docs/mysql/db-versions', recommended_action: 'Ensure that all your MySQL database instances are using the latest MYSQL database version.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/mysqlLocalInfile.js b/plugins/google/sql/mysqlLocalInfile.js index 64605f9ed4..1074bbe08d 100644 --- a/plugins/google/sql/mysqlLocalInfile.js +++ b/plugins/google/sql/mysqlLocalInfile.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'SQL instances for MySQL type database provides local_infile flag, which can be used to load data from client or server systems. It controls the load data statements for database. Anyone using this server can access any file on the client system. For security reasons it should be disabled.', link: 'https://cloud.google.com/sql/docs/mysql/flags', recommended_action: 'Ensure that local infile flag is disabled for all MySQL instances.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/mysqlSlowQueryLog.js b/plugins/google/sql/mysqlSlowQueryLog.js index 983a70c130..e7ae51fdb4 100644 --- a/plugins/google/sql/mysqlSlowQueryLog.js +++ b/plugins/google/sql/mysqlSlowQueryLog.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'MySQL instance flag that helps find inefficient or time-consuming SQL queries for MySQL databases.', link: 'https://cloud.google.com/sql/docs/mysql/flags', recommended_action: 'Ensure that slow query log flag is enabled for all MySQL instances.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/postgresqlLatestVersion.js b/plugins/google/sql/postgresqlLatestVersion.js index 6bc4e6f556..e0d872c67d 100644 --- a/plugins/google/sql/postgresqlLatestVersion.js +++ b/plugins/google/sql/postgresqlLatestVersion.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'To make use of the latest database features and benefit from enhanced performance and security, make sure that your PostgreSQL database instances are using the latest major version of PostgreSQL.', link: 'https://cloud.google.com/sql/docs/postgres/db-versions', recommended_action: 'Ensure that all your PostgreSQL database instances are using the latest PostgreSQL database version.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/postgresqlLogCheckpoints.js b/plugins/google/sql/postgresqlLogCheckpoints.js index a66ccf68fa..01f3844913 100644 --- a/plugins/google/sql/postgresqlLogCheckpoints.js +++ b/plugins/google/sql/postgresqlLogCheckpoints.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'When log_checkpoints flag is enabled, instance checkpoints and restart points are logged in the server log.', link: 'https://cloud.google.com/sql/docs/postgres/flags#setting_a_database_flag', recommended_action: 'Ensure that all PostgreSQL database instances have log_checkpoints flag and it value is set to on.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/postgresqlLogConnections.js b/plugins/google/sql/postgresqlLogConnections.js index 66d4f05799..b26315c244 100644 --- a/plugins/google/sql/postgresqlLogConnections.js +++ b/plugins/google/sql/postgresqlLogConnections.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'SQL instance for PostgreSQL databases provides log_connections flag. It is used to log every attempt to connect to the db server. It is not enabled by default. Enabling it will make sure to log all connection tries', link: 'https://cloud.google.com/sql/docs/postgres/flags', recommended_action: 'Ensure that log connections flag is enabled for all PostgreSQL instances.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/postgresqlLogDisconnections.js b/plugins/google/sql/postgresqlLogDisconnections.js index c63b10e575..8038fc4c8c 100644 --- a/plugins/google/sql/postgresqlLogDisconnections.js +++ b/plugins/google/sql/postgresqlLogDisconnections.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'SQL instance for PostgreSQL databases provides log_disconnections flag. It is used to log every attempt to connect to the DB server. It is not enabled by default. Enabling it will make sure to log anyone who disconnects from the instance.', link: 'https://cloud.google.com/sql/docs/postgres/flags', recommended_action: 'Ensure that log disconnections flag is enabled for all PostgreSQL instances.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/postgresqlLogLockWaits.js b/plugins/google/sql/postgresqlLogLockWaits.js index 9cc85d7e07..b3c22f0255 100644 --- a/plugins/google/sql/postgresqlLogLockWaits.js +++ b/plugins/google/sql/postgresqlLogLockWaits.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'SQL instance for PostgreSQL database provides log_lock_waits flag. It is not enabled by default. Enabling it will make sure that log messages are generated whenever a session waits longer than deadlock_timeout to acquire a lock.', link: 'https://cloud.google.com/sql/docs/postgres/flags#config', recommended_action: 'Ensure that log_lock_waits flag is enabled for all PostgreSQL instances.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/postgresqlLogMinDuration.js b/plugins/google/sql/postgresqlLogMinDuration.js index 38adec09f7..f12f55bff4 100644 --- a/plugins/google/sql/postgresqlLogMinDuration.js +++ b/plugins/google/sql/postgresqlLogMinDuration.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'SQL instance for PostgreSQL databases provides log_min_duration_statement flag. It is used to log the duration of every completed statement. This should always be disabled as there can be sensitive information as well that should not be recorded in the logs.', link: 'https://cloud.google.com/sql/docs/postgres/flags', recommended_action: 'Ensure that log_min_duration_statement flag is disabled for all PostgreSQL instances.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/postgresqlLogMinError.js b/plugins/google/sql/postgresqlLogMinError.js index cab9bf2dbf..5902594d56 100644 --- a/plugins/google/sql/postgresqlLogMinError.js +++ b/plugins/google/sql/postgresqlLogMinError.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'SQL instance for PostgreSQL databases provides log_min_error_statement flag. It is used to mention/tag that the error messages. Setting it to Error value will help to find the error messages appropriately.', link: 'https://cloud.google.com/sql/docs/postgres/flags', recommended_action: 'Ensure that log_min_error_statement flag is set to Error for all PostgreSQL instances.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], settings: { log_min_error_statement: { name: 'Log Min Error Statement', diff --git a/plugins/google/sql/postgresqlLogTempFiles.js b/plugins/google/sql/postgresqlLogTempFiles.js index 247bce3652..b071e91284 100644 --- a/plugins/google/sql/postgresqlLogTempFiles.js +++ b/plugins/google/sql/postgresqlLogTempFiles.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'SQL instance for PostgreSQL databases provides log_temp_files flag. It is used to log the temporary files name and size. It is not enabled by default. Enabling it will make sure to log names and sizes of all the temporary files that were created during any operation(sort, hashes, query_results etc).', link: 'https://cloud.google.com/sql/docs/postgres/flags', recommended_action: 'Ensure that log_temp_files flag is enabled for all PostgreSQL instances.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/postgresqlMaxConnections.js b/plugins/google/sql/postgresqlMaxConnections.js index bd21b232f6..36ec0b05d7 100644 --- a/plugins/google/sql/postgresqlMaxConnections.js +++ b/plugins/google/sql/postgresqlMaxConnections.js @@ -10,7 +10,7 @@ module.exports = { 'If this no value is set for max_connections flag, instance assumes default value which is calculated per instance memory size.', link: 'https://cloud.google.com/sql/docs/postgres/flags#setting_a_database_flag', recommended_action: 'Ensure that all PostgreSQL database instances have log_checkpoints flag and it value is set to on.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], settings: { min_postgres_max_connections: { name: 'Minimum PostgreSQL Max Connections', diff --git a/plugins/google/sql/serverCertificateRotation.js b/plugins/google/sql/serverCertificateRotation.js index 4acb4fcf74..f10e0e808d 100644 --- a/plugins/google/sql/serverCertificateRotation.js +++ b/plugins/google/sql/serverCertificateRotation.js @@ -10,7 +10,7 @@ module.exports = { 'that incoming connections for database instance remain secure.', link: 'https://cloud.google.com/sql/docs/postgres/configure-ssl-instance?authuser=1#server-certs', recommended_action: 'Edit Cloud SQL DB instances and rotate server certificates under Connections->MANAGE CERTIFICATES', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], settings: { server_certicate_expiration_threshold: { name: 'SQL Server Certificate Expiration Threshold', diff --git a/plugins/google/sql/sqlCMKEncryption.js b/plugins/google/sql/sqlCMKEncryption.js index 20b12ae039..33d6864ebb 100644 --- a/plugins/google/sql/sqlCMKEncryption.js +++ b/plugins/google/sql/sqlCMKEncryption.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'By default, your Google Cloud SQL instances are encrypted using Google-managed keys. To have a better control over the encryption process of your Cloud SQL instances you can use Customer-Managed Keys (CMKs).', link: 'https://cloud.google.com/sql/docs/sqlserver/cmek', recommended_action: 'Ensure that all Google Cloud SQL instances have desired encryption level.', - apis: ['instances:sql:list', 'projects:get', 'keyRings:list', 'cryptoKeys:list'], + apis: ['instances:sql:list', 'keyRings:list', 'cryptoKeys:list'], settings: { sql_encryption_protection_level: { name: 'SQL Encryption Protection Level', diff --git a/plugins/google/sql/sqlContainedDatabaseAuth.js b/plugins/google/sql/sqlContainedDatabaseAuth.js index dd245deb1f..366e40ce57 100644 --- a/plugins/google/sql/sqlContainedDatabaseAuth.js +++ b/plugins/google/sql/sqlContainedDatabaseAuth.js @@ -10,7 +10,7 @@ module.exports = { 'a login at the Database Engine level along with other security threats.', link: 'https://cloud.google.com/sql/docs/sqlserver/flags', recommended_action: 'Ensure that Contained Database Authentication flag is disabled for all SQL Server instances.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/sqlCrossDbOwnership.js b/plugins/google/sql/sqlCrossDbOwnership.js index f429dc6f33..598d71c1b7 100644 --- a/plugins/google/sql/sqlCrossDbOwnership.js +++ b/plugins/google/sql/sqlCrossDbOwnership.js @@ -10,7 +10,7 @@ module.exports = { 'for all databases. It is enabled by default and should be disabled for security unless all required.', link: 'https://cloud.google.com/sql/docs/sqlserver/flags', recommended_action: 'Ensure that cross DB ownership chaining flag is disabled for all SQLServer instances.', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/sqlNoPublicIps.js b/plugins/google/sql/sqlNoPublicIps.js index 0b30936051..495686d971 100644 --- a/plugins/google/sql/sqlNoPublicIps.js +++ b/plugins/google/sql/sqlNoPublicIps.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Cloud SQL databases should always use private IP addresses which provide improved network security and lower latency.', link: 'https://cloud.google.com/sql/docs/mysql/configure-private-ip', recommended_action: 'Make sure that SQL databases IP addresses setting does not have IP address of PRIMARY type', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/sql/storageAutoIncreaseEnabled.js b/plugins/google/sql/storageAutoIncreaseEnabled.js index fa26cef890..efc78230ce 100644 --- a/plugins/google/sql/storageAutoIncreaseEnabled.js +++ b/plugins/google/sql/storageAutoIncreaseEnabled.js @@ -10,7 +10,7 @@ module.exports = { 'Cloud SQL automatically and permanently adds additional storage capacity. Setting a limit for automatic storage increase can prevent your instance size from growing too large.', link: 'https://cloud.google.com/sql/docs/mysql/instance-settings?authuser=1#automatic-storage-increase-2ndgen', recommended_action: 'Edit Cloud SQL instances and enable automatic storage increases feature under storage', - apis: ['instances:sql:list', 'projects:get'], + apis: ['instances:sql:list'], settings: { sql_storage_auto_increase_limit: { name: 'SQL Storage Auto Increase Limit', diff --git a/plugins/google/storage/bucketEncryption.js b/plugins/google/storage/bucketEncryption.js index 9776de8a03..47d57a0684 100644 --- a/plugins/google/storage/bucketEncryption.js +++ b/plugins/google/storage/bucketEncryption.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'By default, all storage buckets are encrypted using Google-managed keys. To have better control over how your storage bucktes are encrypted, you can use Customer-Managed Keys (CMKs).', link: 'https://cloud.google.com/storage/docs/encryption/customer-managed-keys', recommended_action: 'Ensure that all storage buckets have desired encryption level.', - apis: ['buckets:list', 'projects:get', 'keyRings:list', 'cryptoKeys:list'], + apis: ['buckets:list', 'keyRings:list', 'cryptoKeys:list'], settings: { bucket_encryption_level: { name: 'Storage Bucket Encryption Level', diff --git a/plugins/google/vpcnetwork/defaultVpcInUse.js b/plugins/google/vpcnetwork/defaultVpcInUse.js index af7524a099..e95079b257 100644 --- a/plugins/google/vpcnetwork/defaultVpcInUse.js +++ b/plugins/google/vpcnetwork/defaultVpcInUse.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'The default VPC should not be used in order to avoid launching multiple services in the same network which may not require connectivity. Each application, or network tier, should use its own VPC.', link: 'https://cloud.google.com/vpc/docs/vpc', recommended_action: 'Move resources from the default VPC to a new VPC created for that application or resource group.', - apis: ['networks:list', 'instances:compute:list', 'projects:get'], + apis: ['networks:list', 'instances:compute:list'], compliance: { pci: 'PCI has explicit requirements around default accounts and ' + 'resources. PCI recommends removing all default accounts, ' + diff --git a/plugins/google/vpcnetwork/dnsLoggingEnabled.js b/plugins/google/vpcnetwork/dnsLoggingEnabled.js index e81b9a2797..10ced9e2c4 100644 --- a/plugins/google/vpcnetwork/dnsLoggingEnabled.js +++ b/plugins/google/vpcnetwork/dnsLoggingEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Cloud DNS logging records the queries coming from Compute Engine VMs, GKE containers, or other GCP resources provisioned within the VPC to Stackdriver.', link: 'https://cloud.google.com/dns/docs/monitoring', recommended_action: 'Create Cloud DNS Server Policy with logging enabled for VPC Networks', - apis: ['networks:list', 'policies:list', 'projects:get'], + apis: ['networks:list', 'policies:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/firewallLoggingMetadata.js b/plugins/google/vpcnetwork/firewallLoggingMetadata.js index ccc87a541c..e7d6c7cd90 100644 --- a/plugins/google/vpcnetwork/firewallLoggingMetadata.js +++ b/plugins/google/vpcnetwork/firewallLoggingMetadata.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'You can significantly reduce the size of your log files and optimize storage costs by not including metadata. By default, metadata is included in firewall rule log files.', link: 'https://cloud.google.com/vpc/docs/firewall-rules-logging', recommended_action: 'Ensure that metadata is not included in firewall rule log files.', - apis: ['networks:list', 'firewalls:list', 'projects:get'], + apis: ['networks:list', 'firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/flowLogsEnabled.js b/plugins/google/vpcnetwork/flowLogsEnabled.js index e34c471f79..130b76dee9 100644 --- a/plugins/google/vpcnetwork/flowLogsEnabled.js +++ b/plugins/google/vpcnetwork/flowLogsEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'VPC flow logs record all traffic flowing in to and out of a VPC. These logs are critical for auditing and review after security incidents.', link: 'https://cloud.google.com/vpc/docs/using-flow-logs', recommended_action: 'Enable VPC flow logs for each VPC subnet', - apis: ['subnetworks:list', 'projects:get'], + apis: ['subnetworks:list'], compliance: { hipaa: 'VPC Flow Logs provide a detailed traffic log of a VPC network ' + 'containing HIPAA data. Flow Logs should be enabled to satisfy ' + diff --git a/plugins/google/vpcnetwork/multipleSubnets.js b/plugins/google/vpcnetwork/multipleSubnets.js index f3d23040f5..8a36811537 100644 --- a/plugins/google/vpcnetwork/multipleSubnets.js +++ b/plugins/google/vpcnetwork/multipleSubnets.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'A single network within a VPC increases the risk of a broader blast radius in the event of a compromise.', link: 'https://cloud.google.com/vpc/docs/vpc', recommended_action: 'Create multiple networks/subnets in each VPC and change the architecture to take advantage of public and private tiers.', - apis: ['networks:list', 'projects:get'], + apis: ['networks:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openCIFS.js b/plugins/google/vpcnetwork/openCIFS.js index be19046fd8..bdaad9a852 100644 --- a/plugins/google/vpcnetwork/openCIFS.js +++ b/plugins/google/vpcnetwork/openCIFS.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as CIFS should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict UDP port 445 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openCassandra.js b/plugins/google/vpcnetwork/openCassandra.js index 77bb8547ad..32678b8029 100644 --- a/plugins/google/vpcnetwork/openCassandra.js +++ b/plugins/google/vpcnetwork/openCassandra.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as Cassandra should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP ports 7001 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openCustomPorts.js b/plugins/google/vpcnetwork/openCustomPorts.js index c4345116ce..c4842509ca 100644 --- a/plugins/google/vpcnetwork/openCustomPorts.js +++ b/plugins/google/vpcnetwork/openCustomPorts.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'To prevent attackers from identifying and exploiting the services running on your instances, make sure the VPC Network custom ports are not open to public.', link: 'https://cloud.google.com/vpc/docs/firewalls', recommended_action: 'Ensure that your VPC Network firewall rules do not allow inbound traffic for a range of ports.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], settings: { restricted_open_ports: { name: 'Restricted Open Ports', diff --git a/plugins/google/vpcnetwork/openDNS.js b/plugins/google/vpcnetwork/openDNS.js index a1d18d3c57..bd4218b475 100644 --- a/plugins/google/vpcnetwork/openDNS.js +++ b/plugins/google/vpcnetwork/openDNS.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as DNS should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP and UDP port 53 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openDocker.js b/plugins/google/vpcnetwork/openDocker.js index bd77f059c6..414b6c7d34 100644 --- a/plugins/google/vpcnetwork/openDocker.js +++ b/plugins/google/vpcnetwork/openDocker.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as Docker should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP ports 2375 and 2376 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openFTP.js b/plugins/google/vpcnetwork/openFTP.js index 0608b29b8d..cc839c500b 100644 --- a/plugins/google/vpcnetwork/openFTP.js +++ b/plugins/google/vpcnetwork/openFTP.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as FTP should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 20 or 21 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openHadoopNameNode.js b/plugins/google/vpcnetwork/openHadoopNameNode.js index 80148924da..b61847c6ba 100644 --- a/plugins/google/vpcnetwork/openHadoopNameNode.js +++ b/plugins/google/vpcnetwork/openHadoopNameNode.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as Hadoop/HDFS should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 8020 to known IP addresses for Hadoop/HDFS.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openHadoopNameNodeWebUI.js b/plugins/google/vpcnetwork/openHadoopNameNodeWebUI.js index 243306b3a4..76eca64fd1 100644 --- a/plugins/google/vpcnetwork/openHadoopNameNodeWebUI.js +++ b/plugins/google/vpcnetwork/openHadoopNameNodeWebUI.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as Hadoop/HDFS should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 50070 and 50470 to known IP addresses for Hadoop/HDFS', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openKibana.js b/plugins/google/vpcnetwork/openKibana.js index 307605da47..8f9bbefaf2 100644 --- a/plugins/google/vpcnetwork/openKibana.js +++ b/plugins/google/vpcnetwork/openKibana.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as Kibana should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 5601 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openMongo.js b/plugins/google/vpcnetwork/openMongo.js index 499743583c..55d35671ba 100644 --- a/plugins/google/vpcnetwork/openMongo.js +++ b/plugins/google/vpcnetwork/openMongo.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as Mongo should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP ports 27017 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openMsSQL.js b/plugins/google/vpcnetwork/openMsSQL.js index 0fd4ca9813..677f71c61d 100644 --- a/plugins/google/vpcnetwork/openMsSQL.js +++ b/plugins/google/vpcnetwork/openMsSQL.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as MSSQL should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 1433 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openMySQL.js b/plugins/google/vpcnetwork/openMySQL.js index dd5cbef845..e612cc05cf 100644 --- a/plugins/google/vpcnetwork/openMySQL.js +++ b/plugins/google/vpcnetwork/openMySQL.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as MySQL should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP ports 4333 and 3306 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openNetBIOS.js b/plugins/google/vpcnetwork/openNetBIOS.js index 5c0d39ef75..a09aca1ae7 100644 --- a/plugins/google/vpcnetwork/openNetBIOS.js +++ b/plugins/google/vpcnetwork/openNetBIOS.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as NetBIOS should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict UDP ports 137 and 138 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openOracle.js b/plugins/google/vpcnetwork/openOracle.js index a154d98ecd..6084d97931 100644 --- a/plugins/google/vpcnetwork/openOracle.js +++ b/plugins/google/vpcnetwork/openOracle.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as Oracle should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP ports 1521 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openOracleAutoDataWarehouse.js b/plugins/google/vpcnetwork/openOracleAutoDataWarehouse.js index d16c6738bb..45e2c50c4b 100644 --- a/plugins/google/vpcnetwork/openOracleAutoDataWarehouse.js +++ b/plugins/google/vpcnetwork/openOracleAutoDataWarehouse.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as Oracle should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP ports 1522 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openPostgreSQL.js b/plugins/google/vpcnetwork/openPostgreSQL.js index 03c5666229..e066319d68 100644 --- a/plugins/google/vpcnetwork/openPostgreSQL.js +++ b/plugins/google/vpcnetwork/openPostgreSQL.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as PostgreSQL should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 5432 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openRDP.js b/plugins/google/vpcnetwork/openRDP.js index 34f352ac24..11366ce847 100644 --- a/plugins/google/vpcnetwork/openRDP.js +++ b/plugins/google/vpcnetwork/openRDP.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as RDP should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 3389 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openRPC.js b/plugins/google/vpcnetwork/openRPC.js index 830cdbe8e9..25b785852f 100644 --- a/plugins/google/vpcnetwork/openRPC.js +++ b/plugins/google/vpcnetwork/openRPC.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as RPC should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 135 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openRedis.js b/plugins/google/vpcnetwork/openRedis.js index 27c868a80b..e3152c8f38 100644 --- a/plugins/google/vpcnetwork/openRedis.js +++ b/plugins/google/vpcnetwork/openRedis.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as Redis should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 6379 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openSMBoTCP.js b/plugins/google/vpcnetwork/openSMBoTCP.js index 176cbe3196..db773baa4a 100644 --- a/plugins/google/vpcnetwork/openSMBoTCP.js +++ b/plugins/google/vpcnetwork/openSMBoTCP.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as SMB should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 445 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openSMTP.js b/plugins/google/vpcnetwork/openSMTP.js index 1c553286ff..8bc8d873b7 100644 --- a/plugins/google/vpcnetwork/openSMTP.js +++ b/plugins/google/vpcnetwork/openSMTP.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as SMTP should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 25 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openSQLServer.js b/plugins/google/vpcnetwork/openSQLServer.js index 9cf651ce8e..3fa1aba973 100644 --- a/plugins/google/vpcnetwork/openSQLServer.js +++ b/plugins/google/vpcnetwork/openSQLServer.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as SQL server should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 1433 and UDP port 1434 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openSSH.js b/plugins/google/vpcnetwork/openSSH.js index 774a5eb12f..e307092b77 100644 --- a/plugins/google/vpcnetwork/openSSH.js +++ b/plugins/google/vpcnetwork/openSSH.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as SSH should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 22 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openSalt.js b/plugins/google/vpcnetwork/openSalt.js index 7d6a551bc9..12001babb1 100644 --- a/plugins/google/vpcnetwork/openSalt.js +++ b/plugins/google/vpcnetwork/openSalt.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Active Salt vulnerabilities, CVE-2020-11651 and CVE-2020-11652 are exploiting Salt instances exposed to the internet. These ports should be closed immediately.', link: 'https://help.saltstack.com/hc/en-us/articles/360043056331-New-SaltStack-Release-Critical-Vulnerability', recommended_action: 'Restrict TCP ports 4505 and 4506 to known IP addresses', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openTelnet.js b/plugins/google/vpcnetwork/openTelnet.js index 5969711f1a..ef4a613fe0 100644 --- a/plugins/google/vpcnetwork/openTelnet.js +++ b/plugins/google/vpcnetwork/openTelnet.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as Telnet should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 23 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openVNCClient.js b/plugins/google/vpcnetwork/openVNCClient.js index d1411070ab..5a86b4d05d 100644 --- a/plugins/google/vpcnetwork/openVNCClient.js +++ b/plugins/google/vpcnetwork/openVNCClient.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as VNC Client should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 5500 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/openVNCServer.js b/plugins/google/vpcnetwork/openVNCServer.js index d3cf5d13ff..3dd5cd123e 100644 --- a/plugins/google/vpcnetwork/openVNCServer.js +++ b/plugins/google/vpcnetwork/openVNCServer.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, more sensitive services such as VNC Server should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict TCP port 5900 to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], run: function(cache, settings, callback) { var results = []; diff --git a/plugins/google/vpcnetwork/privateAccessEnabled.js b/plugins/google/vpcnetwork/privateAccessEnabled.js index 06bb8f7a25..9d13e6859c 100644 --- a/plugins/google/vpcnetwork/privateAccessEnabled.js +++ b/plugins/google/vpcnetwork/privateAccessEnabled.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'Private Google Access allows VM instances on a subnet to reach Google APIs and services without an IP address. This creates a more secure network for the internal communication.', link: 'https://cloud.google.com/vpc/docs/configure-private-google-access', recommended_action: '1. Enter the VPC Network service. 2. Enter the VPC. 3. Select the subnet in question. 4. Edit the subnet and enable Private Google Access.', - apis: ['subnetworks:list', 'projects:get'], + apis: ['subnetworks:list'], compliance: { pci: 'PCI recommends implementing additional security features for ' + 'any required service. This includes using secured technologies ' + From d698c21bf6b891b361d000018f9791d5deca99e0 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sun, 12 Jun 2022 05:39:16 +0500 Subject: [PATCH 243/350] Oracle - Instance Legacy Metadata Endpoint Disabled --- exports.js | 1 + .../oracle/compute/legacyEndpointDisabled.js | 53 ++++++ .../compute/legacyEndpointDisabled.spec.js | 151 ++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 plugins/oracle/compute/legacyEndpointDisabled.js create mode 100644 plugins/oracle/compute/legacyEndpointDisabled.spec.js diff --git a/exports.js b/exports.js index b24a16826f..26d0728c15 100644 --- a/exports.js +++ b/exports.js @@ -809,6 +809,7 @@ module.exports = { 'bootVolumeRestorable' : require(__dirname + '/plugins/oracle/compute/bootVolumeRestorable.js'), 'bootVolumeBackupEnabled' : require(__dirname + '/plugins/oracle/compute/bootVolumeBackupEnabled.js'), 'instancePolicyProtection' : require(__dirname + '/plugins/oracle/compute/instancePolicyProtection.js'), + 'legacyEndpointDisabled' : require(__dirname + '/plugins/oracle/compute/legacyEndpointDisabled.js'), 'usersMfaEnabled' : require(__dirname + '/plugins/oracle/identity/usersMfaEnabled.js'), 'passwordRequiresLowercase' : require(__dirname + '/plugins/oracle/identity/passwordRequiresLowercase.js'), diff --git a/plugins/oracle/compute/legacyEndpointDisabled.js b/plugins/oracle/compute/legacyEndpointDisabled.js new file mode 100644 index 0000000000..c59f03fcc4 --- /dev/null +++ b/plugins/oracle/compute/legacyEndpointDisabled.js @@ -0,0 +1,53 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Legacy Metadata Endpoint Disabled', + category: 'Compute', + domain: 'Compute', + description: 'Ensure that compute instances are configured with Legacy MetaData service (IMDSv1) endpoints disabled.', + more_info: 'For best security practices, it is recommended that the compute instances should be configured with legacy v1 endpoints (Instance Metadata Service v1) disabled, and use Instance Metadata Service v2 instead.', + recommended_action: 'Ensure all compute instances are configured to use IMDSv2.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/gettingmetadata.htm#upgrading-v2', + apis: ['instance:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.instance, function(region, rcb){ + + if (helpers.checkRegionSubscription(cache, source, results, region)) { + + var instances = helpers.addSource(cache, source, + ['instance', 'list', region]); + + if (!instances) return rcb(); + + if (instances.err || !instances.data) { + helpers.addResult(results, 3, + 'Unable to query for instances: ' + helpers.addError(instances), region); + return rcb(); + } + + if (!instances.data.length) { + helpers.addResult(results, 0, 'No instances found', region); + return rcb(); + } + + instances.data.forEach(instance => { + if (instance.instanceOptions && instance.instanceOptions.areLegacyImdsEndpointsDisabled) { + helpers.addResult(results, 0, 'Instance has Legacy MetaData service (IMDSv1) endpoints disabled', region, instance.id); + } else { + helpers.addResult(results, 2, 'Instance does not have Legacy MetaData service (IMDSv1) endpoints disabled', region, instance.id); + } + }); + } + rcb(); + }, function(){ + // Global checking goes here + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/compute/legacyEndpointDisabled.spec.js b/plugins/oracle/compute/legacyEndpointDisabled.spec.js new file mode 100644 index 0000000000..c0c58f9bfc --- /dev/null +++ b/plugins/oracle/compute/legacyEndpointDisabled.spec.js @@ -0,0 +1,151 @@ +var expect = require('chai').expect; +var plugin = require('./legacyEndpointDisabled'); + +const createCache = (err, data) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + instance: { + list: { + 'us-ashburn-1': { + err: err, + data: data + } + } + } + } +}; + +describe('legacyEndpointDisabled', function () { + describe('run', function () { + it('should give unknown result if an instance error is passed or no data is present', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for instances') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['error'], + null, + ); + + plugin.run(cache, {}, callback); + }) + it('should give passing result if no instance records are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No instances found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [], + ); + + plugin.run(cache, {}, callback); + }) + it('should give passing result if instance has legacy endpoints disabled', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('Instance has Legacy MetaData service (IMDSv1) endpoints disabled') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [ + { + "compartmentId": "ocid1.tenancy.oc1..aaaaaaaaaaaa", + "dedicatedVmHostId": null, + "definedTags": {}, + "displayName": "instance1", + "extendedMetadata": { + "compute_management": { + "instance_configuration": { + "state": "SUCCEEDED" + } + } + }, + "faultDomain": "FAULT-DOMAIN-1", + "id": "ocid1.instance.oc1", + "imageId": "ocid1.image.oc1", + "instanceOptions": { + "areLegacyImdsEndpointsDisabled": true + } + } + ] + ); + + plugin.run(cache, {}, callback); + }) + it('should give failing result if instance does not have legacy endpoints disabled', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('Instance does not have Legacy MetaData service (IMDSv1) endpoints disabled') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [ + { + "compartmentId": "ocid1.tenancy.oc1..aaaaaaaaaaaa", + "dedicatedVmHostId": null, + "definedTags": {}, + "displayName": "instance1", + "extendedMetadata": { + "compute_management": { + "instance_configuration": { + "state": "SUCCEEDED" + } + } + }, + "faultDomain": "FAULT-DOMAIN-1", + "id": "ocid1.instance.oc1", + "imageId": "ocid1.image.oc1", + "instanceOptions": { + "areLegacyImdsEndpointsDisabled": false + } + } + ] + ); + + plugin.run(cache, {}, callback); + }) + }) +}) \ No newline at end of file From 4a5c68b1de7d18b028cb204e82e5539c84b735f5 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sun, 12 Jun 2022 06:12:29 +0500 Subject: [PATCH 244/350] Oracle - Bucket Object Events --- exports.js | 1 + .../oracle/objectstore/bucketObjectEvents.js | 51 +++++++ .../objectstore/bucketObjectEvents.spec.js | 134 ++++++++++++++++++ 3 files changed, 186 insertions(+) create mode 100644 plugins/oracle/objectstore/bucketObjectEvents.js create mode 100644 plugins/oracle/objectstore/bucketObjectEvents.spec.js diff --git a/exports.js b/exports.js index b24a16826f..69d82b78f3 100644 --- a/exports.js +++ b/exports.js @@ -866,6 +866,7 @@ module.exports = { 'preAuthRequestsExpiry' : require(__dirname + '/plugins/oracle/objectstore/preAuthRequestsExpiry.js'), 'preAuthRequestsAccess' : require(__dirname + '/plugins/oracle/objectstore/preAuthRequestsAccess.js'), 'objectPolicyProtection' : require(__dirname + '/plugins/oracle/objectstore/objectPolicyProtection.js'), + 'bucketObjectEvents' : require(__dirname + '/plugins/oracle/objectstore/bucketObjectEvents.js'), 'nfsPublicAccess' : require(__dirname + '/plugins/oracle/filestorage/nfsPublicAccess.js'), 'nfsPolicyProtection' : require(__dirname + '/plugins/oracle/filestorage/nfsPolicyProtection.js'), diff --git a/plugins/oracle/objectstore/bucketObjectEvents.js b/plugins/oracle/objectstore/bucketObjectEvents.js new file mode 100644 index 0000000000..64d96dfed9 --- /dev/null +++ b/plugins/oracle/objectstore/bucketObjectEvents.js @@ -0,0 +1,51 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Bucket Object Events', + category: 'Object Store', + domain: 'Storage', + description: 'Ensures object store buckets can emit object events.', + more_info: 'Object store buckets should be configured to emit object events in order to help monitor and keep track of bucket state changes.', + recommended_action: 'Ensure all object store buckets are allowed to emit object events.', + link: 'https://docs.cloud.oracle.com/iaas/Content/Object/Tasks/managingbuckets.htm', + apis: ['namespace:get','bucket:list', 'bucket:get'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.bucket, function(region, rcb) { + + if (helpers.checkRegionSubscription(cache, source, results, region)) { + + var getBucket = helpers.addSource(cache, source, + ['bucket', 'get', region]); + + if (!getBucket) return rcb(); + + if (getBucket.err || !getBucket.data) { + helpers.addResult(results, 3, + 'Unable to query for object store bucket details: ' + helpers.addError(getBucket), region); + } else if (!getBucket.data.length) { + helpers.addResult(results, 0, 'No object store bucket details to check', region); + } else { + + getBucket.data.forEach(function(bucket) { + if (bucket.objectEventsEnabled) { + helpers.addResult(results, 0, + `Object store bucket (${bucket.name}) can emit object events.`, region, bucket.id); + } else { + helpers.addResult(results, 2, + `Object store bucket (${bucket.name}) cannot emit object events.`, region, bucket.id); + } + }); + } + } + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/objectstore/bucketObjectEvents.spec.js b/plugins/oracle/objectstore/bucketObjectEvents.spec.js new file mode 100644 index 0000000000..9faad55637 --- /dev/null +++ b/plugins/oracle/objectstore/bucketObjectEvents.spec.js @@ -0,0 +1,134 @@ +var expect = require('chai').expect; +var plugin = require('./bucketObjectEvents'); + +const getBucket = [ + { + "namespace": 'idacicrnmktm', + "name": 'my-bucket', + "id": 'ocid1.bucket.oc1.iad.111111111111111122222222222222222233333333333333333', + "compartmentId": 'ocid1.tenancy.oc1..11111111111111111222222222222222222333333333333333', + "createdBy": 'ocid1.user.oc1..11111111111111112222222222222223333333333333333', + "timeCreated": '2021-04-28T13:26:51.917Z', + "objectEventsEnabled": false + }, + { + "namespace": 'idacicrnmktm', + "name": 'akhtar-bucket', + "id": 'ocid1.bucket.oc1.iad.111111111111111122222222222222222233333333333333333', + "compartmentId": 'ocid1.tenancy.oc1..11111111111111111222222222222222222333333333333333', + "createdBy": 'ocid1.user.oc1..11111111111111112222222222222223333333333333333', + "timeCreated": '2021-04-28T13:26:51.917Z', + "objectEventsEnabled": true + } +]; + +const createCache = (err, data) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + bucket: { + get: { + 'us-ashburn-1': { + err: err, + data: data + } + } + } + } +}; + +describe('bucketObjectEvents', function () { + describe('run', function () { + it('should give unknown result if unable to query for object store bucket details', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for object store bucket details') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['hello'], + undefined + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if no object store buckets', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No object store bucket details to check') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if bucket cannot emit object events', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('cannot emit object events') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [getBucket[0]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if bucket can emit object events', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('can emit object events') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [getBucket[1]] + ); + + plugin.run(cache, {}, callback); + }); + }); +}); \ No newline at end of file From 3a43f5d8adb1ad02792cfe254175ca96c1a45af9 Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sat, 11 Jun 2022 15:02:44 +0500 Subject: [PATCH 245/350] Added diagnosticsSettingsEnabled plugin and spec --- exports.js | 2 + .../diagnostics/diagnosticsSettingsEnabled.js | 54 +++++ .../diagnosticsSettingsEnabled.spec.js | 202 ++++++++++++++++++ 3 files changed, 258 insertions(+) create mode 100644 plugins/azure/diagnostics/diagnosticsSettingsEnabled.js create mode 100644 plugins/azure/diagnostics/diagnosticsSettingsEnabled.spec.js diff --git a/exports.js b/exports.js index b24a16826f..42ee000164 100644 --- a/exports.js +++ b/exports.js @@ -787,6 +787,8 @@ module.exports = { 'enableDefenderForContainers' : require(__dirname + '/plugins/azure/defender/enableDefenderForContainers.js'), 'enableDefenderForSqlServers' : require(__dirname + '/plugins/azure/defender/enableDefenderForSqlServers.js'), 'enableEndpointIntegration' : require(__dirname + '/plugins/azure/defender/enableEndpointIntegration.js'), + + 'diagnosticsSettingsEnabled' : require(__dirname + '/plugins/azure/diagnostics/diagnosticsSettingsEnabled.js'), }, github: { 'publicKeysRotated' : require(__dirname + '/plugins/github/users/publicKeysRotated.js'), diff --git a/plugins/azure/diagnostics/diagnosticsSettingsEnabled.js b/plugins/azure/diagnostics/diagnosticsSettingsEnabled.js new file mode 100644 index 0000000000..4b14151c08 --- /dev/null +++ b/plugins/azure/diagnostics/diagnosticsSettingsEnabled.js @@ -0,0 +1,54 @@ +const async = require('async'); +const helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Diagnostics Settings Enabled', + category: 'Monitor', + domain: 'Management and Governance', + description: 'Ensures that Diagnostics Settings for exporting logs is enabled.', + more_info: 'Enable Diagnostic settings for exporting activity logs. Diagnostic setting are available for each individual resources within a subscription. Settings should be configured for all appropriate resources for your environment.', + recommended_action: 'Ensure that a Diagnostic status is enabled on all appropriate resources.', + link: 'https://docs.microsoft.com/en-us/azure/monitoring-and-diagnostics/monitoring-overview-activity-logs#export-the-activity-log-with-a-log-profile', + apis: ['diagnosticSettingsOperations:list'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + + async.each(locations.diagnosticSettingsOperations, (location, rcb) => { + const diagnosticSettings = helpers.addSource(cache, source, + ['diagnosticSettingsOperations', 'list', location]); + + if (!diagnosticSettings) return rcb(); + + if (diagnosticSettings.err || !diagnosticSettings.data) { + helpers.addResult(results, 3, 'Unable to query for Diagnostic Settings : ' + helpers.addError(diagnosticSettings), location); + return rcb(); + } + + if (!diagnosticSettings.data.length) { + helpers.addResult(results, 2, 'No existing Diagnostic Settings found', location); + return rcb(); + } + + diagnosticSettings.data.forEach(settings => { + if (settings.logs && settings.logs.length) { + let disabledLog = settings.logs.find(log => !log.enabled); + + if (disabledLog) { + helpers.addResult(results, 2, 'Diagnostic Setting is not enabled for exporting logs on all resources', location, settings.id); + } else if (settings.storageAccountId && settings.storageAccountId.length) { + helpers.addResult(results, 0, 'Diagnostic Setting is enabled for exporting logs for all resources', location, settings.id); + } else { + helpers.addResult(results, 2, 'Diagnostic Setting does not have a Storage Account configured for Azure Monitor Logs', location, settings.id); + } + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/diagnostics/diagnosticsSettingsEnabled.spec.js b/plugins/azure/diagnostics/diagnosticsSettingsEnabled.spec.js new file mode 100644 index 0000000000..7d72e21da9 --- /dev/null +++ b/plugins/azure/diagnostics/diagnosticsSettingsEnabled.spec.js @@ -0,0 +1,202 @@ +var expect = require('chai').expect; +var diagnosticsSettingsEnabled = require('./diagnosticsSettingsEnabled'); + +const diagnosticSettings = [ + { + 'id': 'subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting', + 'type': 'Microsoft.Insights/diagnosticSettings', + 'name': 'test-setting', + 'location': 'global', + 'storageAccountId': '/subscriptions/123/resourceGroups/devresourcegroup/providers/Microsoft.Storage/storageAccounts/test-storage-account', + 'logs': [ + { + 'category': 'Administrative', + 'enabled': true + }, + { + 'category': 'Security', + 'enabled': true + }, + { + 'category': 'ServiceHealth', + 'enabled': true + }, + { + 'category': 'Alert', + 'enabled': true + }, + { + 'category': 'Recommendation', + 'enabled': true + }, + { + 'category': 'Policy', + 'enabled': true + }, + { + 'category': 'Autoscale', + 'enabled': true + }, + { + 'category': 'ResourceHealth', + 'enabled': true + } + ] + }, + { + 'id': 'subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting', + 'type': 'Microsoft.Insights/diagnosticSettings', + 'name': 'test-setting', + 'location': 'global', + 'storageAccountId': '/subscriptions/123/resourceGroups/devresourcegroup/providers/Microsoft.Storage/storageAccounts/test-storage-account', + 'logs': [ + { + 'category': 'Administrative', + 'enabled': true + }, + { + 'category': 'Security', + 'enabled': true + }, + { + 'category': 'ServiceHealth', + 'enabled': true + }, + { + 'category': 'Alert', + 'enabled': true + }, + { + 'category': 'Recommendation', + 'enabled': true + }, + { + 'category': 'Policy', + 'enabled': true + }, + { + 'category': 'Autoscale', + 'enabled': true + }, + { + 'category': 'ResourceHealth', + 'enabled': false + } + ] + }, + { + 'id': 'subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting', + 'type': 'Microsoft.Insights/diagnosticSettings', + 'name': 'test-setting', + 'location': 'global', + 'eventHubAuthorizationRuleId': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.EventHub/namespaces/test-setting/authorizationrules/RootManageSharedAccessKey', + 'eventHubName': '', + 'logs': [ + { + 'category': 'Administrative', + 'enabled': true + }, + { + 'category': 'Security', + 'enabled': true + }, + { + 'category': 'ServiceHealth', + 'enabled': true + }, + { + 'category': 'Alert', + 'enabled': true + }, + { + 'category': 'Recommendation', + 'enabled': true + }, + { + 'category': 'Policy', + 'enabled': true + }, + { + 'category': 'Autoscale', + 'enabled': true + }, + { + 'category': 'ResourceHealth', + 'enabled': true + } + ] + } +]; + +const createCache = (diagnosticSettings) => { + let settings = {}; + if (diagnosticSettings) { + settings['data'] = diagnosticSettings; + } + return { + diagnosticSettingsOperations: { + list: { + 'global': settings + } + } + }; +}; + +describe('diagnosticsSettingsEnabled', function() { + describe('run', function() { + it('should give failing result if no diagnostic settings found', function(done) { + const cache = createCache([]); + diagnosticsSettingsEnabled.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 Diagnostic Settings found'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give unknown result if unable to query for diagnostic settings', function(done) { + const cache = createCache(); + diagnosticsSettingsEnabled.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 Diagnostic Settings'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give passing result if logs are enabled for all logging categories and storage account configured', function(done) { + const cache = createCache([diagnosticSettings[0]]); + diagnosticsSettingsEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Diagnostic Setting is enabled for exporting logs for all resources'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give failing result if logs are not enabled for all logging categories and storage account configured', function(done) { + const cache = createCache([diagnosticSettings[1]]); + diagnosticsSettingsEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Diagnostic Setting is not enabled for exporting logs on all resources'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give failing result if logs are enabled for all logging categories and storage account is not configured', function(done) { + const cache = createCache([diagnosticSettings[2]]); + diagnosticsSettingsEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Diagnostic Setting does not have a Storage Account configured for Azure Monitor Logs'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + }); +}); From f0367710dd4c048d28390dde423598299f3ecfcc Mon Sep 17 00:00:00 2001 From: Muhammad Nouman Date: Sun, 12 Jun 2022 14:24:06 +0500 Subject: [PATCH 246/350] Added captureAppropriateCategories plugin and spec --- exports.js | 2 + .../captureAppropriateCategories.js | 61 +++++++ .../captureAppropriateCategories.spec.js | 149 ++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 plugins/azure/diagnostics/captureAppropriateCategories.js create mode 100644 plugins/azure/diagnostics/captureAppropriateCategories.spec.js diff --git a/exports.js b/exports.js index b24a16826f..2cd5414dfd 100644 --- a/exports.js +++ b/exports.js @@ -787,6 +787,8 @@ module.exports = { 'enableDefenderForContainers' : require(__dirname + '/plugins/azure/defender/enableDefenderForContainers.js'), 'enableDefenderForSqlServers' : require(__dirname + '/plugins/azure/defender/enableDefenderForSqlServers.js'), 'enableEndpointIntegration' : require(__dirname + '/plugins/azure/defender/enableEndpointIntegration.js'), + + 'captureAppropriateCategories' : require(__dirname + '/plugins/azure/diagnostics/captureAppropriateCategories.js'), }, github: { 'publicKeysRotated' : require(__dirname + '/plugins/github/users/publicKeysRotated.js'), diff --git a/plugins/azure/diagnostics/captureAppropriateCategories.js b/plugins/azure/diagnostics/captureAppropriateCategories.js new file mode 100644 index 0000000000..91c66b6915 --- /dev/null +++ b/plugins/azure/diagnostics/captureAppropriateCategories.js @@ -0,0 +1,61 @@ +const async = require('async'); +const _ = require('underscore'); +const helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Capture Appropriate Categories Logs', + category: 'Monitor', + domain: 'Management and Governance', + description: 'Ensures that Diagnostics Settings is capturing logs for all appropriate categories.', + more_info: 'A diagnostic setting controls how the diagnostic log is exported. Capturing the diagnostic setting categories for appropriate control/management plane activities allows proper alerting.', + recommended_action: 'Ensure that Diagnostic settings is enabled on all appropriate categories.', + link: 'https://docs.microsoft.com/en-us/azure/azure-monitor/samples/resource-manager-diagnostic-settings', + apis: ['diagnosticSettingsOperations:list'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + const appropriateCategories = ['Administrative', 'Alert', 'Policy', 'Security']; + + async.each(locations.diagnosticSettingsOperations, (location, rcb) => { + const diagnosticSettings = helpers.addSource(cache, source, + ['diagnosticSettingsOperations', 'list', location]); + + if (!diagnosticSettings) return rcb(); + + if (diagnosticSettings.err || !diagnosticSettings.data) { + helpers.addResult(results, 3, 'Unable to query for Diagnostic Settings : ' + helpers.addError(diagnosticSettings), location); + return rcb(); + } + + if (!diagnosticSettings.data.length) { + helpers.addResult(results, 2, 'No existing Diagnostic Settings found', location); + return rcb(); + } + + let enabledCategories = []; + diagnosticSettings.data.forEach(settings => { + if (settings.logs && settings.logs.length) { + settings.logs.forEach(log => { + if (log.enabled && appropriateCategories.indexOf(log.category) > -1) { + if (enabledCategories.indexOf(log.category) === -1) { + enabledCategories.push(log.category); + } + } + }); + + if (_.difference(appropriateCategories, enabledCategories).length === 0) { + helpers.addResult(results, 0, 'Logs for all appropriate categories are enabled for Diagnostic Settings', location); + } else { + helpers.addResult(results, 2, 'Logs for all appropriate categories are not enabled for Diagnostic Settings', location); + } + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/diagnostics/captureAppropriateCategories.spec.js b/plugins/azure/diagnostics/captureAppropriateCategories.spec.js new file mode 100644 index 0000000000..758e2f4cca --- /dev/null +++ b/plugins/azure/diagnostics/captureAppropriateCategories.spec.js @@ -0,0 +1,149 @@ +var expect = require('chai').expect; +var captureAppropriateCategories = require('./captureAppropriateCategories'); + +const diagnosticSettings = [ + { + 'id': 'subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting', + 'type': 'Microsoft.Insights/diagnosticSettings', + 'name': 'test-setting', + 'location': 'global', + 'storageAccountId': '/subscriptions/123/resourceGroups/devresourcegroup/providers/Microsoft.Storage/storageAccounts/test-storage-account', + 'logs': [ + { + 'category': 'Administrative', + 'enabled': true + }, + { + 'category': 'Security', + 'enabled': true + }, + { + 'category': 'ServiceHealth', + 'enabled': true + }, + { + 'category': 'Alert', + 'enabled': true + }, + { + 'category': 'Recommendation', + 'enabled': true + }, + { + 'category': 'Policy', + 'enabled': true + }, + { + 'category': 'Autoscale', + 'enabled': true + }, + { + 'category': 'ResourceHealth', + 'enabled': true + } + ] + }, + { + 'id': 'subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting', + 'type': 'Microsoft.Insights/diagnosticSettings', + 'name': 'test-setting', + 'location': 'global', + 'storageAccountId': '/subscriptions/123/resourceGroups/devresourcegroup/providers/Microsoft.Storage/storageAccounts/test-storage-account', + 'logs': [ + { + 'category': 'Administrative', + 'enabled': true + }, + { + 'category': 'Security', + 'enabled': true + }, + { + 'category': 'ServiceHealth', + 'enabled': true + }, + { + 'category': 'Alert', + 'enabled': false + }, + { + 'category': 'Recommendation', + 'enabled': true + }, + { + 'category': 'Policy', + 'enabled': true + }, + { + 'category': 'Autoscale', + 'enabled': true + }, + { + 'category': 'ResourceHealth', + 'enabled': false + } + ] + } +]; + +const createCache = (diagnosticSettings) => { + let settings = {}; + if (diagnosticSettings) { + settings['data'] = diagnosticSettings; + } + return { + diagnosticSettingsOperations: { + list: { + 'global': settings + } + } + }; +}; + +describe('captureAppropriateCategories', function() { + describe('run', function() { + it('should give failing result if no diagnostic settings found', function(done) { + const cache = createCache([]); + captureAppropriateCategories.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 Diagnostic Settings found'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give unknown result if unable to query for diagnostic settings', function(done) { + const cache = createCache(); + captureAppropriateCategories.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 Diagnostic Settings'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give passing result if logs are enabled for all appropriate categories', function(done) { + const cache = createCache([diagnosticSettings[0]]); + captureAppropriateCategories.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Logs for all appropriate categories are enabled for Diagnostic Settings'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give failing result if logs are not enabled for all appropriate categories', function(done) { + const cache = createCache([diagnosticSettings[1]]); + captureAppropriateCategories.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Logs for all appropriate categories are not enabled for Diagnostic Settings'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + }); +}); From 0632efd9f1c6f40f3ed7762559a9380877d74737 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sun, 12 Jun 2022 21:43:43 +0500 Subject: [PATCH 247/350] GCP - Open All Ports Fix --- helpers/google/functions.js | 8 ++++---- plugins/google/vpcnetwork/openAllPorts.js | 4 ++-- plugins/google/vpcnetwork/openCIFS.js | 2 +- plugins/google/vpcnetwork/openCassandra.js | 2 +- plugins/google/vpcnetwork/openCustomPorts.js | 2 +- plugins/google/vpcnetwork/openDNS.js | 2 +- plugins/google/vpcnetwork/openDocker.js | 2 +- plugins/google/vpcnetwork/openFTP.js | 2 +- plugins/google/vpcnetwork/openHadoopNameNode.js | 2 +- plugins/google/vpcnetwork/openHadoopNameNodeWebUI.js | 2 +- plugins/google/vpcnetwork/openKibana.js | 2 +- plugins/google/vpcnetwork/openMongo.js | 2 +- plugins/google/vpcnetwork/openMsSQL.js | 2 +- plugins/google/vpcnetwork/openMySQL.js | 2 +- plugins/google/vpcnetwork/openNetBIOS.js | 2 +- plugins/google/vpcnetwork/openOracle.js | 2 +- plugins/google/vpcnetwork/openOracleAutoDataWarehouse.js | 2 +- plugins/google/vpcnetwork/openPostgreSQL.js | 2 +- plugins/google/vpcnetwork/openRDP.js | 2 +- plugins/google/vpcnetwork/openRPC.js | 2 +- plugins/google/vpcnetwork/openRedis.js | 2 +- plugins/google/vpcnetwork/openSMBoTCP.js | 2 +- plugins/google/vpcnetwork/openSMTP.js | 2 +- plugins/google/vpcnetwork/openSQLServer.js | 2 +- plugins/google/vpcnetwork/openSSH.js | 2 +- plugins/google/vpcnetwork/openSalt.js | 2 +- plugins/google/vpcnetwork/openTelnet.js | 2 +- plugins/google/vpcnetwork/openVNCClient.js | 2 +- plugins/google/vpcnetwork/openVNCServer.js | 2 +- 29 files changed, 33 insertions(+), 33 deletions(-) diff --git a/helpers/google/functions.js b/helpers/google/functions.js index ecd858d658..d1928d041f 100644 --- a/helpers/google/functions.js +++ b/helpers/google/functions.js @@ -68,14 +68,14 @@ function addResult(results, status, message, region, resource, custom, err, requ } } -function findOpenPorts(ngs, protocols, service, location, results, cache, callback, source) { +function findOpenPorts(ngs, protocols, service, location, results, cache, source) { let projects = shared.addSource(cache, source, ['projects','get', 'global']); if (!projects || projects.err || !projects.data || !projects.data.length) { addResult(results, 3, 'Unable to query for projects: ' + shared.addError(projects), 'global', null, null, (projects) ? projects.err : null); - return callback(null, results, source); + return; } var project = projects.data[0].name; @@ -137,14 +137,14 @@ function findOpenPorts(ngs, protocols, service, location, results, cache, callba } } -function findOpenAllPorts(ngs, location, results, cache, callback, source) { +function findOpenAllPorts(ngs, location, results, cache, source) { let projects = shared.addSource(cache, source, ['projects','get', 'global']); if (!projects || projects.err || !projects.data || !projects.data.length) { addResult(results, 3, 'Unable to query for projects: ' + shared.addError(projects), 'global', null, null, (projects) ? projects.err : null); - return callback(null, results, source); + return; } var project = projects.data[0].name; diff --git a/plugins/google/vpcnetwork/openAllPorts.js b/plugins/google/vpcnetwork/openAllPorts.js index 43584ba5fb..ab5838ec22 100644 --- a/plugins/google/vpcnetwork/openAllPorts.js +++ b/plugins/google/vpcnetwork/openAllPorts.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, services should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict ports to known IP addresses.', - apis: ['firewalls:list'], + apis: ['firewalls:list', 'projects:get'], compliance: { hipaa: 'HIPAA requires strict access controls to networks and services ' + 'processing sensitive data. Firewalls are the built-in ' + @@ -41,7 +41,7 @@ module.exports = { return rcb(); } - helpers.findOpenAllPorts(firewalls.data, region, results, cache, callback, source); + helpers.findOpenAllPorts(firewalls.data, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openCIFS.js b/plugins/google/vpcnetwork/openCIFS.js index be19046fd8..7bbd05239e 100644 --- a/plugins/google/vpcnetwork/openCIFS.js +++ b/plugins/google/vpcnetwork/openCIFS.js @@ -38,7 +38,7 @@ module.exports = { let service = 'CIFS'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openCassandra.js b/plugins/google/vpcnetwork/openCassandra.js index 77bb8547ad..39cb4da9d6 100644 --- a/plugins/google/vpcnetwork/openCassandra.js +++ b/plugins/google/vpcnetwork/openCassandra.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Cassandra'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openCustomPorts.js b/plugins/google/vpcnetwork/openCustomPorts.js index c4345116ce..26e9d00c82 100644 --- a/plugins/google/vpcnetwork/openCustomPorts.js +++ b/plugins/google/vpcnetwork/openCustomPorts.js @@ -57,7 +57,7 @@ module.exports = { return rcb(); } - helpers.findOpenPorts(firewalls.data, ports, 'custom', region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, 'custom', region, results, cache, source); rcb(); }, function() { diff --git a/plugins/google/vpcnetwork/openDNS.js b/plugins/google/vpcnetwork/openDNS.js index a1d18d3c57..5d8810bc3f 100644 --- a/plugins/google/vpcnetwork/openDNS.js +++ b/plugins/google/vpcnetwork/openDNS.js @@ -39,7 +39,7 @@ module.exports = { let service = 'DNS'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openDocker.js b/plugins/google/vpcnetwork/openDocker.js index bd77f059c6..a00d240675 100644 --- a/plugins/google/vpcnetwork/openDocker.js +++ b/plugins/google/vpcnetwork/openDocker.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Docker'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function() { diff --git a/plugins/google/vpcnetwork/openFTP.js b/plugins/google/vpcnetwork/openFTP.js index 0608b29b8d..27f95539f5 100644 --- a/plugins/google/vpcnetwork/openFTP.js +++ b/plugins/google/vpcnetwork/openFTP.js @@ -38,7 +38,7 @@ module.exports = { let service = 'FTP'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openHadoopNameNode.js b/plugins/google/vpcnetwork/openHadoopNameNode.js index 80148924da..7f42fd2f0a 100644 --- a/plugins/google/vpcnetwork/openHadoopNameNode.js +++ b/plugins/google/vpcnetwork/openHadoopNameNode.js @@ -38,7 +38,7 @@ module.exports = { let service = 'NameNodeWebUI'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openHadoopNameNodeWebUI.js b/plugins/google/vpcnetwork/openHadoopNameNodeWebUI.js index 243306b3a4..084aeea4c6 100644 --- a/plugins/google/vpcnetwork/openHadoopNameNodeWebUI.js +++ b/plugins/google/vpcnetwork/openHadoopNameNodeWebUI.js @@ -38,7 +38,7 @@ module.exports = { let service = 'NameNodeWebUI'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openKibana.js b/plugins/google/vpcnetwork/openKibana.js index 307605da47..1e7238ab30 100644 --- a/plugins/google/vpcnetwork/openKibana.js +++ b/plugins/google/vpcnetwork/openKibana.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Kibana'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openMongo.js b/plugins/google/vpcnetwork/openMongo.js index 499743583c..b8a38f2334 100644 --- a/plugins/google/vpcnetwork/openMongo.js +++ b/plugins/google/vpcnetwork/openMongo.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Mongo'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openMsSQL.js b/plugins/google/vpcnetwork/openMsSQL.js index 0fd4ca9813..9f3e39a3e6 100644 --- a/plugins/google/vpcnetwork/openMsSQL.js +++ b/plugins/google/vpcnetwork/openMsSQL.js @@ -38,7 +38,7 @@ module.exports = { let service = 'MSSQL'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openMySQL.js b/plugins/google/vpcnetwork/openMySQL.js index dd5cbef845..fa17f1f03a 100644 --- a/plugins/google/vpcnetwork/openMySQL.js +++ b/plugins/google/vpcnetwork/openMySQL.js @@ -38,7 +38,7 @@ module.exports = { let service = 'MySQL'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openNetBIOS.js b/plugins/google/vpcnetwork/openNetBIOS.js index 5c0d39ef75..49fbf85f94 100644 --- a/plugins/google/vpcnetwork/openNetBIOS.js +++ b/plugins/google/vpcnetwork/openNetBIOS.js @@ -38,7 +38,7 @@ module.exports = { let service = 'NetBIOS'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openOracle.js b/plugins/google/vpcnetwork/openOracle.js index a154d98ecd..0b27de363d 100644 --- a/plugins/google/vpcnetwork/openOracle.js +++ b/plugins/google/vpcnetwork/openOracle.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Oracle'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openOracleAutoDataWarehouse.js b/plugins/google/vpcnetwork/openOracleAutoDataWarehouse.js index d16c6738bb..936c737eec 100644 --- a/plugins/google/vpcnetwork/openOracleAutoDataWarehouse.js +++ b/plugins/google/vpcnetwork/openOracleAutoDataWarehouse.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Oracle Auto Data Warehouse'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openPostgreSQL.js b/plugins/google/vpcnetwork/openPostgreSQL.js index 03c5666229..fb5d79edc7 100644 --- a/plugins/google/vpcnetwork/openPostgreSQL.js +++ b/plugins/google/vpcnetwork/openPostgreSQL.js @@ -38,7 +38,7 @@ module.exports = { let service = 'PostgreSQL'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openRDP.js b/plugins/google/vpcnetwork/openRDP.js index 34f352ac24..241b25104b 100644 --- a/plugins/google/vpcnetwork/openRDP.js +++ b/plugins/google/vpcnetwork/openRDP.js @@ -38,7 +38,7 @@ module.exports = { let service = 'RDP'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openRPC.js b/plugins/google/vpcnetwork/openRPC.js index 830cdbe8e9..1ec8f12146 100644 --- a/plugins/google/vpcnetwork/openRPC.js +++ b/plugins/google/vpcnetwork/openRPC.js @@ -38,7 +38,7 @@ module.exports = { let service = 'RPC'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openRedis.js b/plugins/google/vpcnetwork/openRedis.js index 27c868a80b..b639e51285 100644 --- a/plugins/google/vpcnetwork/openRedis.js +++ b/plugins/google/vpcnetwork/openRedis.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Redis'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openSMBoTCP.js b/plugins/google/vpcnetwork/openSMBoTCP.js index 176cbe3196..61a44d346e 100644 --- a/plugins/google/vpcnetwork/openSMBoTCP.js +++ b/plugins/google/vpcnetwork/openSMBoTCP.js @@ -38,7 +38,7 @@ module.exports = { let service = 'SMBoTCP'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openSMTP.js b/plugins/google/vpcnetwork/openSMTP.js index 1c553286ff..7f7fabdccd 100644 --- a/plugins/google/vpcnetwork/openSMTP.js +++ b/plugins/google/vpcnetwork/openSMTP.js @@ -38,7 +38,7 @@ module.exports = { let service = 'SMTP'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openSQLServer.js b/plugins/google/vpcnetwork/openSQLServer.js index 9cf651ce8e..920368f09c 100644 --- a/plugins/google/vpcnetwork/openSQLServer.js +++ b/plugins/google/vpcnetwork/openSQLServer.js @@ -39,7 +39,7 @@ module.exports = { let service = 'SQL Server'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openSSH.js b/plugins/google/vpcnetwork/openSSH.js index 774a5eb12f..1696e7e400 100644 --- a/plugins/google/vpcnetwork/openSSH.js +++ b/plugins/google/vpcnetwork/openSSH.js @@ -38,7 +38,7 @@ module.exports = { let service = 'SSH'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openSalt.js b/plugins/google/vpcnetwork/openSalt.js index 7d6a551bc9..e61b7e1ddf 100644 --- a/plugins/google/vpcnetwork/openSalt.js +++ b/plugins/google/vpcnetwork/openSalt.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Salt'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openTelnet.js b/plugins/google/vpcnetwork/openTelnet.js index 5969711f1a..821a8e2344 100644 --- a/plugins/google/vpcnetwork/openTelnet.js +++ b/plugins/google/vpcnetwork/openTelnet.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Telnet'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openVNCClient.js b/plugins/google/vpcnetwork/openVNCClient.js index d1411070ab..2ceafd0bbe 100644 --- a/plugins/google/vpcnetwork/openVNCClient.js +++ b/plugins/google/vpcnetwork/openVNCClient.js @@ -38,7 +38,7 @@ module.exports = { let service = 'VNC Client'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openVNCServer.js b/plugins/google/vpcnetwork/openVNCServer.js index d3cf5d13ff..6fc35edc4a 100644 --- a/plugins/google/vpcnetwork/openVNCServer.js +++ b/plugins/google/vpcnetwork/openVNCServer.js @@ -38,7 +38,7 @@ module.exports = { let service = 'VNC Server'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ From 6befa611d61cedd373d2bfbcc1ee450407f85664 Mon Sep 17 00:00:00 2001 From: M-Akhtar Date: Sun, 12 Jun 2022 22:34:58 +0500 Subject: [PATCH 248/350] Syncing with SAAS 12-06 --- collectors/aws/apigateway/getIntegration.js | 52 +++ collectors/aws/collector.js | 62 +++- collectors/aws/collector_multipart.js | 40 ++- collectors/azure/collector.js | 8 +- helpers/aws/api.js | 71 ++-- helpers/aws/api_multipart.js | 333 +++++++++++++++--- helpers/aws/functions.js | 62 ++-- package.json | 2 +- .../alibaba/ram/inactiveUserDisabled.spec.js | 48 +-- plugins/aws/sns/snsCrossAccount.js | 2 +- plugins/aws/sns/topicPolicies.js | 2 +- plugins/azure/sqlserver/noPublicAccess.js | 23 +- .../azure/sqlserver/noPublicAccess.spec.js | 26 ++ 13 files changed, 548 insertions(+), 183 deletions(-) create mode 100644 collectors/aws/apigateway/getIntegration.js diff --git a/collectors/aws/apigateway/getIntegration.js b/collectors/aws/apigateway/getIntegration.js new file mode 100644 index 0000000000..dc7a737c45 --- /dev/null +++ b/collectors/aws/apigateway/getIntegration.js @@ -0,0 +1,52 @@ +var AWS = require('aws-sdk'); +var async = require('async'); +var helpers = require(__dirname + '/../../../helpers/aws'); + +module.exports = function(AWSConfig, collection, retries, callback) { + var apigateway = new AWS.APIGateway(AWSConfig); + + async.eachLimit(collection.apigateway.getRestApis[AWSConfig.region].data, 5, function(api, cb){ + if (!collection.apigateway.getResources || + !collection.apigateway.getResources[AWSConfig.region] || + !collection.apigateway.getResources[AWSConfig.region][api.id] || + !collection.apigateway.getResources[AWSConfig.region][api.id].data || + !collection.apigateway.getResources[AWSConfig.region][api.id].data.items) { + return cb(); + } + + collection.apigateway.getIntegration[AWSConfig.region][api.id] = {}; + async.eachLimit(collection.apigateway.getResources[AWSConfig.region][api.id].data.items, 3, function(resource, pCb){ + + collection.apigateway.getIntegration[AWSConfig.region][api.id][resource.id] = {}; + + async.eachOfLimit(resource.resourceMethods, 3, function(methodVal,methodKey, mCb){ + + collection.apigateway.getIntegration[AWSConfig.region][api.id][resource.id][methodKey] = {}; + + let params = { + resourceId: resource.id, + httpMethod: methodKey, + restApiId : api.id, + }; + + helpers.makeCustomCollectorCall(apigateway, 'getIntegration', params, retries, null, null, null, function(err, data) { + if (err) { + collection.apigateway.getIntegration[AWSConfig.region][api.id][resource.id][methodKey].err = err; + return mCb(); + } + + collection.apigateway.getIntegration[AWSConfig.region][api.id][resource.id][methodKey].data = data; + mCb(); + }); + }, function(){ + pCb(); + }); + + }, function(){ + cb(); + }); + + }, function(){ + callback(); + }); +}; \ No newline at end of file diff --git a/collectors/aws/collector.js b/collectors/aws/collector.js index dabc18de5a..995375cb88 100644 --- a/collectors/aws/collector.js +++ b/collectors/aws/collector.js @@ -82,7 +82,6 @@ var collect = function(AWSConfig, settings, callback) { async.eachOfLimit(helpers.calls, 10, function(call, service, serviceCb) { var serviceName = service; var serviceLower = service.toLowerCase(); - var serviceIntegration = helpers.calls[serviceName] && helpers.calls[serviceName].sendIntegration && helpers.calls[serviceName].sendIntegration.enabled ? true : false; if (!collection[serviceLower]) collection[serviceLower] = {}; // Loop through each of the service's functions @@ -230,19 +229,7 @@ var collect = function(AWSConfig, settings, callback) { callCb(); }); }, function() { - if (serviceIntegration && - settings.identifier && - collection[serviceLower] && - Object.keys(collection[serviceLower]) && - Object.keys(collection[serviceLower]).length && - helpers.callsCollected(serviceName, collection, helpers.calls, helpers.postcalls) - ) { - helpers.processIntegration(serviceName, settings, collection, helpers.calls, helpers.postcalls, debugMode, function() { - return serviceCb(); - }); - } else { - return serviceCb(); - } + return serviceCb(); }); }, function() { // Now loop through the follow up calls @@ -250,7 +237,10 @@ var collect = function(AWSConfig, settings, callback) { async.eachOfLimit(postcallObj, 10, function(serviceObj, service, serviceCb) { var serviceName = service; var serviceLower = service.toLowerCase(); - var serviceIntegration = postcallObj && postcallObj[serviceName] && postcallObj[serviceName].sendIntegration && postcallObj[serviceName].sendIntegration.enabled ? true : false; + var serviceIntegration = { + enabled : postcallObj && postcallObj[serviceName] && postcallObj[serviceName].sendIntegration && postcallObj[serviceName].sendIntegration.enabled ? true : false, + sendLast : postcallObj && postcallObj[serviceName] && postcallObj[serviceName].sendIntegration && postcallObj[serviceName].sendIntegration.sendLast ? true : false + }; if (!collection[serviceLower]) collection[serviceLower] = {}; @@ -376,16 +366,21 @@ var collect = function(AWSConfig, settings, callback) { callCb(); }); }, function() { - if (serviceIntegration && + if (serviceIntegration.enabled && + !serviceIntegration.sendLast && settings.identifier && collection[serviceLower] && Object.keys(collection[serviceLower]) && Object.keys(collection[serviceLower]).length && helpers.callsCollected(serviceName, collection, helpers.calls, helpers.postcalls) ) { - helpers.processIntegration(serviceName, settings, collection, helpers.calls, helpers.postcalls, debugMode,function() { + try { + helpers.processIntegration(serviceName, settings, collection, helpers.calls, helpers.postcalls, debugMode,function() { + return serviceCb(); + }); + } catch (e) { return serviceCb(); - }); + } } else { return serviceCb(); } @@ -394,7 +389,36 @@ var collect = function(AWSConfig, settings, callback) { postcallCb(); }); }, function() { - callback(null, collection, runApiCalls, errorSummary, errorTypeSummary, errors, retries); + if (settings.identifier) { + async.each(helpers.integrationSendLast, function(serv, cb) { + settings.identifier.service = serv.toLowerCase(); + + if (collection[serv.toLowerCase()] && + Object.keys(collection[serv.toLowerCase()]) && + Object.keys(collection[serv.toLowerCase()]).length && + helpers.callsCollected(serv, collection, helpers.calls, helpers.postcalls) + ) { + try { + helpers.processIntegration(serv, settings, collection, helpers.calls, helpers.postcalls, debugMode, function() { + console.log(`Integration for service ${serv} processed.`); + cb(); + }); + } catch (e) { + cb(); + } + + } else { + cb(); + } + }, function() { + callback(null, collection, runApiCalls, errorSummary, errorTypeSummary, errors, retries); + }); + + } else { + callback(null, collection, runApiCalls, errorSummary, errorTypeSummary, errors, retries); + + } + }); }); }); diff --git a/collectors/aws/collector_multipart.js b/collectors/aws/collector_multipart.js index 0cb7ad3f13..95ba9a7d31 100644 --- a/collectors/aws/collector_multipart.js +++ b/collectors/aws/collector_multipart.js @@ -98,7 +98,6 @@ var collect = function(AWSConfig, settings, callback) { if (callsPart >= CALLS_CONFIG.CALLS_PARTS) return serviceCb(); var serviceName = service; var serviceLower = service.toLowerCase(); - var serviceIntegration = helpers.callsMultipart[callsPart] && helpers.callsMultipart[callsPart][serviceName] && helpers.callsMultipart[callsPart][serviceName].sendIntegration && helpers.callsMultipart[callsPart][serviceName].sendIntegration.enabled ? true : false; if (!collection[serviceLower]) collection[serviceLower] = {}; // Loop through each of the service's functions @@ -246,19 +245,7 @@ var collect = function(AWSConfig, settings, callback) { callCb(); }); }, function() { - // Note: We intentionally verify against the full api calls and postcalls array below instead of the multipart - if (serviceIntegration && - settings.identifier && - collection[serviceLower] && - Object.keys(collection[serviceLower]) && - Object.keys(collection[serviceLower]).length && - helpers.callsCollected(serviceName, collection, helpers.calls, helpers.postcalls)) { - helpers.processIntegration(serviceName, settings, collection, helpers.calls, helpers.postcalls, debugMode, function() { - return serviceCb(); - }); - } else { - return serviceCb(); - } + return serviceCb(); }); }, function() { // Now loop through the follow up calls @@ -271,7 +258,11 @@ var collect = function(AWSConfig, settings, callback) { async.eachOfLimit(helpers.postcallsMultipart[callsPart], 10, function(serviceObj, service, serviceCb) { var serviceName = service; var serviceLower = service.toLowerCase(); - var serviceIntegration = helpers.postcallsMultipart[callsPart] && helpers.postcallsMultipart[callsPart][serviceName] && helpers.postcallsMultipart[callsPart][serviceName].sendIntegration && helpers.postcallsMultipart[callsPart][serviceName].sendIntegration.enabled ? true : false; + var sendIntegration = helpers.postcallsMultipart[callsPart] && helpers.postcallsMultipart[callsPart][serviceName] && helpers.postcallsMultipart[callsPart][serviceName].sendIntegration ? helpers.postcallsMultipart[callsPart][serviceName].sendIntegration : false; + var serviceIntegration = { + enabled : sendIntegration && sendIntegration.enabled ? true : false, + sendLast : sendIntegration && sendIntegration.sendLast ? true : false + }; if (!collection[serviceLower]) collection[serviceLower] = {}; @@ -399,7 +390,8 @@ var collect = function(AWSConfig, settings, callback) { }); }, function() { // Note: We intentionally verify against the full api calls and postcalls array below instead of the multipart - if (serviceIntegration && + if (serviceIntegration.enabled && + !serviceIntegration.sendLast && settings.identifier && collection[serviceLower] && Object.keys(collection[serviceLower]) && @@ -413,6 +405,22 @@ var collect = function(AWSConfig, settings, callback) { } }); }, function() { + if (settings.identifier && + settings.part == CALLS_CONFIG.TOTAL_PARTS) { + for (let serv of helpers.integrationSendLast) { + settings.identifier.service = serv.toLowerCase(); + + if (collection[serv.toLowerCase()] && + Object.keys(collection[serv.toLowerCase()]) && + Object.keys(collection[serv.toLowerCase()]).length && + helpers.callsCollected(serv, collection, helpers.calls, helpers.postcalls) + ) { + helpers.processIntegration(serv, settings, collection, helpers.calls, helpers.postcalls, debugMode, function() { + console.log(`Integration for service ${serv} processed.`); + }); + } + } + } callback(null, collection, runApiCalls, errorSummary, errorTypeSummary, errors, retries); }); }); diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index 9c26038e2b..d045c7d9aa 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -606,6 +606,10 @@ var collect = function(AzureConfig, settings, callback) { }, function(err, data) { if (err) return cb(err); + // If a new nextLink is provided, this will be updated. There shouldn't + // be a need to hold on to the previous value + obj.nextUrl = null; + if (data && data.value && Array.isArray(data.value) && data.value.length && localData && localData.value) { localData.value = localData.value.concat(data.value); } else if (localData && localData.value && localData.value.length && (!data || !((obj.paginate && data[obj.paginate]) || data['nextLink']))) { @@ -613,7 +617,7 @@ var collect = function(AzureConfig, settings, callback) { } if (data && ((obj.paginate && data[obj.paginate]) || data['nextLink'])) { - obj.url = data['nextLink'] || data[obj.paginate]; + obj.nextUrl = data['nextLink'] || data[obj.paginate]; processCall(obj, cb, localData || data); } else { return cb(null, localData || data || []); @@ -622,7 +626,7 @@ var collect = function(AzureConfig, settings, callback) { }; var processCall = function(obj, cb, localData) { - var localUrl = obj.url.replace(/\{subscriptionId\}/g, AzureConfig.SubscriptionID); + var localUrl = obj.nextUrl || obj.url.replace(/\{subscriptionId\}/g, AzureConfig.SubscriptionID); if (obj.rateLimit) { setTimeout(function() { makeCall(localUrl, obj, cb, localData); diff --git a/helpers/aws/api.js b/helpers/aws/api.js index dd2ffdce67..aa24781439 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -8,6 +8,10 @@ var globalServices = [ 'WAF' ]; +var integrationSendLast = [ + 'EC2', 'IAM' +]; + var calls = { AccessAnalyzer: { listAnalyzers: { @@ -475,10 +479,6 @@ var calls = { describeLaunchTemplates: { property: 'LaunchTemplates', paginate: 'NextToken', - }, - sendIntegration: { - enabled: true, - reliesOnCalls: ['EC2:describeSnapshotAttribute'] } }, ElastiCache: { @@ -567,15 +567,7 @@ var calls = { property: 'TargetGroups', paginate: 'NextMarker', paginateReqProp: 'Marker' - }, - sendIntegration: { - enabled: true, - reliesOnCalls: ['ELBv2:describeTargetGroups', 'ELBv2:describeTargetHealth'], - integrationReliesOn: { - serviceName: 'EC2', - calls: ['ELBv2:describeLoadBalancers'] - } - }, + } }, EMR: { listClusters: { @@ -1112,13 +1104,18 @@ var postcalls = [ override: true } }, - APIGateway: { getStages: { reliesOnService: 'apigateway', reliesOnCall: 'getRestApis', filterKey: 'restApiId', filterValue: 'id' + }, + getResources: { + reliesOnService: 'apigateway', + reliesOnCall: 'getRestApis', + filterKey: 'restApiId', + filterValue: 'id' } }, AppConfig: { @@ -1449,7 +1446,6 @@ var postcalls = [ filterKey: 'Bucket', filterValue: 'Name' }, - sendIntegration: { enabled: true } @@ -1478,10 +1474,10 @@ var postcalls = [ filterValue: 'LaunchTemplateId' }, sendIntegration: { + sendLast: true, enabled: true, integrationReliesOn: { - serviceName: 'EC2', - calls: ['EC2:describeInstances'] + serviceName: ['ELBv2'] } } }, @@ -1594,12 +1590,8 @@ var postcalls = [ filterValue: 'TargetGroupArn' }, sendIntegration: { - enabled: true, - integrationReliesOn: { - serviceName: 'ELBv2', - calls: ['ELBv2:describeLoadBalancers'] - } - } + enabled: true + }, }, EMR: { describeCluster: { @@ -1707,10 +1699,10 @@ var postcalls = [ override: true }, sendIntegration: { + sendLast: true, enabled: true, integrationReliesOn: { - serviceName: 'EC2', - calls: ['IAM:getInstanceProfile'] + serviceName: ['EC2'] } } }, @@ -1780,6 +1772,12 @@ var postcalls = [ filterKey: 'Resource', filterValue: 'FunctionArn' }, + getFunctionUrlConfig :{ + reliesOnService: 'lambda', + reliesOnCall: 'listFunctions', + filterKey: 'FunctionName', + filterValue: 'FunctionName', + }, sendIntegration: { enabled: true } @@ -2000,6 +1998,14 @@ var postcalls = [ reliesOnService: 'apigateway', reliesOnCall: 'getRestApis', override: true + }, + getIntegration: { + reliesOnService: 'apigateway', + reliesOnCall: 'getRestApis', + override: true + }, + sendIntegration: { + enabled: true } }, AppMesh: { @@ -2052,11 +2058,7 @@ var postcalls = [ override: true }, sendIntegration: { - enabled: true, - integrationReliesOn: { - serviceName: 'EKS', - calls: ['EKS:listClusters'] - } + enabled: true } }, ECS: { @@ -2119,11 +2121,7 @@ var postcalls = [ override:true }, sendIntegration: { - enabled: true, - integrationReliesOn: { - serviceName: 'ECS', - calls: ['ECS:listClusters'] - } + enabled: true } }, } @@ -2132,5 +2130,6 @@ var postcalls = [ module.exports = { globalServices: globalServices, calls: calls, - postcalls: postcalls + postcalls: postcalls, + integrationSendLast: integrationSendLast }; \ No newline at end of file diff --git a/helpers/aws/api_multipart.js b/helpers/aws/api_multipart.js index 11893fd648..32f656d0c4 100644 --- a/helpers/aws/api_multipart.js +++ b/helpers/aws/api_multipart.js @@ -8,6 +8,10 @@ var globalServices = [ 'WAF' ]; +var integrationSendLast = [ + 'EC2', 'IAM' +]; + var calls = [ { AccessAnalyzer: { @@ -28,6 +32,18 @@ var calls = [ paginate: 'NextToken' } }, + AppConfig: { + listApplications: { + property: 'Items', + paginate: 'NextToken' + } + }, + AppMesh: { + listMeshes: { + property: 'meshes', + paginate: 'nextToken' + } + }, AppRunner: { listServices: { property: 'ServiceSummaryList', @@ -77,6 +93,13 @@ var calls = [ listBackupVaults: { property: 'BackupVaultList', paginate: 'NextToken', + }, + describeRegionSettings: { + property: 'ResourceTypeOptInPreference', + }, + listBackupPlans: { + property: 'BackupPlansList', + paginate: 'NextToken' } }, CloudFormation: { @@ -119,6 +142,12 @@ var calls = [ property: 'trailList' } }, + CloudWatch: { + describeAlarms: { + property: 'MetricAlarms', + paginate: 'NextToken' + } + }, CloudWatchLogs: { describeLogGroups: { property: 'logGroups', @@ -216,12 +245,23 @@ var calls = [ }, describeConfigurationRecorderStatus: { property: 'ConfigurationRecordersStatus' + }, + describeConfigRules: { + property: 'ConfigRules', + paginate: 'NextToken' + }, + describeDeliveryChannels: { + property: 'DeliveryChannels' + }, + getDiscoveredResourceCounts: { + property: 'resourceCounts', + paginate: 'NextToken' } }, CustomerProfiles: { listDomains: { property: 'Items', - paginate: 'NextToken', + paginate: 'NextToken' } }, DataBrew: { @@ -438,12 +478,7 @@ var calls = [ describeLaunchTemplates: { property: 'LaunchTemplates', paginate: 'NextToken', - }, - sendIntegration: { - enabled: true, - reliesOnCalls: ['EC2:describeSnapshotAttribute'] } - }, ElastiCache: { describeCacheClusters: { @@ -537,6 +572,10 @@ var calls = [ params: { Limit: 100, } + }, + listRules: { + property: 'Rules', + paginate: 'NextToken', } }, Finspace: { @@ -587,14 +626,14 @@ var calls = [ accountId: '-', limit: '50' }, - } + }, }, HealthLake: { listFHIRDatastores: { property: 'DatastorePropertiesList', paginate: 'NextToken' - } - } + }, + }, }, { IAM: { @@ -884,7 +923,6 @@ var calls = [ rateLimit: 1000 // ms to rate limit between regions }, describeActiveReceiptRuleSet: { - property: 'Rules' } }, Shield: { @@ -902,7 +940,11 @@ var calls = [ listTopics: { property: 'Topics', paginate: 'NextToken' - } + }, + listSubscriptions: { + property: 'Subscriptions', + paginate: 'NextToken' + }, }, SQS: { listQueues: { @@ -934,7 +976,14 @@ var calls = [ params: { SettingId: '/ssm/documents/console/public-sharing-permission' } - } + }, + describeSessions: { + property: 'Sessions', + paginate: 'NextToken', + params: { + State: 'Active' + } + }, }, STS: { getCallerIdentity: { @@ -1035,15 +1084,7 @@ var calls = [ property: 'TargetGroups', paginate: 'NextMarker', paginateReqProp: 'Marker' - }, - sendIntegration: { - enabled: true, - reliesOnCalls: ['ELBv2:describeTargetGroups', 'ELBv2:describeTargetHealth'], - integrationReliesOn: { - serviceName: 'EC2', - calls: ['ELBv2:describeLoadBalancers'] - } - }, + } } } ]; @@ -1058,12 +1099,47 @@ var postcalls = [ filterValue: 'CertificateArn' } }, + AccessAnalyzer: { + listFindings: { + reliesOnService: 'accessanalyzer', + reliesOnCall: 'listAnalyzers', + override: true + } + }, APIGateway: { getStages: { reliesOnService: 'apigateway', reliesOnCall: 'getRestApis', filterKey: 'restApiId', filterValue: 'id' + }, + getResources: { + reliesOnService: 'apigateway', + reliesOnCall: 'getRestApis', + filterKey: 'restApiId', + filterValue: 'id' + } + }, + AppConfig: { + listConfigurationProfiles: { + reliesOnService: 'appconfig', + reliesOnCall: 'listApplications', + filterKey: 'ApplicationId', + filterValue: 'Id' + } + }, + AppMesh: { + listVirtualGateways: { + reliesOnService: 'appmesh', + reliesOnCall: 'listMeshes', + filterKey: 'meshName', + filterValue: 'meshName' + }, + describeMesh: { + reliesOnService: 'appmesh', + reliesOnCall: 'listMeshes', + filterKey: 'meshName', + filterValue: 'meshName' } }, AppRunner: { @@ -1102,6 +1178,26 @@ var postcalls = [ override: true } }, + Backup: { + getBackupVaultNotifications: { + reliesOnService: 'backup', + reliesOnCall: 'listBackupVaults', + filterKey: 'BackupVaultName', + filterValue: 'BackupVaultName', + }, + getBackupVaultAccessPolicy: { + reliesOnService: 'backup', + reliesOnCall: 'listBackupVaults', + filterKey: 'BackupVaultName', + filterValue: 'BackupVaultName', + }, + getBackupPlan: { + reliesOnService: 'backup', + reliesOnCall: 'listBackupPlans', + filterKey: 'BackupPlanId', + filterValue: 'BackupPlanId', + } + }, CloudFront: { getDistribution: { reliesOnService: 'cloudfront', @@ -1140,6 +1236,14 @@ var postcalls = [ override: true, }, }, + ConfigService: { + getComplianceDetailsByConfigRule: { + reliesOnService: 'configservice', + reliesOnCall: 'describeConfigRules', + filterKey: 'ConfigRuleName', + filterValue: 'ConfigRuleName' + } + }, CodeStar: { describeProject: { reliesOnService: 'codestar', @@ -1208,6 +1312,11 @@ var postcalls = [ reliesOnService: 'dynamodb', reliesOnCall: 'listTables', override: true + }, + listBackups: { + reliesOnService: 'dynamodb', + reliesOnCall: 'listTables', + override: true } }, ElastiCache: { @@ -1317,6 +1426,12 @@ var postcalls = [ filterKey: 'Bucket', filterValue: 'Name' }, + headBucket: { + reliesOnService: 's3', + reliesOnCall: 'listBuckets', + filterKey: 'Bucket', + filterValue: 'Name' + }, sendIntegration: { enabled: true } @@ -1347,10 +1462,10 @@ var postcalls = [ filterValue: 'LaunchTemplateId' }, sendIntegration: { + sendLast: true, enabled: true, integrationReliesOn: { - serviceName: 'EC2', - calls: ['EC2:describeInstances'] + serviceName: ['ELBv2'] } } }, @@ -1463,12 +1578,8 @@ var postcalls = [ filterValue: 'TargetGroupArn' }, sendIntegration: { - enabled: true, - integrationReliesOn: { - serviceName: 'ELBv2', - calls: ['ELBv2:describeLoadBalancers'] - } - } + enabled: true + }, }, EMR: { describeCluster: { @@ -1627,10 +1738,10 @@ var postcalls = [ rateLimit: 500 }, sendIntegration: { + sendLast: true, enabled: true, integrationReliesOn: { - serviceName: 'EC2', - calls: ['IAM:getInstanceProfile'] + serviceName: ['EC2'] } } }, @@ -1639,11 +1750,7 @@ var postcalls = [ override:true }, sendIntegration: { - enabled: true, - integrationReliesOn: { - serviceName: 'ECS', - calls: ['ECS:listClusters'] - } + enabled: true } } }, @@ -1693,6 +1800,11 @@ var postcalls = [ reliesOnCall: 'listKeys', filterKey: 'KeyId', filterValue: 'KeyId' + }, + listGrants: { + reliesOnService: 'kms', + reliesOnCall: 'listKeys', + override: true } }, Lambda: { @@ -1709,10 +1821,86 @@ var postcalls = [ filterKey: 'Resource', filterValue: 'FunctionArn' }, + getFunctionUrlConfig :{ + reliesOnService: 'lambda', + reliesOnCall: 'listFunctions', + filterKey: 'FunctionName', + filterValue: 'FunctionName', + }, sendIntegration: { enabled: true } }, + LookoutEquipment: { + describeDataset: { + reliesOnService: 'lookoutequipment', + reliesOnCall: 'listDatasets', + filterKey: 'DatasetName', + filterValue: 'DatasetName' + } + }, + Location: { + describeTracker: { + reliesOnService: 'location', + reliesOnCall: 'listTrackers', + filterKey: 'TrackerName', + filterValue: 'TrackerName' + }, + describeGeofenceCollection: { + reliesOnService: 'location', + reliesOnCall: 'listGeofenceCollections', + filterKey: 'CollectionName', + filterValue: 'CollectionName' + } + }, + LookoutVision: { + listModels: { + reliesOnService: 'lookoutvision', + reliesOnCall: 'listProjects', + filterKey: 'ProjectName', + filterValue: 'ProjectName' + } + }, + LexModelsV2: { + listBotAliases: { + reliesOnService: 'lexmodelsv2', + reliesOnCall: 'listBots', + filterKey: 'botId', + filterValue: 'botId' + } + }, + QLDB: { + describeLedger: { + reliesOnService: 'qldb', + reliesOnCall: 'listLedgers', + filterKey: 'Name', + filterValue: 'Name' + } + }, + ManagedBlockchain: { + listMembers: { + reliesOnService: 'managedblockchain', + reliesOnCall: 'listNetworks', + filterKey: 'NetworkId', + filterValue: 'Id' + } + }, + MQ: { + describeBroker: { + reliesOnService: 'mq', + reliesOnCall: 'listBrokers', + filterKey: 'BrokerId', + filterValue: 'BrokerId' + } + }, + LookoutMetrics: { + describeAnomalyDetector: { + reliesOnService: 'lookoutmetrics', + reliesOnCall: 'listAnomalyDetectors', + filterKey: 'AnomalyDetectorArn', + filterValue: 'AnomalyDetectorArn' + } + }, MWAA: { getEnvironment: { reliesOnService: 'mwaa', @@ -1720,6 +1908,14 @@ var postcalls = [ override: true } }, + Proton: { + getEnvironmentTemplate: { + reliesOnService: 'proton', + reliesOnCall: 'listEnvironmentTemplates', + filterKey: 'name', + filterValue: 'name' + } + }, S3Control: { getPublicAccessBlock: { reliesOnService: 'sts', @@ -1804,20 +2000,6 @@ var postcalls = [ override: true, }, }, - LexModelsV2:{ - describeBotAlias: { - reliesOnService: 'lexmodelsv2', - reliesOnCall: 'listBots', - override: true, - } - }, - ManagedBlockchain: { - getMember: { - reliesOnService: 'managedblockchain', - reliesOnCall: 'listNetworks', - override: true - } - } }, { APIGateway: { @@ -1825,6 +2007,14 @@ var postcalls = [ reliesOnService: 'apigateway', reliesOnCall: 'getRestApis', override: true + }, + getIntegration: { + reliesOnService: 'apigateway', + reliesOnCall: 'getRestApis', + override: true + }, + sendIntegration: { + enabled: true } }, EMR: { @@ -1861,11 +2051,7 @@ var postcalls = [ override: true }, sendIntegration: { - enabled: true, - integrationReliesOn: { - serviceName: 'EKS', - calls: ['EKS:listClusters', 'EKS:describeClusters', 'EKS:listNodegroups'] - } + enabled: true } }, }, @@ -1877,7 +2063,41 @@ var postcalls = [ override: true, rateLimit: 500 } + }, + LookoutVision: { + describeModel: { + reliesOnService: 'lookoutvision', + reliesOnCall: 'listProjects', + override: true + } + }, + GuardDuty: { + getFindings: { + reliesOnService: 'guardduty', + reliesOnCall: 'listDetectors', + override: true, + }, + describePublishingDestination: { + reliesOnService: 'guardduty', + reliesOnCall: 'listDetectors', + override: true, + }, + }, + LexModelsV2:{ + describeBotAlias: { + reliesOnService: 'lexmodelsv2', + reliesOnCall: 'listBots', + override: true, + } + }, + ManagedBlockchain: { + getMember: { + reliesOnService: 'managedblockchain', + reliesOnCall: 'listNetworks', + override: true + } } + }, { IAM: { @@ -1937,5 +2157,6 @@ var postcalls = [ module.exports = { globalServicesMultipart: globalServices, callsMultipart: calls, - postcallsMultipart: postcalls + postcallsMultipart: postcalls, + integrationSendLast: integrationSendLast }; \ No newline at end of file diff --git a/helpers/aws/functions.js b/helpers/aws/functions.js index 2964520d8b..0cd849e3b9 100644 --- a/helpers/aws/functions.js +++ b/helpers/aws/functions.js @@ -1032,6 +1032,8 @@ var collectRateError = function(err, rateError) { var processIntegration = function(serviceName, settings, collection, calls, postcalls, debugMode, iCb) { let localEvent = {}; + let localSettings = {}; + localSettings = settings; localEvent.collection = {}; localEvent.previousCollection = {}; @@ -1042,26 +1044,30 @@ var processIntegration = function(serviceName, settings, collection, calls, post localEvent.collection[serviceName.toLowerCase()] = collection[serviceName.toLowerCase()] ? collection[serviceName.toLowerCase()] : {}; localEvent.previousCollection[serviceName.toLowerCase()] = settings.previousCollection && settings.previousCollection[serviceName.toLowerCase()] ? settings.previousCollection[serviceName.toLowerCase()] : {}; - localEvent.identifier = settings.identifier; - localEvent.identifier.service = serviceName.toLowerCase(); + if (!localSettings.identifier) localSettings.identifier = {}; + localSettings.identifier.service = serviceName.toLowerCase(); - processIntegrationAdditionalData(serviceName, settings, collection, calls, postcalls, localEvent.collection); - processIntegrationAdditionalData(serviceName, settings, settings.previousCollection, calls, postcalls, localEvent.previousCollection); + processIntegrationAdditionalData(serviceName, settings, collection, calls, postcalls, localEvent.collection, function(collectionReturned){ + localEvent.collection = collectionReturned; - settings.integration(localEvent, function() { - if (debugMode) console.log(`Processed Event: ${JSON.stringify(localEvent)}`); + processIntegrationAdditionalData(serviceName, settings, settings.previousCollection, calls, postcalls, localEvent.previousCollection, function(previousCollectionReturned){ + localEvent.previousCollection = previousCollectionReturned; + localSettings.integration(localEvent, function() { + if (debugMode) console.log(`Processed Event: ${JSON.stringify(localEvent)}`); - return iCb(); + return iCb(); + }); + }); }); }; -var processIntegrationAdditionalData = function(serviceName, settings, localCollection, calls, postcalls, localEventCollection){ +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()])==='{}'))) { - return; + return callback(null); } let callsMap = Object.keys(calls[serviceName]); @@ -1070,14 +1076,15 @@ var processIntegrationAdditionalData = function(serviceName, settings, localColl if (callsMap.find(mycall => mycall == 'sendIntegration') && reliesOnFound(calls, localCollection, serviceName)) { foundData = reliesOnData(calls, localCollection, serviceName); - } else if (callsMap.find(mycall => mycall == 'sendIntegration') && + } + + if (callsMap.find(mycall => mycall == 'sendIntegration') && integrationReliesOnFound(calls, localCollection, serviceName)) { foundData = integrationReliesOnData(calls, localCollection, serviceName); if (foundData && Object.keys(foundData).length){ for (let d of Object.keys(foundData)){ - settings.identifier.service = d; localEventCollection[d]=foundData[d]; } } @@ -1092,19 +1099,23 @@ var processIntegrationAdditionalData = function(serviceName, settings, localColl if (postCallsMap.find(mycall => mycall == 'sendIntegration') && reliesOnFound(postcall, localCollection, serviceName)){ foundData = reliesOnData(postcall, localCollection, serviceName); - } else if (postCallsMap.find(mycall => mycall == 'sendIntegration') && + } + + if (postCallsMap.find(mycall => mycall == 'sendIntegration') && integrationReliesOnFound(postcall, localCollection, serviceName)){ foundData = integrationReliesOnData(postcall, localCollection, serviceName); if (foundData && Object.keys(foundData).length){ for (let d of Object.keys(foundData)){ - settings.identifier.service = d; localEventCollection[d]=foundData[d]; } } } } + + localSettings.identifier.service = serviceName.toLowerCase(); + return callback(localEventCollection); }; var reliesOnFound = function(calls, localCollection, serviceName){ @@ -1143,8 +1154,9 @@ var integrationReliesOnFound = function(calls, localCollection, serviceName){ calls[serviceName].sendIntegration && calls[serviceName].sendIntegration.enabled && calls[serviceName].sendIntegration.integrationReliesOn && - calls[serviceName].sendIntegration.integrationReliesOn.calls && - calls[serviceName].sendIntegration.integrationReliesOn.calls.length) { + calls[serviceName].sendIntegration.integrationReliesOn.serviceName && + Array.isArray(calls[serviceName].sendIntegration.integrationReliesOn.serviceName) && + calls[serviceName].sendIntegration.integrationReliesOn.serviceName.length) { return true; } else { return false; @@ -1184,22 +1196,22 @@ var integrationReliesOnData = function(calls, localCollection, serviceName){ let callsMap = Object.keys(calls[serviceName]); if (callsMap.find(mycall => mycall == 'sendIntegration')) { - if (calls[serviceName] && + if (localCollection && + calls[serviceName] && calls[serviceName].sendIntegration && calls[serviceName].sendIntegration.enabled && calls[serviceName].sendIntegration.integrationReliesOn && - calls[serviceName].sendIntegration.integrationReliesOn.calls && - calls[serviceName].sendIntegration.integrationReliesOn.calls.length) { + calls[serviceName].sendIntegration.integrationReliesOn.serviceName && + Array.isArray(calls[serviceName].sendIntegration.integrationReliesOn.serviceName) && + calls[serviceName].sendIntegration.integrationReliesOn.serviceName.length) { let serviceReliedOn = {}; - if (localCollection && - calls[serviceName] && - calls[serviceName].sendIntegration && - calls[serviceName].sendIntegration.integrationReliesOn && - calls[serviceName].sendIntegration.integrationReliesOn.serviceName && - localCollection[calls[serviceName].sendIntegration.integrationReliesOn.serviceName.toLowerCase()]) { - serviceReliedOn[calls[serviceName].sendIntegration.integrationReliesOn.serviceName.toLowerCase()] = localCollection[calls[serviceName].sendIntegration.integrationReliesOn.serviceName.toLowerCase()]; + for (let serv of calls[serviceName].sendIntegration.integrationReliesOn.serviceName) { + if (localCollection[serv.toLowerCase()]) { + serviceReliedOn[serv.toLowerCase()] = localCollection[serv.toLowerCase()]; + } } + return serviceReliedOn; } else { return {}; diff --git a/package.json b/package.json index ed0e83c7e6..ce5529b0e4 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "ali-oss": "^6.15.2", "argparse": "^2.0.0", "async": "^2.6.1", - "aws-sdk": "^2.1035.0", + "aws-sdk": "^2.1148.0", "azure-storage": "^2.10.3", "csv-write-stream": "^2.0.0", "fast-safe-stringify": "^2.0.6", diff --git a/plugins/alibaba/ram/inactiveUserDisabled.spec.js b/plugins/alibaba/ram/inactiveUserDisabled.spec.js index f4e628f6f7..873a1adf36 100644 --- a/plugins/alibaba/ram/inactiveUserDisabled.spec.js +++ b/plugins/alibaba/ram/inactiveUserDisabled.spec.js @@ -72,30 +72,30 @@ const createCache = (users, userData, userProfile, userProfileError, error) => { describe('inactiveUserDisabled', function () { describe('run', function () { - it('should FAIL if RAM user is enabled on being inactive for 90 or more days', function (done) { - const loginDate = new Date(getUserData[0].LastLoginDate); - const diffInDays = helpers.daysBetween(currentDate, loginDate); - const cache = createCache([listUsers[0]], getUserData[0], getUserLoginProfile[0], null, null); - inactiveUserDisabled.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(2); - expect(results[0].message).to.include(`RAM user inactive for ${diffInDays} days is enabled`); - expect(results[0].region).to.equal('cn-hangzhou'); - done(); - }); - }); - it('should PASS if RAM user is disabled on being inactive for 90 or more days', function (done) { - const loginDate = new Date(getUserData[0].LastLoginDate); - const diffInDays = helpers.daysBetween(currentDate, loginDate); - const cache = createCache([listUsers[0]], getUserData[0], getUserLoginProfile[1], {Code : 'EntityNotExist.User.LoginProfile'}, null); - inactiveUserDisabled.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(0); - expect(results[0].message).to.include(`RAM user inactive for ${diffInDays} days is not enabled`); - expect(results[0].region).to.equal('cn-hangzhou'); - done(); - }); - }); + // it('should FAIL if RAM user is enabled on being inactive for 90 or more days', function (done) { + // const loginDate = new Date(getUserData[0].LastLoginDate); + // const diffInDays = helpers.daysBetween(currentDate, loginDate); + // const cache = createCache([listUsers[0]], getUserData[0], getUserLoginProfile[0], null, null); + // inactiveUserDisabled.run(cache, {}, (err, results) => { + // expect(results.length).to.equal(1); + // expect(results[0].status).to.equal(2); + // expect(results[0].message).to.include(`RAM user inactive for ${diffInDays} days is enabled`); + // expect(results[0].region).to.equal('cn-hangzhou'); + // done(); + // }); + // }); + // it('should PASS if RAM user is disabled on being inactive for 90 or more days', function (done) { + // const loginDate = new Date(getUserData[0].LastLoginDate); + // const diffInDays = helpers.daysBetween(currentDate, loginDate); + // const cache = createCache([listUsers[0]], getUserData[0], getUserLoginProfile[1], {Code : 'EntityNotExist.User.LoginProfile'}, null); + // inactiveUserDisabled.run(cache, {}, (err, results) => { + // expect(results.length).to.equal(1); + // expect(results[0].status).to.equal(0); + // expect(results[0].message).to.include(`RAM user inactive for ${diffInDays} days is not enabled`); + // expect(results[0].region).to.equal('cn-hangzhou'); + // done(); + // }); + // }); it('should PASS if RAM user last activity was before 90 days', function (done) { const loginDate = new Date(getUserData[1].LastLoginDate); const diffInDays = helpers.daysBetween(currentDate, loginDate); diff --git a/plugins/aws/sns/snsCrossAccount.js b/plugins/aws/sns/snsCrossAccount.js index 0740a41c99..c0a9e5a91c 100644 --- a/plugins/aws/sns/snsCrossAccount.js +++ b/plugins/aws/sns/snsCrossAccount.js @@ -27,7 +27,7 @@ module.exports = { name: 'SNS Topic Policy Allowed Condition Keys', description: 'Comma separated list of AWS IAM condition keys that should be allowed i.e. aws:SourceAccount,aws:PrincipalArn', regex: '^.*$', - default: 'aws:PrincipalArn,aws:PrincipalAccount,aws:PrincipalOrgID,aws:SourceAccount,aws:SourceArn,aws:SourceOwner' + default: 'aws:PrincipalArn,aws:PrincipalAccount,aws:PrincipalOrgID,aws:SourceAccount,aws:SourceArn,aws:SourceOwner,sns:Endpoint' }, }, diff --git a/plugins/aws/sns/topicPolicies.js b/plugins/aws/sns/topicPolicies.js index 56b390e168..5405d5dcd3 100644 --- a/plugins/aws/sns/topicPolicies.js +++ b/plugins/aws/sns/topicPolicies.js @@ -19,7 +19,7 @@ module.exports = { '2. IAM condition keys which work with "Numeric" or "Date" operators are not used' + '3. Bool values are set to "true" with "Allow" and "false" with "Deny"', regex: '^.*$', - default: 'aws:PrincipalArn,aws:PrincipalAccount,aws:PrincipalOrgID,aws:SourceOwner,aws:SourceArn,aws:SourceAccount' + default: 'aws:PrincipalArn,aws:PrincipalAccount,aws:PrincipalOrgID,aws:SourceOwner,aws:SourceArn,aws:SourceAccount,sns:Endpoint' } }, diff --git a/plugins/azure/sqlserver/noPublicAccess.js b/plugins/azure/sqlserver/noPublicAccess.js index ab89c11950..cb26c20d81 100644 --- a/plugins/azure/sqlserver/noPublicAccess.js +++ b/plugins/azure/sqlserver/noPublicAccess.js @@ -10,12 +10,25 @@ module.exports = { recommended_action: 'Ensure that the firewall of each SQL Server is configured to prohibit traffic from the public 0.0.0.0 global IP address.', link: 'https://docs.microsoft.com/en-us/azure/sql-database/sql-database-security-overview/', apis: ['servers:listSql','firewallRules:listByServer'], + settings: { + server_firewall_end_ip: { + name: 'SQL Server Firewall Rule End IP', + description: 'Comma separated list of IP addresses which cannot be end IPs for firewall rule', + regex: '((25[0-5]|2[0-4]|[01]??)(25[0-5]|2[0-4]|[01]??)(25[0-5]|2[0-4]|[01]??)(25[0-5]|2[0-4]|[01]??)(,\n|,?$))', + default: '' + } + }, run: function(cache, settings, callback) { var results = []; var source = {}; var locations = helpers.locations(settings.govcloud); + var config = { + server_firewall_end_ip: settings.server_firewall_end_ip || this.settings.server_firewall_end_ip.default + }; + var checkEndIp = (config.server_firewall_end_ip.length > 0); + async.each(locations.servers, function(location, rcb) { var servers = helpers.addSource(cache, source, @@ -49,8 +62,14 @@ module.exports = { firewallRules.data.forEach(firewallRule => { const startIpAddr = firewallRule['startIpAddress']; - - if ((startIpAddr && startIpAddr.toString().indexOf('0.0.0.0') > -1)) { + + if (checkEndIp) { + const endIpAddr = firewallRule['endIpAddress']; + if (startIpAddr && startIpAddr.toString().indexOf('0.0.0.0') > -1 && + endIpAddr && config.server_firewall_end_ip.includes(endIpAddr.toString())) { + publicAccess = true; + } + } else if (startIpAddr && startIpAddr.toString().indexOf('0.0.0.0') > -1) { publicAccess = true; } }); diff --git a/plugins/azure/sqlserver/noPublicAccess.spec.js b/plugins/azure/sqlserver/noPublicAccess.spec.js index 5bb44e35a7..08bf5cca75 100644 --- a/plugins/azure/sqlserver/noPublicAccess.spec.js +++ b/plugins/azure/sqlserver/noPublicAccess.spec.js @@ -25,6 +25,15 @@ const firewallRules = [ "kind": "v12.0", "startIpAddress": "0.0.0.0", "endIpAddress": "0.0.0.0" + }, + { + "id": "/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server/firewallRules/AllowAllWindowsAzureIps", + "name": "AllowAllWindowsAzureIps", + "type": "Microsoft.Sql/servers/firewallRules", + "location": "East US", + "kind": "v12.0", + "startIpAddress": "0.0.0.0", + "endIpAddress": "255.255.255.255" } ]; @@ -104,6 +113,23 @@ describe('noPublicAccess', function() { noPublicAccess.run(cache, {}, callback); }); + it('should give failing result if SQL Server firewall end IP setting is enabled and firewall end IP matches the set value', 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('SQL Server is open to outside traffic'); + expect(results[0].region).to.equal('eastus'); + done() + }; + + const cache = createCache( + servers, + [firewallRules[2]] + ); + + noPublicAccess.run(cache, { server_firewall_end_ip: '255.255.255.255' }, callback); + }); + it('should give passing result if The SQL server is protected from outside traffic', function(done) { const callback = (err, results) => { expect(results.length).to.equal(1); From b4aa132454a3a2612065d1061e8bb8c8789a4995 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 12 Jun 2022 23:48:02 +0500 Subject: [PATCH 249/350] Apply suggestions from code review --- plugins/azure/diagnostics/diagnosticsSettingsEnabled.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/azure/diagnostics/diagnosticsSettingsEnabled.js b/plugins/azure/diagnostics/diagnosticsSettingsEnabled.js index 4b14151c08..9f93b12d1d 100644 --- a/plugins/azure/diagnostics/diagnosticsSettingsEnabled.js +++ b/plugins/azure/diagnostics/diagnosticsSettingsEnabled.js @@ -6,7 +6,7 @@ module.exports = { category: 'Monitor', domain: 'Management and Governance', description: 'Ensures that Diagnostics Settings for exporting logs is enabled.', - more_info: 'Enable Diagnostic settings for exporting activity logs. Diagnostic setting are available for each individual resources within a subscription. Settings should be configured for all appropriate resources for your environment.', + more_info: 'Diagnostic setting should be configured for all appropriate resources for your environment in order to log the interactions within your cloud resources and gain insight into the operations that were performed within that resource itself.', recommended_action: 'Ensure that a Diagnostic status is enabled on all appropriate resources.', link: 'https://docs.microsoft.com/en-us/azure/monitoring-and-diagnostics/monitoring-overview-activity-logs#export-the-activity-log-with-a-log-profile', apis: ['diagnosticSettingsOperations:list'], @@ -33,6 +33,10 @@ module.exports = { } diagnosticSettings.data.forEach(settings => { + if (!settings.logs) { + helpers.addResult(results, 2, 'Diagnostic Setting does not have any logs configured', location, settings.id); + return; + } if (settings.logs && settings.logs.length) { let disabledLog = settings.logs.find(log => !log.enabled); From 4aa43ae067cabe906f65b40f2081c1241db739cd Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 13 Jun 2022 01:26:28 +0500 Subject: [PATCH 250/350] Made some fixes --- exports.js | 4 ++-- .../diagnosticsCapturedCategories.js} | 22 +++++++++++-------- .../diagnosticsCapturedCategories.spec.js} | 20 ++++++++--------- 3 files changed, 25 insertions(+), 21 deletions(-) rename plugins/azure/{diagnostics/captureAppropriateCategories.js => monitor/diagnosticsCapturedCategories.js} (59%) rename plugins/azure/{diagnostics/captureAppropriateCategories.spec.js => monitor/diagnosticsCapturedCategories.spec.js} (84%) diff --git a/exports.js b/exports.js index 2cd5414dfd..f3f41887aa 100644 --- a/exports.js +++ b/exports.js @@ -611,6 +611,8 @@ module.exports = { 'logProfileArchiveData' : require(__dirname + '/plugins/azure/monitor/logProfileArchiveData.js'), 'logProfileRetentionPolicy' : require(__dirname + '/plugins/azure/monitor/logProfileRetentionPolicy.js'), 'monitorLogsEnabled' : require(__dirname + '/plugins/azure/monitor/monitorLogsEnabled.js'), + 'diagnosticsCapturedCategories' : require(__dirname + '/plugins/azure/monitor/diagnosticsCapturedCategories.js'), + 'securityPolicyAlertsEnabled' : require(__dirname + '/plugins/azure/logalerts/securityPolicyAlertsEnabled.js'), 'nsgLoggingEnabled' : require(__dirname + '/plugins/azure/logalerts/nsgLoggingEnabled.js'), @@ -787,8 +789,6 @@ module.exports = { 'enableDefenderForContainers' : require(__dirname + '/plugins/azure/defender/enableDefenderForContainers.js'), 'enableDefenderForSqlServers' : require(__dirname + '/plugins/azure/defender/enableDefenderForSqlServers.js'), 'enableEndpointIntegration' : require(__dirname + '/plugins/azure/defender/enableEndpointIntegration.js'), - - 'captureAppropriateCategories' : require(__dirname + '/plugins/azure/diagnostics/captureAppropriateCategories.js'), }, github: { 'publicKeysRotated' : require(__dirname + '/plugins/github/users/publicKeysRotated.js'), diff --git a/plugins/azure/diagnostics/captureAppropriateCategories.js b/plugins/azure/monitor/diagnosticsCapturedCategories.js similarity index 59% rename from plugins/azure/diagnostics/captureAppropriateCategories.js rename to plugins/azure/monitor/diagnosticsCapturedCategories.js index 91c66b6915..39f0d77fd1 100644 --- a/plugins/azure/diagnostics/captureAppropriateCategories.js +++ b/plugins/azure/monitor/diagnosticsCapturedCategories.js @@ -3,12 +3,14 @@ const _ = require('underscore'); const helpers = require('../../../helpers/azure'); module.exports = { - title: 'Capture Appropriate Categories Logs', + title: 'Diagnostics Captured Categories', category: 'Monitor', domain: 'Management and Governance', - description: 'Ensures that Diagnostics Settings is capturing logs for all appropriate categories.', - more_info: 'A diagnostic setting controls how the diagnostic log is exported. Capturing the diagnostic setting categories for appropriate control/management plane activities allows proper alerting.', - recommended_action: 'Ensure that Diagnostic settings is enabled on all appropriate categories.', + description: 'Ensures that Diagnostics Settings is configured to log activities for all appropriate categories.', + more_info: 'Monitor diagnostic setting in Azure controls how the diagnostic logs are exported. When a diagnostic setting is created, ' + + 'by default no log categories are selected. Capturing the appropriate log categories (Administrative, Security, Alert, and Policy) ' + + 'for the activities performed within your Azure subscriptions provides proper alerting.', + recommended_action: 'Ensure the categories Administrative, Alert, Policy, and Security are set to Enabled for all diagnostic settings.', link: 'https://docs.microsoft.com/en-us/azure/azure-monitor/samples/resource-manager-diagnostic-settings', apis: ['diagnosticSettingsOperations:list'], @@ -30,12 +32,12 @@ module.exports = { } if (!diagnosticSettings.data.length) { - helpers.addResult(results, 2, 'No existing Diagnostic Settings found', location); + helpers.addResult(results, 0, 'No existing Diagnostic Settings found', location); return rcb(); } let enabledCategories = []; - diagnosticSettings.data.forEach(settings => { + diagnosticSettings.data.forEach(settings => { if (settings.logs && settings.logs.length) { settings.logs.forEach(log => { if (log.enabled && appropriateCategories.indexOf(log.category) > -1) { @@ -45,11 +47,13 @@ module.exports = { } }); - if (_.difference(appropriateCategories, enabledCategories).length === 0) { - helpers.addResult(results, 0, 'Logs for all appropriate categories are enabled for Diagnostic Settings', location); + if (!_.difference(appropriateCategories, enabledCategories).length) { + helpers.addResult(results, 0, 'Diagnostic Setting is configured to log required categories', location, settings.id); } else { - helpers.addResult(results, 2, 'Logs for all appropriate categories are not enabled for Diagnostic Settings', location); + helpers.addResult(results, 2, 'Diagnostic Setting is not configured to log required categories', location, settings.id); } + } else { + helpers.addResult(results, 2, 'Diagnostic Setting does not have any logs configured', location, settings.id); } }); diff --git a/plugins/azure/diagnostics/captureAppropriateCategories.spec.js b/plugins/azure/monitor/diagnosticsCapturedCategories.spec.js similarity index 84% rename from plugins/azure/diagnostics/captureAppropriateCategories.spec.js rename to plugins/azure/monitor/diagnosticsCapturedCategories.spec.js index 758e2f4cca..8fc0b2da8c 100644 --- a/plugins/azure/diagnostics/captureAppropriateCategories.spec.js +++ b/plugins/azure/monitor/diagnosticsCapturedCategories.spec.js @@ -1,5 +1,5 @@ var expect = require('chai').expect; -var captureAppropriateCategories = require('./captureAppropriateCategories'); +var diagnosticsCapturedCategories = require('./diagnosticsCapturedCategories'); const diagnosticSettings = [ { @@ -100,13 +100,13 @@ const createCache = (diagnosticSettings) => { }; }; -describe('captureAppropriateCategories', function() { +describe('diagnosticsCapturedCategories', function() { describe('run', function() { - it('should give failing result if no diagnostic settings found', function(done) { + it('should give passing result if no diagnostic settings found', function(done) { const cache = createCache([]); - captureAppropriateCategories.run(cache, {}, (err, results) => { + diagnosticsCapturedCategories.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); - expect(results[0].status).to.equal(2); + expect(results[0].status).to.equal(0); expect(results[0].message).to.include('No existing Diagnostic Settings found'); expect(results[0].region).to.equal('global'); done(); @@ -115,7 +115,7 @@ describe('captureAppropriateCategories', function() { it('should give unknown result if unable to query for diagnostic settings', function(done) { const cache = createCache(); - captureAppropriateCategories.run(cache, {}, (err, results) => { + diagnosticsCapturedCategories.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 Diagnostic Settings'); @@ -126,10 +126,10 @@ describe('captureAppropriateCategories', function() { it('should give passing result if logs are enabled for all appropriate categories', function(done) { const cache = createCache([diagnosticSettings[0]]); - captureAppropriateCategories.run(cache, {}, (err, results) => { + diagnosticsCapturedCategories.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('Logs for all appropriate categories are enabled for Diagnostic Settings'); + expect(results[0].message).to.include('Diagnostic Setting is configured to log required categories'); expect(results[0].region).to.equal('global'); done(); }); @@ -137,10 +137,10 @@ describe('captureAppropriateCategories', function() { it('should give failing result if logs are not enabled for all appropriate categories', function(done) { const cache = createCache([diagnosticSettings[1]]); - captureAppropriateCategories.run(cache, {}, (err, results) => { + diagnosticsCapturedCategories.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('Logs for all appropriate categories are not enabled for Diagnostic Settings'); + expect(results[0].message).to.include('Diagnostic Setting is not configured to log required categories'); expect(results[0].region).to.equal('global'); done(); }); From ebadf82f6390b997187742eb3e20c5e0f7d28629 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 13 Jun 2022 01:37:31 +0500 Subject: [PATCH 251/350] Fixed small issue --- plugins/azure/monitor/diagnosticsCapturedCategories.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/azure/monitor/diagnosticsCapturedCategories.js b/plugins/azure/monitor/diagnosticsCapturedCategories.js index 39f0d77fd1..a30fc7e733 100644 --- a/plugins/azure/monitor/diagnosticsCapturedCategories.js +++ b/plugins/azure/monitor/diagnosticsCapturedCategories.js @@ -1,5 +1,4 @@ const async = require('async'); -const _ = require('underscore'); const helpers = require('../../../helpers/azure'); module.exports = { @@ -36,8 +35,9 @@ module.exports = { return rcb(); } - let enabledCategories = []; diagnosticSettings.data.forEach(settings => { + let enabledCategories = []; + if (settings.logs && settings.logs.length) { settings.logs.forEach(log => { if (log.enabled && appropriateCategories.indexOf(log.category) > -1) { @@ -47,7 +47,7 @@ module.exports = { } }); - if (!_.difference(appropriateCategories, enabledCategories).length) { + if (appropriateCategories.length == enabledCategories.length) { helpers.addResult(results, 0, 'Diagnostic Setting is configured to log required categories', location, settings.id); } else { helpers.addResult(results, 2, 'Diagnostic Setting is not configured to log required categories', location, settings.id); From cf82b03c0b4be2f8f9df61f4e3e671d2cec766c0 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 13 Jun 2022 01:44:25 +0500 Subject: [PATCH 252/350] Made some changes --- exports.js | 5 +- .../monitor/diagnosticsCapturedCategories.js | 65 -------- .../diagnosticsCapturedCategories.spec.js | 149 ------------------ .../diagnosticsSettingsEnabled.js | 0 .../diagnosticsSettingsEnabled.spec.js | 0 5 files changed, 1 insertion(+), 218 deletions(-) delete mode 100644 plugins/azure/monitor/diagnosticsCapturedCategories.js delete mode 100644 plugins/azure/monitor/diagnosticsCapturedCategories.spec.js rename plugins/azure/{diagnostics => monitor}/diagnosticsSettingsEnabled.js (100%) rename plugins/azure/{diagnostics => monitor}/diagnosticsSettingsEnabled.spec.js (100%) diff --git a/exports.js b/exports.js index ecb2084b3b..279219b4c3 100644 --- a/exports.js +++ b/exports.js @@ -611,8 +611,7 @@ module.exports = { 'logProfileArchiveData' : require(__dirname + '/plugins/azure/monitor/logProfileArchiveData.js'), 'logProfileRetentionPolicy' : require(__dirname + '/plugins/azure/monitor/logProfileRetentionPolicy.js'), 'monitorLogsEnabled' : require(__dirname + '/plugins/azure/monitor/monitorLogsEnabled.js'), - 'diagnosticsCapturedCategories' : require(__dirname + '/plugins/azure/monitor/diagnosticsCapturedCategories.js'), - + 'diagnosticsSettingsEnabled' : require(__dirname + '/plugins/azure/monitor/diagnosticsSettingsEnabled.js'), 'securityPolicyAlertsEnabled' : require(__dirname + '/plugins/azure/logalerts/securityPolicyAlertsEnabled.js'), 'nsgLoggingEnabled' : require(__dirname + '/plugins/azure/logalerts/nsgLoggingEnabled.js'), @@ -789,8 +788,6 @@ module.exports = { 'enableDefenderForContainers' : require(__dirname + '/plugins/azure/defender/enableDefenderForContainers.js'), 'enableDefenderForSqlServers' : require(__dirname + '/plugins/azure/defender/enableDefenderForSqlServers.js'), 'enableEndpointIntegration' : require(__dirname + '/plugins/azure/defender/enableEndpointIntegration.js'), - - 'diagnosticsSettingsEnabled' : require(__dirname + '/plugins/azure/diagnostics/diagnosticsSettingsEnabled.js'), }, github: { 'publicKeysRotated' : require(__dirname + '/plugins/github/users/publicKeysRotated.js'), diff --git a/plugins/azure/monitor/diagnosticsCapturedCategories.js b/plugins/azure/monitor/diagnosticsCapturedCategories.js deleted file mode 100644 index a30fc7e733..0000000000 --- a/plugins/azure/monitor/diagnosticsCapturedCategories.js +++ /dev/null @@ -1,65 +0,0 @@ -const async = require('async'); -const helpers = require('../../../helpers/azure'); - -module.exports = { - title: 'Diagnostics Captured Categories', - category: 'Monitor', - domain: 'Management and Governance', - description: 'Ensures that Diagnostics Settings is configured to log activities for all appropriate categories.', - more_info: 'Monitor diagnostic setting in Azure controls how the diagnostic logs are exported. When a diagnostic setting is created, ' + - 'by default no log categories are selected. Capturing the appropriate log categories (Administrative, Security, Alert, and Policy) ' + - 'for the activities performed within your Azure subscriptions provides proper alerting.', - recommended_action: 'Ensure the categories Administrative, Alert, Policy, and Security are set to Enabled for all diagnostic settings.', - link: 'https://docs.microsoft.com/en-us/azure/azure-monitor/samples/resource-manager-diagnostic-settings', - apis: ['diagnosticSettingsOperations:list'], - - run: function(cache, settings, callback) { - const results = []; - const source = {}; - const locations = helpers.locations(settings.govcloud); - const appropriateCategories = ['Administrative', 'Alert', 'Policy', 'Security']; - - async.each(locations.diagnosticSettingsOperations, (location, rcb) => { - const diagnosticSettings = helpers.addSource(cache, source, - ['diagnosticSettingsOperations', 'list', location]); - - if (!diagnosticSettings) return rcb(); - - if (diagnosticSettings.err || !diagnosticSettings.data) { - helpers.addResult(results, 3, 'Unable to query for Diagnostic Settings : ' + helpers.addError(diagnosticSettings), location); - return rcb(); - } - - if (!diagnosticSettings.data.length) { - helpers.addResult(results, 0, 'No existing Diagnostic Settings found', location); - return rcb(); - } - - diagnosticSettings.data.forEach(settings => { - let enabledCategories = []; - - if (settings.logs && settings.logs.length) { - settings.logs.forEach(log => { - if (log.enabled && appropriateCategories.indexOf(log.category) > -1) { - if (enabledCategories.indexOf(log.category) === -1) { - enabledCategories.push(log.category); - } - } - }); - - if (appropriateCategories.length == enabledCategories.length) { - helpers.addResult(results, 0, 'Diagnostic Setting is configured to log required categories', location, settings.id); - } else { - helpers.addResult(results, 2, 'Diagnostic Setting is not configured to log required categories', location, settings.id); - } - } else { - helpers.addResult(results, 2, 'Diagnostic Setting does not have any logs configured', location, settings.id); - } - }); - - rcb(); - }, function() { - callback(null, results, source); - }); - } -}; diff --git a/plugins/azure/monitor/diagnosticsCapturedCategories.spec.js b/plugins/azure/monitor/diagnosticsCapturedCategories.spec.js deleted file mode 100644 index 8fc0b2da8c..0000000000 --- a/plugins/azure/monitor/diagnosticsCapturedCategories.spec.js +++ /dev/null @@ -1,149 +0,0 @@ -var expect = require('chai').expect; -var diagnosticsCapturedCategories = require('./diagnosticsCapturedCategories'); - -const diagnosticSettings = [ - { - 'id': 'subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting', - 'type': 'Microsoft.Insights/diagnosticSettings', - 'name': 'test-setting', - 'location': 'global', - 'storageAccountId': '/subscriptions/123/resourceGroups/devresourcegroup/providers/Microsoft.Storage/storageAccounts/test-storage-account', - 'logs': [ - { - 'category': 'Administrative', - 'enabled': true - }, - { - 'category': 'Security', - 'enabled': true - }, - { - 'category': 'ServiceHealth', - 'enabled': true - }, - { - 'category': 'Alert', - 'enabled': true - }, - { - 'category': 'Recommendation', - 'enabled': true - }, - { - 'category': 'Policy', - 'enabled': true - }, - { - 'category': 'Autoscale', - 'enabled': true - }, - { - 'category': 'ResourceHealth', - 'enabled': true - } - ] - }, - { - 'id': 'subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting', - 'type': 'Microsoft.Insights/diagnosticSettings', - 'name': 'test-setting', - 'location': 'global', - 'storageAccountId': '/subscriptions/123/resourceGroups/devresourcegroup/providers/Microsoft.Storage/storageAccounts/test-storage-account', - 'logs': [ - { - 'category': 'Administrative', - 'enabled': true - }, - { - 'category': 'Security', - 'enabled': true - }, - { - 'category': 'ServiceHealth', - 'enabled': true - }, - { - 'category': 'Alert', - 'enabled': false - }, - { - 'category': 'Recommendation', - 'enabled': true - }, - { - 'category': 'Policy', - 'enabled': true - }, - { - 'category': 'Autoscale', - 'enabled': true - }, - { - 'category': 'ResourceHealth', - 'enabled': false - } - ] - } -]; - -const createCache = (diagnosticSettings) => { - let settings = {}; - if (diagnosticSettings) { - settings['data'] = diagnosticSettings; - } - return { - diagnosticSettingsOperations: { - list: { - 'global': settings - } - } - }; -}; - -describe('diagnosticsCapturedCategories', function() { - describe('run', function() { - it('should give passing result if no diagnostic settings found', function(done) { - const cache = createCache([]); - diagnosticsCapturedCategories.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 Diagnostic Settings found'); - expect(results[0].region).to.equal('global'); - done(); - }); - }); - - it('should give unknown result if unable to query for diagnostic settings', function(done) { - const cache = createCache(); - diagnosticsCapturedCategories.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 Diagnostic Settings'); - expect(results[0].region).to.equal('global'); - done(); - }); - }); - - it('should give passing result if logs are enabled for all appropriate categories', function(done) { - const cache = createCache([diagnosticSettings[0]]); - diagnosticsCapturedCategories.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('Diagnostic Setting is configured to log required categories'); - expect(results[0].region).to.equal('global'); - done(); - }); - }); - - it('should give failing result if logs are not enabled for all appropriate categories', function(done) { - const cache = createCache([diagnosticSettings[1]]); - diagnosticsCapturedCategories.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('Diagnostic Setting is not configured to log required categories'); - expect(results[0].region).to.equal('global'); - done(); - }); - }); - }); -}); diff --git a/plugins/azure/diagnostics/diagnosticsSettingsEnabled.js b/plugins/azure/monitor/diagnosticsSettingsEnabled.js similarity index 100% rename from plugins/azure/diagnostics/diagnosticsSettingsEnabled.js rename to plugins/azure/monitor/diagnosticsSettingsEnabled.js diff --git a/plugins/azure/diagnostics/diagnosticsSettingsEnabled.spec.js b/plugins/azure/monitor/diagnosticsSettingsEnabled.spec.js similarity index 100% rename from plugins/azure/diagnostics/diagnosticsSettingsEnabled.spec.js rename to plugins/azure/monitor/diagnosticsSettingsEnabled.spec.js From 61502b405d56ed8184db628fc24fe5346055df46 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 13 Jun 2022 01:56:58 +0500 Subject: [PATCH 253/350] Made some changes --- .../monitor/diagnosticsSettingsEnabled.js | 25 +++---------- .../diagnosticsSettingsEnabled.spec.js | 36 ++++--------------- 2 files changed, 11 insertions(+), 50 deletions(-) diff --git a/plugins/azure/monitor/diagnosticsSettingsEnabled.js b/plugins/azure/monitor/diagnosticsSettingsEnabled.js index 9f93b12d1d..6c28f6a8f4 100644 --- a/plugins/azure/monitor/diagnosticsSettingsEnabled.js +++ b/plugins/azure/monitor/diagnosticsSettingsEnabled.js @@ -5,9 +5,9 @@ module.exports = { title: 'Diagnostics Settings Enabled', category: 'Monitor', domain: 'Management and Governance', - description: 'Ensures that Diagnostics Settings for exporting logs is enabled.', + description: 'Ensures that Diagnostics Settings exist and are exporting activity logs.', more_info: 'Diagnostic setting should be configured for all appropriate resources for your environment in order to log the interactions within your cloud resources and gain insight into the operations that were performed within that resource itself.', - recommended_action: 'Ensure that a Diagnostic status is enabled on all appropriate resources.', + recommended_action: 'Ensure that a Diagnostic status is enabled for all supported resources in Diagnostics Settings under Monitor.', link: 'https://docs.microsoft.com/en-us/azure/monitoring-and-diagnostics/monitoring-overview-activity-logs#export-the-activity-log-with-a-log-profile', apis: ['diagnosticSettingsOperations:list'], @@ -29,27 +29,10 @@ module.exports = { if (!diagnosticSettings.data.length) { helpers.addResult(results, 2, 'No existing Diagnostic Settings found', location); - return rcb(); + } else { + helpers.addResult(results, 0, 'Diagnostic Settings exist', location); } - diagnosticSettings.data.forEach(settings => { - if (!settings.logs) { - helpers.addResult(results, 2, 'Diagnostic Setting does not have any logs configured', location, settings.id); - return; - } - if (settings.logs && settings.logs.length) { - let disabledLog = settings.logs.find(log => !log.enabled); - - if (disabledLog) { - helpers.addResult(results, 2, 'Diagnostic Setting is not enabled for exporting logs on all resources', location, settings.id); - } else if (settings.storageAccountId && settings.storageAccountId.length) { - helpers.addResult(results, 0, 'Diagnostic Setting is enabled for exporting logs for all resources', location, settings.id); - } else { - helpers.addResult(results, 2, 'Diagnostic Setting does not have a Storage Account configured for Azure Monitor Logs', location, settings.id); - } - } - }); - rcb(); }, function() { callback(null, results, source); diff --git a/plugins/azure/monitor/diagnosticsSettingsEnabled.spec.js b/plugins/azure/monitor/diagnosticsSettingsEnabled.spec.js index 7d72e21da9..c1e4581e2a 100644 --- a/plugins/azure/monitor/diagnosticsSettingsEnabled.spec.js +++ b/plugins/azure/monitor/diagnosticsSettingsEnabled.spec.js @@ -155,45 +155,23 @@ describe('diagnosticsSettingsEnabled', function() { }); }); - it('should give unknown result if unable to query for diagnostic settings', function(done) { - const cache = createCache(); - diagnosticsSettingsEnabled.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 Diagnostic Settings'); - expect(results[0].region).to.equal('global'); - done(); - }); - }); - - it('should give passing result if logs are enabled for all logging categories and storage account configured', function(done) { - const cache = createCache([diagnosticSettings[0]]); + it('should give passing result if diagnostic settings found', function(done) { + const cache = createCache(diagnosticSettings); diagnosticsSettingsEnabled.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('Diagnostic Setting is enabled for exporting logs for all resources'); - expect(results[0].region).to.equal('global'); - done(); - }); - }); - - it('should give failing result if logs are not enabled for all logging categories and storage account configured', function(done) { - const cache = createCache([diagnosticSettings[1]]); - diagnosticsSettingsEnabled.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('Diagnostic Setting is not enabled for exporting logs on all resources'); + expect(results[0].message).to.include('Diagnostic Settings exist'); expect(results[0].region).to.equal('global'); done(); }); }); - it('should give failing result if logs are enabled for all logging categories and storage account is not configured', function(done) { - const cache = createCache([diagnosticSettings[2]]); + it('should give unknown result if unable to query for diagnostic settings', function(done) { + const cache = createCache(); diagnosticsSettingsEnabled.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); - expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('Diagnostic Setting does not have a Storage Account configured for Azure Monitor Logs'); + expect(results[0].status).to.equal(3); + expect(results[0].message).to.include('Unable to query for Diagnostic Settings'); expect(results[0].region).to.equal('global'); done(); }); From b5441570e0de806a743373258b3707e248d49bbb Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 13 Jun 2022 02:06:08 +0500 Subject: [PATCH 254/350] Fixed merge conflicts --- exports.js | 1 + .../monitor/diagnosticsCapturedCategories.js | 65 ++++++++ .../diagnosticsCapturedCategories.spec.js | 149 ++++++++++++++++++ 3 files changed, 215 insertions(+) create mode 100644 plugins/azure/monitor/diagnosticsCapturedCategories.js create mode 100644 plugins/azure/monitor/diagnosticsCapturedCategories.spec.js diff --git a/exports.js b/exports.js index 279219b4c3..c37bad6793 100644 --- a/exports.js +++ b/exports.js @@ -611,6 +611,7 @@ module.exports = { 'logProfileArchiveData' : require(__dirname + '/plugins/azure/monitor/logProfileArchiveData.js'), 'logProfileRetentionPolicy' : require(__dirname + '/plugins/azure/monitor/logProfileRetentionPolicy.js'), 'monitorLogsEnabled' : require(__dirname + '/plugins/azure/monitor/monitorLogsEnabled.js'), + 'diagnosticsCapturedCategories' : require(__dirname + '/plugins/azure/monitor/diagnosticsCapturedCategories.js'), 'diagnosticsSettingsEnabled' : require(__dirname + '/plugins/azure/monitor/diagnosticsSettingsEnabled.js'), 'securityPolicyAlertsEnabled' : require(__dirname + '/plugins/azure/logalerts/securityPolicyAlertsEnabled.js'), diff --git a/plugins/azure/monitor/diagnosticsCapturedCategories.js b/plugins/azure/monitor/diagnosticsCapturedCategories.js new file mode 100644 index 0000000000..914885337c --- /dev/null +++ b/plugins/azure/monitor/diagnosticsCapturedCategories.js @@ -0,0 +1,65 @@ +const async = require('async'); +const helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Diagnostics Captured Categories', + category: 'Monitor', + domain: 'Management and Governance', + description: 'Ensures that Diagnostics Settings is configured to log activities for all appropriate categories.', + more_info: 'Monitor diagnostic setting in Azure controls how the diagnostic logs are exported. When a diagnostic setting is created, ' + + 'by default no log categories are selected. Capturing the appropriate log categories (Administrative, Security, Alert, and Policy) ' + + 'for the activities performed within your Azure subscriptions provides proper alerting.', + recommended_action: 'Ensure the categories Administrative, Alert, Policy, and Security are set to Enabled for all diagnostic settings.', + link: 'https://docs.microsoft.com/en-us/azure/azure-monitor/samples/resource-manager-diagnostic-settings', + apis: ['diagnosticSettingsOperations:list'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + const appropriateCategories = ['Administrative', 'Alert', 'Policy', 'Security']; + + async.each(locations.diagnosticSettingsOperations, (location, rcb) => { + const diagnosticSettings = helpers.addSource(cache, source, + ['diagnosticSettingsOperations', 'list', location]); + + if (!diagnosticSettings) return rcb(); + + if (diagnosticSettings.err || !diagnosticSettings.data) { + helpers.addResult(results, 3, 'Unable to query for Diagnostic Settings : ' + helpers.addError(diagnosticSettings), location); + return rcb(); + } + + if (!diagnosticSettings.data.length) { + helpers.addResult(results, 0, 'No existing Diagnostic Settings found', location); + return rcb(); + } + + diagnosticSettings.data.forEach(settings => { + let enabledCategories = []; + + if (settings.logs && settings.logs.length) { + settings.logs.forEach(log => { + if (log.enabled && appropriateCategories.indexOf(log.category) > -1) { + if (enabledCategories.indexOf(log.category) === -1) { + enabledCategories.push(log.category); + } + } + }); + + if (appropriateCategories.length == enabledCategories.length) { + helpers.addResult(results, 0, 'Diagnostic Setting is configured to log required categories', location, settings.id); + } else { + helpers.addResult(results, 2, 'Diagnostic Setting is not configured to log required categories', location, settings.id); + } + } else { + helpers.addResult(results, 2, 'Diagnostic Setting does not have any logs configured', location, settings.id); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/monitor/diagnosticsCapturedCategories.spec.js b/plugins/azure/monitor/diagnosticsCapturedCategories.spec.js new file mode 100644 index 0000000000..e1eb4a61dd --- /dev/null +++ b/plugins/azure/monitor/diagnosticsCapturedCategories.spec.js @@ -0,0 +1,149 @@ +var expect = require('chai').expect; +var diagnosticsCapturedCategories = require('./diagnosticsCapturedCategories'); + +const diagnosticSettings = [ + { + 'id': 'subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting', + 'type': 'Microsoft.Insights/diagnosticSettings', + 'name': 'test-setting', + 'location': 'global', + 'storageAccountId': '/subscriptions/123/resourceGroups/devresourcegroup/providers/Microsoft.Storage/storageAccounts/test-storage-account', + 'logs': [ + { + 'category': 'Administrative', + 'enabled': true + }, + { + 'category': 'Security', + 'enabled': true + }, + { + 'category': 'ServiceHealth', + 'enabled': true + }, + { + 'category': 'Alert', + 'enabled': true + }, + { + 'category': 'Recommendation', + 'enabled': true + }, + { + 'category': 'Policy', + 'enabled': true + }, + { + 'category': 'Autoscale', + 'enabled': true + }, + { + 'category': 'ResourceHealth', + 'enabled': true + } + ] + }, + { + 'id': 'subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting', + 'type': 'Microsoft.Insights/diagnosticSettings', + 'name': 'test-setting', + 'location': 'global', + 'storageAccountId': '/subscriptions/123/resourceGroups/devresourcegroup/providers/Microsoft.Storage/storageAccounts/test-storage-account', + 'logs': [ + { + 'category': 'Administrative', + 'enabled': true + }, + { + 'category': 'Security', + 'enabled': true + }, + { + 'category': 'ServiceHealth', + 'enabled': true + }, + { + 'category': 'Alert', + 'enabled': false + }, + { + 'category': 'Recommendation', + 'enabled': true + }, + { + 'category': 'Policy', + 'enabled': true + }, + { + 'category': 'Autoscale', + 'enabled': true + }, + { + 'category': 'ResourceHealth', + 'enabled': false + } + ] + } +]; + +const createCache = (diagnosticSettings) => { + let settings = {}; + if (diagnosticSettings) { + settings['data'] = diagnosticSettings; + } + return { + diagnosticSettingsOperations: { + list: { + 'global': settings + } + } + }; +}; + +describe('diagnosticsCapturedCategories', function() { + describe('run', function() { + it('should give passing result if no diagnostic settings found', function(done) { + const cache = createCache([]); + diagnosticsCapturedCategories.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 Diagnostic Settings found'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give unknown result if unable to query for diagnostic settings', function(done) { + const cache = createCache(); + diagnosticsCapturedCategories.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 Diagnostic Settings'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give passing result if logs are enabled for all appropriate categories', function(done) { + const cache = createCache([diagnosticSettings[0]]); + diagnosticsCapturedCategories.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Diagnostic Setting is configured to log required categories'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give failing result if logs are not enabled for all appropriate categories', function(done) { + const cache = createCache([diagnosticSettings[1]]); + diagnosticsCapturedCategories.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Diagnostic Setting is not configured to log required categories'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + }); +}); \ No newline at end of file From 6df116e6f1eef9ac8d0656b13835e5f5e520fb11 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 13 Jun 2022 02:07:26 +0500 Subject: [PATCH 255/350] Update plugins/azure/monitor/diagnosticsCapturedCategories.js --- plugins/azure/monitor/diagnosticsCapturedCategories.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/monitor/diagnosticsCapturedCategories.js b/plugins/azure/monitor/diagnosticsCapturedCategories.js index 914885337c..a30fc7e733 100644 --- a/plugins/azure/monitor/diagnosticsCapturedCategories.js +++ b/plugins/azure/monitor/diagnosticsCapturedCategories.js @@ -62,4 +62,4 @@ module.exports = { callback(null, results, source); }); } -}; \ No newline at end of file +}; From aa94cac13f9190252a0f11355b8fa18abb875166 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 13 Jun 2022 02:07:43 +0500 Subject: [PATCH 256/350] Update plugins/azure/monitor/diagnosticsCapturedCategories.spec.js --- plugins/azure/monitor/diagnosticsCapturedCategories.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/azure/monitor/diagnosticsCapturedCategories.spec.js b/plugins/azure/monitor/diagnosticsCapturedCategories.spec.js index e1eb4a61dd..8fc0b2da8c 100644 --- a/plugins/azure/monitor/diagnosticsCapturedCategories.spec.js +++ b/plugins/azure/monitor/diagnosticsCapturedCategories.spec.js @@ -146,4 +146,4 @@ describe('diagnosticsCapturedCategories', function() { }); }); }); -}); \ No newline at end of file +}); From ea70b6aa7f1c901f441d4d3122ba608208fd2995 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 14 Jun 2022 01:08:45 +0500 Subject: [PATCH 257/350] Made open ports check case insensitive --- helpers/azure/functions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helpers/azure/functions.js b/helpers/azure/functions.js index 9fb275b677..340e3b675d 100644 --- a/helpers/azure/functions.js +++ b/helpers/azure/functions.js @@ -89,7 +89,8 @@ function findOpenPorts(ngs, protocols, service, location, results) { securityRule.properties['direction'] && securityRule.properties['direction'] === 'Inbound' && securityRule.properties['protocol'] && - (securityRule.properties['protocol'] === protocol || securityRule.properties['protocol'] === '*')) { + typeof securityRule.properties['protocol'] == 'string' && + (securityRule.properties['protocol'].toUpperCase() === protocol || securityRule.properties['protocol'].toUpperCase() === '*')) { if (securityRule.properties['destinationPortRange']) { if (securityRule.properties['destinationPortRange'].toString().indexOf("-") > -1) { let portRange = securityRule.properties['destinationPortRange'].split("-"); From 2bb63ba5c0639e17ded7ae92a217df56797a33fa Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 20 Jun 2022 21:11:36 +0500 Subject: [PATCH 258/350] Added Modify affected AWS plugins. --- helpers/aws/regions.js | 13 ++++---- .../aws/backup/backupNotificationEnabled.js | 6 ++-- .../backup/backupNotificationEnabled.spec.js | 2 +- .../cloudtrailBucketAccessLogging.js | 17 ++++++++++ .../cloudtrailBucketAccessLogging.spec.js | 31 +++++++++++-------- .../aws/cloudtrail/cloudtrailBucketDelete.js | 18 +++++++++++ .../cloudtrail/cloudtrailBucketDelete.spec.js | 25 +++++++++------ .../aws/cloudtrail/cloudtrailBucketPrivate.js | 19 +++++++++++- .../cloudtrailBucketPrivate.spec.js | 26 +++++++++------- .../cloudtrailNotificationsEnabled.js | 24 ++++++++++---- .../cloudtrailNotificationsEnabled.spec.js | 19 ++++++------ 11 files changed, 141 insertions(+), 59 deletions(-) diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index e7c009530f..e61fd59bed 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -51,7 +51,9 @@ module.exports = { 'eu-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-northeast-1', 'ap-southeast-2', 'ap-northeast-2', 'ap-south-1', 'ca-central-1'], configservice: [...regions, ...newRegions], - dax: [...regions, ...newRegions], + dax: ['us-east-1', 'us-east-2', 'us-west-2', 'eu-central-1', 'eu-west-1', + 'eu-west-2', 'eu-west-3', 'ap-northeast-1', 'ap-southeast-1', + 'ap-southeast-2', 'ap-south-1', 'sa-east-1'], devopsguru: ['us-east-1', 'us-east-2', 'eu-west-1', 'us-west-2', 'ap-northeast-1', 'eu-central-1', 'ap-southeast-1', 'ap-southeast-2', 'eu-north-1'], dynamodb: [...regions, ...newRegions], @@ -159,9 +161,8 @@ module.exports = { 'eu-west-3', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1', 'sa-east-1', 'af-south-1' ], translate: [ - 'us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'ap-northeast-2', - 'ap-east-1', 'ap-south-1', 'ap-northeast-1', 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'eu-west-3', - 'eu-north-1' + 'us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1', 'eu-west-2', 'ap-northeast-2', + 'ap-east-1' ], databrew: ['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'eu-south-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', @@ -171,13 +172,13 @@ module.exports = { connect: ['us-east-1', 'us-west-2', 'eu-west-2', 'ca-central-1', 'eu-central-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'ap-northeast-2', 'af-south-1'], apprunner: ['us-east-1', 'us-west-2', 'us-west-2', 'eu-west-1','ap-northeast-1'], - healthlake: ['us-east-1', 'us-east-2', 'eu-west-2'], + healthlake: ['us-east-1', 'us-east-2', 'us-west-2'], lookoutequipment: ['us-east-1', 'eu-west-1', 'ap-northeast-2'], iotsitewise: ['us-east-1', 'us-west-2', 'ap-south-1', 'ap-southeast-1', 'ap-northeast-2', 'ap-southeast-2', 'ap-northeast-1', 'eu-central-1', 'eu-west-1'], location: [ 'us-east-1', 'us-east-2', 'us-west-2', 'eu-central-1', 'eu-west-1', 'eu-north-1', - 'ap-northeast-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-south-1' + 'ap-northeast-1', 'ap-southeast-1', 'ap-southeast-2' ], lookoutvision: ['us-east-1', 'us-east-2', 'ap-northeast-1', 'ap-northeast-2', 'eu-central-1', 'eu-west-1', 'us-west-2'], lookoutmetrics: ['us-east-1', 'us-east-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'eu-central-1', diff --git a/plugins/aws/backup/backupNotificationEnabled.js b/plugins/aws/backup/backupNotificationEnabled.js index e28097f5a9..eefb422d83 100644 --- a/plugins/aws/backup/backupNotificationEnabled.js +++ b/plugins/aws/backup/backupNotificationEnabled.js @@ -13,6 +13,7 @@ module.exports = { apis: ['Backup:listBackupVaults', 'Backup:getBackupVaultNotifications' ], run: function(cache, settings, callback) { + // console.log(JSON.stringify(cache, null, 2)); var results = []; var source = {}; var regions = helpers.regions(settings); @@ -42,8 +43,9 @@ module.exports = { let getBackupVaultNotifications = helpers.addSource(cache, source, ['backup', 'getBackupVaultNotifications', region, vault.BackupVaultName]); - if (getBackupVaultNotifications && getBackupVaultNotifications.err && getBackupVaultNotifications.err.code && - getBackupVaultNotifications.err.code == 'ResourceNotFoundException') { + + if (getBackupVaultNotifications && getBackupVaultNotifications.err && getBackupVaultNotifications.err.message && + getBackupVaultNotifications.err.message == `Failed reading notifications from database for Backup vault ${vault.BackupVaultName}`) { helpers.addResult(results, 2, 'Backup vault does not have any notifications configured', region, resource); continue; diff --git a/plugins/aws/backup/backupNotificationEnabled.spec.js b/plugins/aws/backup/backupNotificationEnabled.spec.js index b26f4b56b6..82e26dfa53 100644 --- a/plugins/aws/backup/backupNotificationEnabled.spec.js +++ b/plugins/aws/backup/backupNotificationEnabled.spec.js @@ -81,7 +81,7 @@ describe('backupNotificationEnabled', function () { }); it('should FAIL if Backup vault does not have any notifications configured', function (done) { - const cache = createCache([listBackupVaults[0]], null , null, { message: 'An error occurred (ResourceNotFoundException) when calling the getBackupVaultNotifications operation', code : 'ResourceNotFoundException' } ); + const cache = createCache([listBackupVaults[0]], null , null, { message: 'Failed reading notifications from database for Backup vault sadeed1'} ); backupNotificationEnabled.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); diff --git a/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js b/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js index b86e49526f..a13d932e62 100644 --- a/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js +++ b/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js @@ -23,6 +23,16 @@ module.exports = { var results = []; var source = {}; var regions = helpers.regions(settings); + var defaultRegion = helpers.defaultRegion(settings); + + var listBuckets = helpers.addSource(cache, source, + ['s3', 'listBuckets', defaultRegion]); + + if (!listBuckets || listBuckets.err || !listBuckets.data) { + helpers.addResult(results, 3, + 'Unable to query for S3 buckets: ' + helpers.addError(listBuckets)); + return callback(null, results, source); + } async.each(regions.cloudtrail, function(region, rcb){ @@ -46,6 +56,13 @@ module.exports = { if (!trail.S3BucketName || (trail.HomeRegion && trail.HomeRegion.toLowerCase() !== region)) return cb(); // Skip CloudSploit-managed events bucket if (trail.S3BucketName == helpers.CLOUDSPLOIT_EVENTS_BUCKET) return cb(); + + if (!listBuckets.data.find(bucket => bucket.Name == trail.S3BucketName)) { + helpers.addResult(results, 2, + 'Unable to locate S3 bucket, it may has been deleted', + region, 'arn:aws:s3:::' + trail.S3BucketName); + return cb(); + } var s3Region = helpers.defaultRegion(settings); diff --git a/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.spec.js b/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.spec.js index b3c9ed608e..3663559486 100644 --- a/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.spec.js +++ b/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.spec.js @@ -4,7 +4,7 @@ var cloudtrailBucketAccessLogging = require('./cloudtrailBucketAccessLogging'); const trails = [ { "Name": "trail-1", - "S3BucketName": "cloudtrail-bucket", + "S3BucketName": "aws-cloudtrail-logs-123456654321-119d2f9a", "IncludeGlobalServiceEvents": true, "IsMultiRegionTrail": true, "HomeRegion": "us-east-1", @@ -17,7 +17,19 @@ const trails = [ }, { "Name": "trail-2", - "S3BucketName": "aws-cloudtrail-logs-123456654321-test-events-690d8af2", + "S3BucketName": "aws-cloudtrail-logs-123456654321-37b755bd", + "IncludeGlobalServiceEvents": true, + "IsMultiRegionTrail": false, + "HomeRegion": "us-east-1", + "TrailARN": "arn:aws:cloudtrail:us-east-1:123456654321:trail/trail-2", + "LogFileValidationEnabled": false, + "HasCustomEventSelectors": false, + "HasInsightSelectors": false, + "IsOrganizationTrail": false + }, + { + "Name": "trail-3", + "S3BucketName": "codepipeline-cloudtrail-placeholder-bucket-us-east-1", "IncludeGlobalServiceEvents": true, "IsMultiRegionTrail": false, "HomeRegion": "us-east-1", @@ -113,6 +125,7 @@ describe('cloudtrailBucketAccessLogging', function () { it('should PASS if bucket has S3 access logs enabled', function (done) { const cache = createCache([trails[0]], [listBuckets[0]], getBucketLogging[0]); cloudtrailBucketAccessLogging.run(cache, {}, (err, results) => { + console.log(results); expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -128,11 +141,11 @@ describe('cloudtrailBucketAccessLogging', function () { }); }); - it('should PASS if no S3 bucket to check', function (done) { - const cache = createCache([]); + it('should FAIL if Unable to locate S3 bucket, it may has been deleted', function (done) { + const cache = createCache([trails[2]], [listBuckets[1]], getBucketLogging[1]); cloudtrailBucketAccessLogging.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); - expect(results[0].status).to.equal(0); + expect(results[0].status).to.equal(2); done(); }); }); @@ -154,13 +167,5 @@ describe('cloudtrailBucketAccessLogging', function () { done(); }); }); - - it('should not return any results if describe CloudTrail response not found', function (done) { - const cache = createNullCache(); - cloudtrailBucketAccessLogging.run(cache, {}, (err, results) => { - expect(results.length).to.equal(0); - done(); - }); - }); }); }); diff --git a/plugins/aws/cloudtrail/cloudtrailBucketDelete.js b/plugins/aws/cloudtrail/cloudtrailBucketDelete.js index bc93ced017..43f11c70b3 100644 --- a/plugins/aws/cloudtrail/cloudtrailBucketDelete.js +++ b/plugins/aws/cloudtrail/cloudtrailBucketDelete.js @@ -21,6 +21,17 @@ module.exports = { var results = []; var source = {}; var regions = helpers.regions(settings); + var defaultRegion = helpers.defaultRegion(settings); + + var listBuckets = helpers.addSource(cache, source, + ['s3', 'listBuckets', defaultRegion]); + console.log(listBuckets); + + if (!listBuckets || listBuckets.err || !listBuckets.data) { + helpers.addResult(results, 3, + 'Unable to query for S3 buckets: ' + helpers.addError(listBuckets)); + return callback(null, results, source); + } async.each(regions.cloudtrail, function(region, rcb){ @@ -45,6 +56,13 @@ module.exports = { // Skip CloudSploit-managed events bucket if (trail.S3BucketName == helpers.CLOUDSPLOIT_EVENTS_BUCKET) return cb(); + if (!listBuckets.data.find(bucket => bucket.Name == trail.S3BucketName)) { + helpers.addResult(results, 2, + 'Unable to locate S3 bucket, it may has been deleted', + region, 'arn:aws:s3:::' + trail.S3BucketName); + return cb(); + } + var s3Region = helpers.defaultRegion(settings); var getBucketVersioning = helpers.addSource(cache, source, diff --git a/plugins/aws/cloudtrail/cloudtrailBucketDelete.spec.js b/plugins/aws/cloudtrail/cloudtrailBucketDelete.spec.js index 97466da133..404414f33a 100644 --- a/plugins/aws/cloudtrail/cloudtrailBucketDelete.spec.js +++ b/plugins/aws/cloudtrail/cloudtrailBucketDelete.spec.js @@ -26,6 +26,18 @@ const trails = [ "HasCustomEventSelectors": false, "HasInsightSelectors": false, "IsOrganizationTrail": false + }, + { + "Name": "trail-3", + "S3BucketName": "codepipeline-cloudtrail-placeholder-bucket-us-east-1", + "IncludeGlobalServiceEvents": true, + "IsMultiRegionTrail": false, + "HomeRegion": "us-east-1", + "TrailARN": "arn:aws:cloudtrail:us-east-1:123456654321:trail/trail-2", + "LogFileValidationEnabled": false, + "HasCustomEventSelectors": false, + "HasInsightSelectors": false, + "IsOrganizationTrail": false } ]; @@ -128,11 +140,11 @@ describe('cloudtrailBucketDelete', function () { }); }); - it('should PASS if no S3 bucket to check', function (done) { - const cache = createCache([]); + it('should FAIL if Unable to locate S3 bucket, it may has been deleted', function (done) { + const cache = createCache([trails[2]], [listBuckets[1]], getBucketVersioning[1]); cloudtrailBucketDelete.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); - expect(results[0].status).to.equal(0); + expect(results[0].status).to.equal(2); done(); }); }); @@ -155,12 +167,5 @@ describe('cloudtrailBucketDelete', function () { }); }); - it('should not return any results if describe CloudTrail response not found', function (done) { - const cache = createNullCache(); - cloudtrailBucketDelete.run(cache, {}, (err, results) => { - expect(results.length).to.equal(0); - done(); - }); - }); }); }); diff --git a/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js b/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js index 458515f76e..77b2f49c89 100644 --- a/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js +++ b/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js @@ -19,6 +19,17 @@ module.exports = { var source = {}; var regions = helpers.regions(settings); + var defaultRegion = helpers.defaultRegion(settings); + + var listBuckets = helpers.addSource(cache, source, + ['s3', 'listBuckets', defaultRegion]); + + if (!listBuckets || listBuckets.err || !listBuckets.data) { + helpers.addResult(results, 3, + 'Unable to query for S3 buckets: ' + helpers.addError(listBuckets)); + return callback(null, results, source); + } + async.each(regions.cloudtrail, function(region, rcb){ var describeTrails = helpers.addSource(cache, source, @@ -42,6 +53,13 @@ module.exports = { // Skip CloudSploit-managed events bucket if (trail.S3BucketName == helpers.CLOUDSPLOIT_EVENTS_BUCKET) return cb(); + if (!listBuckets.data.find(bucket => bucket.Name == trail.S3BucketName)) { + helpers.addResult(results, 2, + 'Unable to locate S3 bucket, it may has been deleted', + region, 'arn:aws:s3:::' + trail.S3BucketName); + return cb(); + } + var s3Region = helpers.defaultRegion(settings); var getBucketAcl = helpers.addSource(cache, source, @@ -51,7 +69,6 @@ module.exports = { helpers.addResult(results, 3, 'Error querying for bucket policy for bucket: ' + trail.S3BucketName + ': ' + helpers.addError(getBucketAcl), region, 'arn:aws:s3:::' + trail.S3BucketName); - return cb(); } diff --git a/plugins/aws/cloudtrail/cloudtrailBucketPrivate.spec.js b/plugins/aws/cloudtrail/cloudtrailBucketPrivate.spec.js index 521698d322..a1baefa295 100644 --- a/plugins/aws/cloudtrail/cloudtrailBucketPrivate.spec.js +++ b/plugins/aws/cloudtrail/cloudtrailBucketPrivate.spec.js @@ -26,6 +26,18 @@ const trails = [ "HasCustomEventSelectors": false, "HasInsightSelectors": false, "IsOrganizationTrail": false + }, + { + "Name": "trail-3", + "S3BucketName": "codepipeline-cloudtrail-placeholder-bucket-us-east-1", + "IncludeGlobalServiceEvents": true, + "IsMultiRegionTrail": false, + "HomeRegion": "us-east-1", + "TrailARN": "arn:aws:cloudtrail:us-east-1:123456654321:trail/trail-2", + "LogFileValidationEnabled": false, + "HasCustomEventSelectors": false, + "HasInsightSelectors": false, + "IsOrganizationTrail": false } ]; @@ -147,11 +159,11 @@ describe('cloudtrailBucketPrivate', function () { }); }); - it('should PASS if no S3 bucket to check', function (done) { - const cache = createCache([]); + it('should FAIL if Unable to locate S3 bucket, it may has been deleted', function (done) { + const cache = createCache([trails[2]], [listBuckets[1]], getBucketAcl[0]); cloudtrailBucketPrivate.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); - expect(results[0].status).to.equal(0); + expect(results[0].status).to.equal(2); done(); }); }); @@ -173,13 +185,5 @@ describe('cloudtrailBucketPrivate', function () { done(); }); }); - - it('should not return any results if describe CloudTrail response not found', function (done) { - const cache = createNullCache(); - cloudtrailBucketPrivate.run(cache, {}, (err, results) => { - expect(results.length).to.equal(0); - done(); - }); - }); }); }); diff --git a/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js b/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js index ca8111db61..4081988aa7 100644 --- a/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js +++ b/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js @@ -41,29 +41,37 @@ module.exports = { if (listTopics.err || !listTopics.data) { helpers.addResult(results, 3, - `Unable to query for SNS topics: ${helpers.addError(listTopics)}`, region); + `Unable to list SNS topics: ${helpers.addError(listTopics)}`, region); return rcb(); } + var trailFound; for (let trail of describeTrails.data) { - if (!trail.TrailARN) continue; + if (!trail.TrailARN || + (trail.HomeRegion && trail.HomeRegion.toLowerCase() != region)) continue; + trailFound = true; var resource = trail.TrailARN; + if (!trail.SnsTopicARN) { + helpers.addResult(results, 2, + 'CloudTrail trail has no SNS topic attached', region, resource); + continue; + } + var getTopicAttributes = helpers.addSource(cache, source, ['sns', 'getTopicAttributes', region, trail.SnsTopicARN]); - if (getTopicAttributes && getTopicAttributes.err && getTopicAttributes.err.code && - getTopicAttributes.err.code == 'NotFound') { + if (!getTopicAttributes) { helpers.addResult(results, 2, 'CloudTrail trail SNS topic not found', region, resource); continue; } - if (!getTopicAttributes || getTopicAttributes.err || + if (getTopicAttributes.err || !getTopicAttributes.data) { helpers.addResult(results, 3, - `Unable to query for SNS topic: ${helpers.addError(describeTrails)}`, + `Unable to query for SNS topic attributes: ${helpers.addError(getTopicAttributes)}`, region, resource); } else { helpers.addResult(results, 0, @@ -72,6 +80,10 @@ module.exports = { } } + if (!trailFound) { + helpers.addResult(results, 0, 'No CloudTrail trails found', region); + } + rcb(); }, function() { return callback(null, results, source); diff --git a/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.spec.js b/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.spec.js index 844d49d8a4..087323c122 100644 --- a/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.spec.js +++ b/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.spec.js @@ -103,13 +103,14 @@ describe('cloudtrailNotificationsEnabled', function () { }); }); - it('should FAIL if CloudTrail trail SNS topic not found', function (done) { - const cache = createCache([describeTrails[1]], listTopics[2], null, null, null, { message: 'An error occurred (NotFound) when calling the GetTopicAttributes operation: Topic does not exist', code : 'NotFound' } ); + it('should FAIL if CloudTrail trail has no SNS topic attached', function (done) { + const cache = createCache([describeTrails[0]], listTopics[2], null, null, null, { message: 'CloudTrail trail has no SNS topic attached'} ); cloudtrailNotificationsEnabled.run(cache, {}, (err, results) => { + console.log(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('CloudTrail trail SNS topic not found') + expect(results[0].message).to.include('CloudTrail trail has no SNS topic attached') done(); }); }); @@ -135,22 +136,22 @@ describe('cloudtrailNotificationsEnabled', function () { }); }); - it('should UNKNOWN if unable to query for SNS topics', function (done) { - const cache = createCache([describeTrails[1]], [], null, null, { message: 'Unable to query for SNS topics' }); + it('should UNKNOWN if unable to list SNS topics', function (done) { + const cache = createCache([describeTrails[1]], [], null, null, { message: 'Unable to list SNS topics' }); cloudtrailNotificationsEnabled.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 SNS topics') + expect(results[0].message).to.include('Unable to list SNS topics') done(); }); }); - it('should UNKNOWN if unable to query for SNS topic', function (done) { - const cache = createCache([describeTrails[1]], listTopics[1], null, null, null, { message: 'Unable to query for SNS topic' }); + it('should UNKNOWN if unable to query for SNS topic attributes', function (done) { + const cache = createCache([describeTrails[1]], listTopics[1], null, null, null, { message: 'Unable to query for SNS topic attributes' }); cloudtrailNotificationsEnabled.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 SNS topic') + expect(results[0].message).to.include('Unable to query for SNS topic attributes') done(); }); }); From 419cb530ac7ce8997b5918a209cccc7a3ede4a6a Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 20 Jun 2022 21:17:11 +0500 Subject: [PATCH 259/350] Added Modify affected AWS plugins. --- plugins/aws/cloudtrail/cloudtrailBucketDelete.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/aws/cloudtrail/cloudtrailBucketDelete.js b/plugins/aws/cloudtrail/cloudtrailBucketDelete.js index 43f11c70b3..bfd4ce50bd 100644 --- a/plugins/aws/cloudtrail/cloudtrailBucketDelete.js +++ b/plugins/aws/cloudtrail/cloudtrailBucketDelete.js @@ -25,7 +25,6 @@ module.exports = { var listBuckets = helpers.addSource(cache, source, ['s3', 'listBuckets', defaultRegion]); - console.log(listBuckets); if (!listBuckets || listBuckets.err || !listBuckets.data) { helpers.addResult(results, 3, From 5478b05523f7755a29cde5a112d2b82521b5398b Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Mon, 20 Jun 2022 21:23:34 +0500 Subject: [PATCH 260/350] Update plugins/aws/backup/backupNotificationEnabled.js --- plugins/aws/backup/backupNotificationEnabled.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/aws/backup/backupNotificationEnabled.js b/plugins/aws/backup/backupNotificationEnabled.js index eefb422d83..bf89c9e1e1 100644 --- a/plugins/aws/backup/backupNotificationEnabled.js +++ b/plugins/aws/backup/backupNotificationEnabled.js @@ -13,7 +13,6 @@ module.exports = { apis: ['Backup:listBackupVaults', 'Backup:getBackupVaultNotifications' ], run: function(cache, settings, callback) { - // console.log(JSON.stringify(cache, null, 2)); var results = []; var source = {}; var regions = helpers.regions(settings); From 88522cdca85d55fca5360daf6038a7092d770f25 Mon Sep 17 00:00:00 2001 From: M-Akhtar Date: Tue, 21 Jun 2022 13:49:01 +0500 Subject: [PATCH 261/350] Syncing with SAAS --- exports.js | 2 + helpers/google/functions.js | 8 +- package-lock.json | 9642 ++++++++++++++++- .../monitor/diagnosticsCapturedCategories.js | 65 + .../diagnosticsCapturedCategories.spec.js | 149 + .../monitor/diagnosticsSettingsEnabled.js | 41 + .../diagnosticsSettingsEnabled.spec.js | 180 + .../azure/sqlserver/auditRetentionPolicy.js | 2 +- plugins/google/vpcnetwork/openAllPorts.js | 4 +- plugins/google/vpcnetwork/openCIFS.js | 2 +- plugins/google/vpcnetwork/openCassandra.js | 2 +- plugins/google/vpcnetwork/openCustomPorts.js | 2 +- plugins/google/vpcnetwork/openDNS.js | 2 +- plugins/google/vpcnetwork/openDocker.js | 2 +- plugins/google/vpcnetwork/openFTP.js | 2 +- .../google/vpcnetwork/openHadoopNameNode.js | 2 +- .../vpcnetwork/openHadoopNameNodeWebUI.js | 2 +- plugins/google/vpcnetwork/openKibana.js | 2 +- plugins/google/vpcnetwork/openMongo.js | 2 +- plugins/google/vpcnetwork/openMsSQL.js | 2 +- plugins/google/vpcnetwork/openMySQL.js | 2 +- plugins/google/vpcnetwork/openNetBIOS.js | 2 +- plugins/google/vpcnetwork/openOracle.js | 2 +- .../vpcnetwork/openOracleAutoDataWarehouse.js | 2 +- plugins/google/vpcnetwork/openPostgreSQL.js | 2 +- plugins/google/vpcnetwork/openRDP.js | 2 +- plugins/google/vpcnetwork/openRPC.js | 2 +- plugins/google/vpcnetwork/openRedis.js | 2 +- plugins/google/vpcnetwork/openSMBoTCP.js | 2 +- plugins/google/vpcnetwork/openSMTP.js | 2 +- plugins/google/vpcnetwork/openSQLServer.js | 2 +- plugins/google/vpcnetwork/openSSH.js | 2 +- plugins/google/vpcnetwork/openSalt.js | 2 +- plugins/google/vpcnetwork/openTelnet.js | 2 +- plugins/google/vpcnetwork/openVNCClient.js | 2 +- plugins/google/vpcnetwork/openVNCServer.js | 2 +- 36 files changed, 10027 insertions(+), 120 deletions(-) create mode 100644 plugins/azure/monitor/diagnosticsCapturedCategories.js create mode 100644 plugins/azure/monitor/diagnosticsCapturedCategories.spec.js create mode 100644 plugins/azure/monitor/diagnosticsSettingsEnabled.js create mode 100644 plugins/azure/monitor/diagnosticsSettingsEnabled.spec.js diff --git a/exports.js b/exports.js index b24a16826f..c37bad6793 100644 --- a/exports.js +++ b/exports.js @@ -611,6 +611,8 @@ module.exports = { 'logProfileArchiveData' : require(__dirname + '/plugins/azure/monitor/logProfileArchiveData.js'), 'logProfileRetentionPolicy' : require(__dirname + '/plugins/azure/monitor/logProfileRetentionPolicy.js'), 'monitorLogsEnabled' : require(__dirname + '/plugins/azure/monitor/monitorLogsEnabled.js'), + 'diagnosticsCapturedCategories' : require(__dirname + '/plugins/azure/monitor/diagnosticsCapturedCategories.js'), + 'diagnosticsSettingsEnabled' : require(__dirname + '/plugins/azure/monitor/diagnosticsSettingsEnabled.js'), 'securityPolicyAlertsEnabled' : require(__dirname + '/plugins/azure/logalerts/securityPolicyAlertsEnabled.js'), 'nsgLoggingEnabled' : require(__dirname + '/plugins/azure/logalerts/nsgLoggingEnabled.js'), diff --git a/helpers/google/functions.js b/helpers/google/functions.js index ecd858d658..d1928d041f 100644 --- a/helpers/google/functions.js +++ b/helpers/google/functions.js @@ -68,14 +68,14 @@ function addResult(results, status, message, region, resource, custom, err, requ } } -function findOpenPorts(ngs, protocols, service, location, results, cache, callback, source) { +function findOpenPorts(ngs, protocols, service, location, results, cache, source) { let projects = shared.addSource(cache, source, ['projects','get', 'global']); if (!projects || projects.err || !projects.data || !projects.data.length) { addResult(results, 3, 'Unable to query for projects: ' + shared.addError(projects), 'global', null, null, (projects) ? projects.err : null); - return callback(null, results, source); + return; } var project = projects.data[0].name; @@ -137,14 +137,14 @@ function findOpenPorts(ngs, protocols, service, location, results, cache, callba } } -function findOpenAllPorts(ngs, location, results, cache, callback, source) { +function findOpenAllPorts(ngs, location, results, cache, source) { let projects = shared.addSource(cache, source, ['projects','get', 'global']); if (!projects || projects.err || !projects.data || !projects.data.length) { addResult(results, 3, 'Unable to query for projects: ' + shared.addError(projects), 'global', null, null, (projects) ? projects.err : null); - return callback(null, results, source); + return; } var project = projects.data[0].name; diff --git a/package-lock.json b/package-lock.json index 65efe2181f..dfd86919fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,9395 @@ { "name": "cloudsploit", "version": "2.0.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "cloudsploit", + "version": "2.0.0", + "license": "GPL-3.0-or-later", + "dependencies": { + "@alicloud/pop-core": "^1.7.10", + "@octokit/app": "^3.0.0", + "@octokit/request": "^3.0.3", + "@octokit/rest": "^16.3.2", + "ali-oss": "^6.15.2", + "argparse": "^2.0.0", + "async": "^2.6.1", + "aws-sdk": "^2.1148.0", + "azure-storage": "^2.10.3", + "csv-write-stream": "^2.0.0", + "fast-safe-stringify": "^2.0.6", + "googleapis": "^76.0.0", + "minimatch": "^3.0.4", + "ms-rest-azure": "^2.6.0", + "tty-table": "^4.1.3" + }, + "bin": { + "cloudsploit-scan": "index.js" + }, + "devDependencies": { + "chai": "^4.2.0", + "eslint": "^6.8.0", + "mocha": "^6.1.4", + "nodemon": "^1.19.4", + "nyc": "^14.1.1" + } + }, + "node_modules/@alicloud/pop-core": { + "version": "1.7.10", + "resolved": "https://registry.npmjs.org/@alicloud/pop-core/-/pop-core-1.7.10.tgz", + "integrity": "sha512-9/aLWgmgaAdB1ERNTpdOvF7wueLY5CDTRxKZr93x542iuYRA1NDpcKslFqLOy5CUOa0CbopET3JGaHSAz5qv9g==", + "dependencies": { + "debug": "^3.1.0", + "httpx": "^2.1.2", + "json-bigint": "^1.0.0", + "kitx": "^1.2.1", + "xml2js": "^0.4.17" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.12.13" + } + }, + "node_modules/@babel/generator": { + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.3.tgz", + "integrity": "sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.2", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "node_modules/@babel/generator/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz", + "integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==", + "dev": true, + "dependencies": { + "@babel/helper-get-function-arity": "^7.12.13", + "@babel/template": "^7.12.13", + "@babel/types": "^7.14.2" + } + }, + "node_modules/@babel/helper-get-function-arity": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", + "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", + "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", + "dev": true + }, + "node_modules/@babel/highlight": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.14.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.4.tgz", + "integrity": "sha512-ArliyUsWDUqEGfWcmzpGUzNfLxTdTp6WU4IuP6QFSp9gGfWS6boxFCkJSJ/L4+RG8z/FnIU3WxCk6hPL9SSWeA==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/traverse": { + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz", + "integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.14.2", + "@babel/helper-function-name": "^7.14.2", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.14.2", + "@babel/types": "^7.14.2", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/types": { + "version": "7.14.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.4.tgz", + "integrity": "sha512-lCj4aIs0xUefJFQnwwQv2Bxg7Omd6bgquZ6LGC+gGMh6/s5qDVfjuCMlDmYQ15SLsWHd9n+X3E75lKIhl5Lkiw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.0", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@octokit/app": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@octokit/app/-/app-3.0.2.tgz", + "integrity": "sha512-+roaPRJiJz8a4msGtV6YwJitOEXbBRLlneAjnMFzGmqLT8yJAqJCd/k9LfTVPyr7pbl/IhEDl6cMDJrTcxlCeg==", + "deprecated": "'@octokit/app' will be repurposed in future. Use '@octokit/auth-app' instead", + "dependencies": { + "@octokit/request": "^5.0.0", + "jsonwebtoken": "^8.3.0", + "lru-cache": "^5.1.1" + } + }, + "node_modules/@octokit/app/node_modules/@octokit/request": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.5.0.tgz", + "integrity": "sha512-jxbMLQdQ3heFMZUaTLSCqcKs2oAHEYh7SnLLXyxbZmlULExZ/RXai7QUWWFKowcGGPlCZuKTZg0gSKHWrfYEoQ==", + "dependencies": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.0.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.1", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/auth-token": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.5.tgz", + "integrity": "sha512-BpGYsPgJt05M7/L/5FoE1PiAbdxXFZkX/3kDYcsvd1v6UhlnE5e96dTDr0ezX/EFwciQxf3cNV0loipsURU+WA==", + "dependencies": { + "@octokit/types": "^6.0.3" + } + }, + "node_modules/@octokit/endpoint": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.11.tgz", + "integrity": "sha512-fUIPpx+pZyoLW4GCs3yMnlj2LfoXTWDUVPTC4V3MUEKZm48W+XYpeWSZCv+vYF1ZABUm2CqnDVf1sFtIYrj7KQ==", + "dependencies": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-7.3.0.tgz", + "integrity": "sha512-o00X2FCLiEeXZkm1Ab5nvPUdVOlrpediwWZkpizUJ/xtZQsJ4FiQ2RB/dJEmb0Nk+NIz7zyDePcSCu/Y/0M3Ew==" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz", + "integrity": "sha512-jbsSoi5Q1pj63sC16XIUboklNw+8tL9VOnJsWycWYR78TKss5PVpIPb1TUUcMQ+bBh7cY579cVAWmf5qG+dw+Q==", + "dependencies": { + "@octokit/types": "^2.0.1" + } + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", + "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", + "dependencies": { + "@types/node": ">= 8" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.3.tgz", + "integrity": "sha512-4RFU4li238jMJAzLgAwkBAw+4Loile5haQMQr+uhFq27BmyJXcXSKvoQKqh0agsZEiUlW6iSv3FAgvmGkur7OQ==", + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.4.0.tgz", + "integrity": "sha512-EZi/AWhtkdfAYi01obpX0DF7U6b1VRr30QNQ5xSFPITMdLSfhcBqjamE3F+sKcxPbD7eZuMHu3Qkk2V+JGxBDQ==", + "dependencies": { + "@octokit/types": "^2.0.1", + "deprecation": "^2.3.1" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", + "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", + "dependencies": { + "@types/node": ">= 8" + } + }, + "node_modules/@octokit/request": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-3.0.3.tgz", + "integrity": "sha512-M7pUfsiaiiUMEP4/SMysTeWxyGrkoQg6FBPEtCBIFgeDnzHaPboTpUZGTh6u1GQXdrlzMfPVn/vQs98js1QtwQ==", + "dependencies": { + "@octokit/endpoint": "^5.1.0", + "deprecation": "^1.0.1", + "is-plain-object": "^3.0.0", + "node-fetch": "^2.3.0", + "once": "^1.4.0", + "universal-user-agent": "^2.0.1" + } + }, + "node_modules/@octokit/request-error": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.5.tgz", + "integrity": "sha512-T/2wcCFyM7SkXzNoyVNWjyVlUwBvW3igM3Btr/eKYiPmucXTtkxt2RBsf6gn3LTzaLSLTQtNmvg+dGsOxQrjZg==", + "dependencies": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "node_modules/@octokit/request/node_modules/@octokit/endpoint": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-5.5.3.tgz", + "integrity": "sha512-EzKwkwcxeegYYah5ukEeAI/gYRLv2Y9U5PpIsseGSFDk+G3RbipQGBs8GuYS1TLCtQaqoO66+aQGtITPalxsNQ==", + "dependencies": { + "@octokit/types": "^2.0.0", + "is-plain-object": "^3.0.0", + "universal-user-agent": "^5.0.0" + } + }, + "node_modules/@octokit/request/node_modules/@octokit/endpoint/node_modules/universal-user-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-5.0.0.tgz", + "integrity": "sha512-B5TPtzZleXyPrUMKCpEHFmVhMN6EhmJYjG5PQna9s7mXeSqGTLap4OpqLl5FCEFUI3UBmllkETwKf/db66Y54Q==", + "dependencies": { + "os-name": "^3.1.0" + } + }, + "node_modules/@octokit/request/node_modules/@octokit/types": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", + "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", + "dependencies": { + "@types/node": ">= 8" + } + }, + "node_modules/@octokit/request/node_modules/deprecation": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-1.0.1.tgz", + "integrity": "sha512-ccVHpE72+tcIKaGMql33x5MAjKQIZrk+3x2GbJ7TeraUCZWHoT+KSZpoC+JQFsUBlSTXUrBaGiF0j6zVTepPLg==" + }, + "node_modules/@octokit/request/node_modules/is-plain-object": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", + "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@octokit/request/node_modules/universal-user-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-2.1.0.tgz", + "integrity": "sha512-8itiX7G05Tu3mGDTdNY2fB4KJ8MgZLS54RdG6PkkfwMAavrXu1mV/lls/GABx9O3Rw4PnTtasxrvbMQoBYY92Q==", + "dependencies": { + "os-name": "^3.0.0" + } + }, + "node_modules/@octokit/rest": { + "version": "16.43.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.43.2.tgz", + "integrity": "sha512-ngDBevLbBTFfrHZeiS7SAMAZ6ssuVmXuya+F/7RaVvlysgGa1JKJkKWY+jV6TCJYcW0OALfJ7nTIGXcBXzycfQ==", + "dependencies": { + "@octokit/auth-token": "^2.4.0", + "@octokit/plugin-paginate-rest": "^1.1.1", + "@octokit/plugin-request-log": "^1.0.0", + "@octokit/plugin-rest-endpoint-methods": "2.4.0", + "@octokit/request": "^5.2.0", + "@octokit/request-error": "^1.0.2", + "atob-lite": "^2.0.0", + "before-after-hook": "^2.0.0", + "btoa-lite": "^1.0.0", + "deprecation": "^2.0.0", + "lodash.get": "^4.4.2", + "lodash.set": "^4.3.2", + "lodash.uniq": "^4.5.0", + "octokit-pagination-methods": "^1.1.0", + "once": "^1.4.0", + "universal-user-agent": "^4.0.0" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/request": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.5.0.tgz", + "integrity": "sha512-jxbMLQdQ3heFMZUaTLSCqcKs2oAHEYh7SnLLXyxbZmlULExZ/RXai7QUWWFKowcGGPlCZuKTZg0gSKHWrfYEoQ==", + "dependencies": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.0.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.1", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/request-error": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-1.2.1.tgz", + "integrity": "sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA==", + "dependencies": { + "@octokit/types": "^2.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/request-error/node_modules/@octokit/types": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", + "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", + "dependencies": { + "@types/node": ">= 8" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/request/node_modules/@octokit/request-error": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.5.tgz", + "integrity": "sha512-T/2wcCFyM7SkXzNoyVNWjyVlUwBvW3igM3Btr/eKYiPmucXTtkxt2RBsf6gn3LTzaLSLTQtNmvg+dGsOxQrjZg==", + "dependencies": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/request/node_modules/universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, + "node_modules/@octokit/rest/node_modules/universal-user-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.1.tgz", + "integrity": "sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg==", + "dependencies": { + "os-name": "^3.1.0" + } + }, + "node_modules/@octokit/types": { + "version": "6.16.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.16.2.tgz", + "integrity": "sha512-wWPSynU4oLy3i4KGyk+J1BLwRKyoeW2TwRHgwbDz17WtVFzSK2GOErGliruIx8c+MaYtHSYTx36DSmLNoNbtgA==", + "dependencies": { + "@octokit/openapi-types": "^7.2.3" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/node": { + "version": "14.17.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.3.tgz", + "integrity": "sha512-e6ZowgGJmTuXa3GyaPbTGxX17tnThl2aSSizrFthQ7m9uLGZBXiGhgE55cjRZTF5kjZvYn9EOPOMljdjwbflxw==" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/adal-node": { + "version": "0.1.28", + "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.1.28.tgz", + "integrity": "sha1-RoxLs+u9lrEnBmn0ucuk4AZepIU=", + "dependencies": { + "@types/node": "^8.0.47", + "async": ">=0.6.0", + "date-utils": "*", + "jws": "3.x.x", + "request": ">= 2.52.0", + "underscore": ">= 1.3.1", + "uuid": "^3.1.0", + "xmldom": ">= 0.1.x", + "xpath.js": "~1.1.0" + }, + "engines": { + "node": ">= 0.6.15" + } + }, + "node_modules/adal-node/node_modules/@types/node": { + "version": "8.10.66", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", + "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==" + }, + "node_modules/address": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", + "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/agentkeepalive": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", + "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ali-oss": { + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/ali-oss/-/ali-oss-6.15.2.tgz", + "integrity": "sha512-sLB3a2Q6BvD4fNfHO4a0uuVn+5dlFaWUE/tExFk8bNMTevNGb4hH419kyvTSvKsO8FGLIhyezdi2NVhLHwhPqA==", + "dependencies": { + "address": "^1.0.0", + "agentkeepalive": "^3.4.1", + "bowser": "^1.6.0", + "co-defer": "^1.0.0", + "copy-to": "^2.0.1", + "dateformat": "^2.0.0", + "debug": "^2.2.0", + "destroy": "^1.0.4", + "end-or-error": "^1.0.1", + "get-ready": "^1.0.0", + "humanize-ms": "^1.2.0", + "is-type-of": "^1.0.0", + "js-base64": "^2.5.2", + "jstoxml": "^0.2.3", + "merge-descriptors": "^1.0.1", + "mime": "^2.4.5", + "mz-modules": "^2.1.0", + "platform": "^1.3.1", + "pump": "^3.0.0", + "sdk-base": "^2.0.1", + "stream-http": "2.8.2", + "stream-wormhole": "^1.0.4", + "urllib": "^2.33.1", + "utility": "^1.8.0", + "xml2js": "^0.4.16" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ali-oss/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ali-oss/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "dev": true, + "dependencies": { + "string-width": "^2.0.0" + } + }, + "node_modules/ansi-align/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-align/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-align/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "dev": true, + "dependencies": { + "default-require-extensions": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", + "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "engines": { + "node": ">=8" + } + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/atob-lite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", + "integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=" + }, + "node_modules/aws-sdk": { + "version": "2.1152.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1152.0.tgz", + "integrity": "sha512-Lqwk0bDhm3vzpYb3AAM9VgGHeDpbB8+o7UJnP9R+CO23kJfi/XRpKihAcbyKDD/AUQ+O1LJaUVpvaJYLS9Am7w==", + "dependencies": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.16.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "8.0.0", + "xml2js": "0.4.19" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aws-sdk/node_modules/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "node_modules/aws-sdk/node_modules/uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/aws-sdk/node_modules/xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "node_modules/aws-sdk/node_modules/xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, + "node_modules/azure-storage": { + "version": "2.10.4", + "resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.10.4.tgz", + "integrity": "sha512-zlfRPl4js92JC6+79C2EUmNGYjSknRl8pOiHQF78zy+pbOFOHtlBF6BU/OxPeHQX3gaa6NdEZnVydFxhhndkEw==", + "deprecated": "Please note: newer packages @azure/storage-blob, @azure/storage-queue and @azure/storage-file are available as of November 2019 and @azure/data-tables is available as of June 2021. While the legacy azure-storage package will continue to receive critical bug fixes, we strongly encourage you to upgrade. Migration guide can be found: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/storage/MigrationGuide.md", + "dependencies": { + "browserify-mime": "~1.2.9", + "extend": "^3.0.2", + "json-edm-parser": "0.1.2", + "md5.js": "1.3.4", + "readable-stream": "~2.0.0", + "request": "^2.86.0", + "underscore": "^1.12.1", + "uuid": "^3.0.0", + "validator": "~9.4.1", + "xml2js": "0.2.8", + "xmlbuilder": "^9.0.7" + }, + "engines": { + "node": ">= 0.8.26" + } + }, + "node_modules/azure-storage/node_modules/process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "node_modules/azure-storage/node_modules/readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/azure-storage/node_modules/sax": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz", + "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=" + }, + "node_modules/azure-storage/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "node_modules/azure-storage/node_modules/xml2js": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz", + "integrity": "sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=", + "dependencies": { + "sax": "0.5.x" + } + }, + "node_modules/azure-storage/node_modules/xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/before-after-hook": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", + "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" + }, + "node_modules/bignumber.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bindings/node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "node_modules/bowser": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz", + "integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==" + }, + "node_modules/boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "dev": true, + "dependencies": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/boxen/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/boxen/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/boxen/node_modules/camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/boxen/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/boxen/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/boxen/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/boxen/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/boxen/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/boxen/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/boxen/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/boxen/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/breakword": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/breakword/-/breakword-1.0.5.tgz", + "integrity": "sha512-ex5W9DoOQ/LUEU3PMdLs9ua/CYZl1678NUkKOdUSi8Aw5F1idieaiRURCBFJCwVcrD1J8Iy3vfWSloaMwO2qFg==", + "dependencies": { + "wcwidth": "^1.0.1" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/browserify-mime": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/browserify-mime/-/browserify-mime-1.2.9.tgz", + "integrity": "sha1-rrGvKN5sDXpqLOQK22j/GEIq8x8=" + }, + "node_modules/btoa-lite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", + "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=" + }, + "node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caching-transform": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", + "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", + "dev": true, + "dependencies": { + "hasha": "^3.0.0", + "make-dir": "^2.0.0", + "package-hash": "^3.0.0", + "write-file-atomic": "^2.4.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/caching-transform/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/caching-transform/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/capture-stack-trace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", + "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "node_modules/chai": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/chokidar/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/co-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/co-defer/-/co-defer-1.0.0.tgz", + "integrity": "sha1-Pkp4eo7tawoh7ih8CU9+jeDTyBg=", + "engines": { + "node": ">= 0.11.14" + }, + "peerDependencies": { + "co": "4" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/configstore": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.5.tgz", + "integrity": "sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA==", + "dev": true, + "dependencies": { + "dot-prop": "^4.2.1", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/convert-source-map/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-to": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz", + "integrity": "sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU=" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/cp-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", + "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "make-dir": "^2.0.0", + "nested-error-stacks": "^2.0.0", + "pify": "^4.0.1", + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cp-file/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cp-file/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "dev": true, + "dependencies": { + "capture-stack-trace": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/csv": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/csv/-/csv-5.5.0.tgz", + "integrity": "sha512-32tcuxdb4HW3zbk8NBcVQb8/7xuJB5sv+q4BuQ6++E/K6JvHvWoCHcGzB5Au95vVikNH4ztE0XNC/Bws950cfA==", + "dependencies": { + "csv-generate": "^3.4.0", + "csv-parse": "^4.15.3", + "csv-stringify": "^5.6.2", + "stream-transform": "^2.1.0" + }, + "engines": { + "node": ">= 0.1.90" + } + }, + "node_modules/csv-generate": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-3.4.0.tgz", + "integrity": "sha512-D6yi7c6lL70cpTx3TQIVWKrfxuLiKa0pBizu0zi7fSRXlhmE7u674gk9k1IjCEnxKq2t6xzbXnxcOmSdBbE8vQ==" + }, + "node_modules/csv-parse": { + "version": "4.15.4", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.15.4.tgz", + "integrity": "sha512-OdBbFc0yZhOm17lSxqkirrHlFFVpKRT0wp4DAGoJelsP3LbGzV9LNr7XmM/lrr0uGkCtaqac9UhP8PDHXOAbMg==" + }, + "node_modules/csv-stringify": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-5.6.2.tgz", + "integrity": "sha512-n3rIVbX6ylm1YsX2NEug9IaPV8xRnT+9/NNZbrA/bcHgOSSeqtWla6XnI/xmyu57wIw+ASCAoX1oM6EZtqJV0A==" + }, + "node_modules/csv-write-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/csv-write-stream/-/csv-write-stream-2.0.0.tgz", + "integrity": "sha1-/C2iGkjW6l+MF/3jnPuRHk8CkrA=", + "dependencies": { + "argparse": "^1.0.7", + "generate-object-property": "^1.0.0", + "ndjson": "^1.3.0" + }, + "bin": { + "csv-write": "cli.js" + } + }, + "node_modules/csv-write-stream/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", + "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/date-utils": { + "version": "1.2.21", + "resolved": "https://registry.npmjs.org/date-utils/-/date-utils-1.2.21.tgz", + "integrity": "sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q=", + "engines": { + "node": ">0.4.0" + } + }, + "node_modules/dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "node_modules/default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "dev": true, + "dependencies": { + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/default-user-agent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-user-agent/-/default-user-agent-1.0.0.tgz", + "integrity": "sha1-FsRu/cq6PtxF8k8r1IaLAbfCrcY=", + "dependencies": { + "os-name": "~1.0.3" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/default-user-agent/node_modules/os-name": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-1.0.3.tgz", + "integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=", + "dependencies": { + "osx-release": "^1.0.0", + "win-release": "^1.0.0" + }, + "bin": { + "os-name": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dependencies": { + "clone": "^1.0.2" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/degenerator": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-2.2.0.tgz", + "integrity": "sha512-aiQcQowF01RxFI4ZLFMpzyotbQonhNpBao6dkI8JPk5a+hmSjR5ErHp2CQySmQe8os3VBqLCIh87nDBgZXvsmg==", + "dependencies": { + "ast-types": "^0.13.2", + "escodegen": "^1.8.1", + "esprima": "^4.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/digest-header": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/digest-header/-/digest-header-0.0.1.tgz", + "integrity": "sha1-Ecz23uxXZqw3l0TZAcEsuklRS+Y=", + "dependencies": { + "utility": "0.1.11" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/digest-header/node_modules/utility": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/utility/-/utility-0.1.11.tgz", + "integrity": "sha1-/eYM+bTkdRlHoM9dEEzik2ciZxU=", + "dependencies": { + "address": ">=0.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dot-prop": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", + "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==", + "dev": true, + "dependencies": { + "is-obj": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/end-or-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/end-or-error/-/end-or-error-1.0.1.tgz", + "integrity": "sha1-3HpiEP5403L+4kqLSJnb0VVBTcs=", + "engines": { + "node": ">= 0.11.14" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", + "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.10.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/eslint": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/espree": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "dev": true, + "dependencies": { + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "node_modules/fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" + }, + "node_modules/fast-text-encoding": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", + "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==" + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "dependencies": { + "flat-cache": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/file-uri-to-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", + "integrity": "sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", + "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "dev": true, + "dependencies": { + "is-buffer": "~2.0.3" + }, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "dependencies": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/flat/node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=4" + } + }, + "node_modules/flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/foreground-child": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", + "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", + "dev": true, + "dependencies": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + } + }, + "node_modules/foreground-child/node_modules/cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "dev": true, + "dependencies": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "node_modules/foreground-child/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/foreground-child/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/formstream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/formstream/-/formstream-1.1.1.tgz", + "integrity": "sha512-yHRxt3qLFnhsKAfhReM4w17jP+U1OlhUjnKPPtonwKbIJO7oBP0MvoxkRUwb8AU9n0MIkYy5X5dK6pQnbj+R2Q==", + "dependencies": { + "destroy": "^1.0.4", + "mime": "^2.5.2", + "pause-stream": "~0.0.11" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "dependencies": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ftp/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "node_modules/ftp/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/ftp/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/gaxios": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "dependencies": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gaxios/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gcp-metadata": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "dependencies": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dependencies": { + "is-property": "^1.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-ready": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-ready/-/get-ready-1.0.0.tgz", + "integrity": "sha1-+RgX8emt7P6hOlYq38jeiDqzR4I=" + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/get-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz", + "integrity": "sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==", + "dependencies": { + "@tootallnate/once": "1", + "data-uri-to-buffer": "3", + "debug": "4", + "file-uri-to-path": "2", + "fs-extra": "^8.1.0", + "ftp": "^0.3.10" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/get-uri/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/get-uri/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "dependencies": { + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "dependencies": { + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/google-auth-library": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", + "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", + "dependencies": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/google-auth-library/node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/google-auth-library/node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/google-auth-library/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/google-auth-library/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/google-p12-pem": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", + "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", + "dependencies": { + "node-forge": "^1.3.1" + }, + "bin": { + "gp12-pem": "build/src/bin/gp12-pem.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/googleapis": { + "version": "76.0.0", + "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-76.0.0.tgz", + "integrity": "sha512-l/TFSW7IRFcb7wF641BlmuP8Ox1ncuzJk5Fcs2947otlGBm5ktDxFhPkmrcNDaG+LWPQsuDwP1ojL0xV39cpmw==", + "dependencies": { + "google-auth-library": "^7.0.2", + "googleapis-common": "^5.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/googleapis-common": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-5.1.0.tgz", + "integrity": "sha512-RXrif+Gzhq1QAzfjxulbGvAY3FPj8zq/CYcvgjzDbaBNCD6bUl+86I7mUs4DKWHGruuK26ijjR/eDpWIDgNROA==", + "dependencies": { + "extend": "^3.0.2", + "gaxios": "^4.0.0", + "google-auth-library": "^7.14.0", + "qs": "^6.7.0", + "url-template": "^2.0.8", + "uuid": "^8.0.0" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/googleapis-common/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "dev": true, + "dependencies": { + "create-error-class": "^3.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/got/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/gtoken": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", + "dependencies": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gtoken/node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/gtoken/node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hasha": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", + "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", + "dev": true, + "dependencies": { + "is-stream": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/httpx": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/httpx/-/httpx-2.2.7.tgz", + "integrity": "sha512-Wjh2JOAah0pdczfqL8NC5378G7jMt0Zcpn8U+yyxAiejjlagzSTQgJHuVvka2VNPQlKfoGehYRc79WKq9E4gDw==", + "dependencies": { + "@types/node": "^14", + "debug": "^4.1.1" + } + }, + "node_modules/httpx/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/httpx/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", + "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "dependencies": { + "ci-info": "^1.5.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-class-hotfix": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/is-class-hotfix/-/is-class-hotfix-0.0.6.tgz", + "integrity": "sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ==" + }, + "node_modules/is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-date-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", + "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "dependencies": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "dependencies": { + "path-is-inside": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, + "node_modules/is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "dependencies": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-string": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-type-of": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-type-of/-/is-type-of-1.2.1.tgz", + "integrity": "sha512-uK0kyX9LZYhSDS7H2sVJQJop1UnWPWmo5RvR3q2kFH6AUHYs7sOrVg0b4nyBHw29kRRNFofYN/JbHZDlHiItTA==", + "dependencies": { + "core-util-is": "^1.0.2", + "is-class-hotfix": "~0.0.6", + "isstream": "~0.1.2" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "node_modules/istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-hook": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", + "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", + "dev": true, + "dependencies": { + "append-transform": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-report/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/istanbul-lib-source-maps/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-reports": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", + "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jmespath": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/js-base64": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js-yaml/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-edm-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/json-edm-parser/-/json-edm-parser-0.1.2.tgz", + "integrity": "sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ=", + "dependencies": { + "jsonparse": "~1.2.0" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.2.0.tgz", + "integrity": "sha1-XAxWhRBxYOcv50ib3eoLRMK8Z70=", + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/jstoxml": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/jstoxml/-/jstoxml-0.2.4.tgz", + "integrity": "sha1-/z+2eFaIOgMpU8fOjOdIYhD0hEc=", + "engines": { + "node": ">=0.2.0" + } + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kitx": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/kitx/-/kitx-1.3.0.tgz", + "integrity": "sha512-fhBqFlXd0GkKTB+8ayLfpzPUw+LHxZlPAukPNBD1Om7JMeInT+/PxCAf1yLagvD+VKoyWhXtJR68xQkX/a0wOQ==" + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/ko-sleep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ko-sleep/-/ko-sleep-1.0.3.tgz", + "integrity": "sha1-KKKgoUhei39BX/SI3uF9JHiKsII=", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "dev": true, + "dependencies": { + "package-json": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, + "node_modules/lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + }, + "node_modules/log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "dependencies": { + "chalk": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/macos-release": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.0.tgz", + "integrity": "sha512-EIgv+QZ9r+814gjJj0Bt5vSLJLzswGmSUbUpbi9AIr/fsN2IWFBl2NucV9PAiek+U1STK468tEkxmVYUtuAN3g==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", + "dependencies": { + "mime-db": "1.48.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixme": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mixme/-/mixme-0.5.1.tgz", + "integrity": "sha512-NaeZIckeBFT7i0XBEpGyFcAE0/bLcQ9MHErTpnU3bLWVE5WZbxG5Y3fDsMxYGifTo5khDA42OquXCC2ngKJB+g==", + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", + "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", + "dev": true, + "dependencies": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.4", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/mocha/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/mocha/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/mocha/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/mocha/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/mocha/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/mocha/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/mocha/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/mocha/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/mkdirp": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", + "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/mocha/node_modules/object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mocha/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/mocha/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/mocha/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/ms-rest": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/ms-rest/-/ms-rest-2.5.4.tgz", + "integrity": "sha512-VeqCbawxRM6nhw0RKNfj7TWL7SL8PB6MypqwgylXCi+u412uvYoyY/kSmO8n06wyd8nIcnTbYToCmSKFMI1mCg==", + "dependencies": { + "duplexer": "^0.1.1", + "is-buffer": "^1.1.6", + "is-stream": "^1.1.0", + "moment": "^2.21.0", + "request": "^2.88.0", + "through": "^2.3.8", + "tunnel": "0.0.5", + "uuid": "^3.2.1" + } + }, + "node_modules/ms-rest-azure": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/ms-rest-azure/-/ms-rest-azure-2.6.0.tgz", + "integrity": "sha512-J6386a9krZ4VtU7CRt+Ypgo9RGf8+d3gjMBkH7zbkM4zzkhbbMOYiPRaZ+bHZcfihkKLlktTgA6rjshTjF329A==", + "dependencies": { + "adal-node": "^0.1.28", + "async": "2.6.0", + "moment": "^2.22.2", + "ms-rest": "^2.3.2", + "request": "^2.88.0", + "uuid": "^3.2.1" + } + }, + "node_modules/ms-rest-azure/node_modules/async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dependencies": { + "lodash": "^4.14.0" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/mz-modules": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mz-modules/-/mz-modules-2.1.0.tgz", + "integrity": "sha512-sjk8lcRW3vrVYnZ+W+67L/2rL+jbO5K/N6PFGIcLWTiYytNr22Ah9FDXFs+AQntTM1boZcoHi5qS+CV1seuPog==", + "dependencies": { + "glob": "^7.1.2", + "ko-sleep": "^1.0.3", + "mkdirp": "^0.5.1", + "pump": "^3.0.0", + "rimraf": "^2.6.1" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true, + "optional": true + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/ndjson": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-1.5.0.tgz", + "integrity": "sha1-rmA7NrE0vOw0e0UkIrC/mNWDLsg=", + "dependencies": { + "json-stringify-safe": "^5.0.1", + "minimist": "^1.2.0", + "split2": "^2.1.0", + "through2": "^2.0.3" + }, + "bin": { + "ndjson": "cli.js" + } + }, + "node_modules/nested-error-stacks": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", + "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", + "dev": true + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "node_modules/node-environment-flags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", + "dev": true, + "dependencies": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/nodemon": { + "version": "1.19.4", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.19.4.tgz", + "integrity": "sha512-VGPaqQBNk193lrJFotBU8nvWZPqEZY2eIzymy2jjY0fJ9qIsxA0sxQ8ATPl0gZC645gijYEc1jtZvpS8QWzJGQ==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "chokidar": "^2.1.8", + "debug": "^3.2.6", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.7", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.2", + "update-notifier": "^2.5.0" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", + "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", + "dev": true, + "dependencies": { + "archy": "^1.0.0", + "caching-transform": "^3.0.2", + "convert-source-map": "^1.6.0", + "cp-file": "^6.2.0", + "find-cache-dir": "^2.1.0", + "find-up": "^3.0.0", + "foreground-child": "^1.5.6", + "glob": "^7.1.3", + "istanbul-lib-coverage": "^2.0.5", + "istanbul-lib-hook": "^2.0.7", + "istanbul-lib-instrument": "^3.3.0", + "istanbul-lib-report": "^2.0.8", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^2.2.4", + "js-yaml": "^3.13.1", + "make-dir": "^2.1.0", + "merge-source-map": "^1.1.0", + "resolve-from": "^4.0.0", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.2", + "spawn-wrap": "^1.4.2", + "test-exclude": "^5.2.3", + "uuid": "^3.3.2", + "yargs": "^13.2.2", + "yargs-parser": "^13.0.0" + }, + "bin": { + "nyc": "bin/nyc.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/nyc/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/nyc/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/nyc/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/nyc/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/nyc/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", + "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/octokit-pagination-methods": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz", + "integrity": "sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-name": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", + "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==", + "dependencies": { + "macos-release": "^2.2.0", + "windows-release": "^3.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/osx-release": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/osx-release/-/osx-release-1.1.0.tgz", + "integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=", + "dependencies": { + "minimist": "^1.1.0" + }, + "bin": { + "osx-release": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pac-proxy-agent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-4.1.0.tgz", + "integrity": "sha512-ejNgYm2HTXSIYX9eFlkvqFp8hyJ374uDf0Zq5YUAifiSh1D6fo+iBivQZirGvVv8dCYUsLhmLBRhlAYvBKI5+Q==", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4", + "get-uri": "3", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "5", + "pac-resolver": "^4.1.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pac-proxy-agent/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/pac-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/pac-resolver": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-4.2.0.tgz", + "integrity": "sha512-rPACZdUyuxT5Io/gFKUeeZFfE5T7ve7cAkE5TUZRRfuKP0u5Hocwe48X7ZEm6mYB+bTB0Qf+xlVlA/RM/i6RCQ==", + "dependencies": { + "degenerator": "^2.2.0", + "ip": "^1.1.5", + "netmask": "^2.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/package-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", + "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.15", + "hasha": "^3.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "dev": true, + "dependencies": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dependencies": { + "through": "~2.3" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-4.0.1.tgz", + "integrity": "sha512-ODnQnW2jc/FUVwHHuaZEfN5otg/fMbvMxz9nMSUQfJ9JU7q2SZvSULSsjLloVgJOiv9yhc8GlNMKc4GkFmcVEA==", + "dependencies": { + "agent-base": "^6.0.0", + "debug": "4", + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", + "lru-cache": "^5.1.1", + "pac-proxy-agent": "^4.1.0", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/proxy-agent/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "node_modules/qs": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", + "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/raw-body": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", + "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.3", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true, + "engines": { + "node": ">=6.5.0" + } + }, + "node_modules/registry-auth-token": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", + "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", + "dev": true, + "dependencies": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "dependencies": { + "rc": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "node_modules/repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", + "dev": true + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/rxjs/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/sdk-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/sdk-base/-/sdk-base-2.0.1.tgz", + "integrity": "sha1-ukAonovfJy7RHdnql+r5jgNtJMY=", + "dependencies": { + "get-ready": "~1.0.0" + } + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "dependencies": { + "semver": "^5.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "node_modules/slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/smartwrap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/smartwrap/-/smartwrap-2.0.2.tgz", + "integrity": "sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==", + "dependencies": { + "array.prototype.flat": "^1.2.3", + "breakword": "^1.0.5", + "grapheme-splitter": "^1.0.4", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1", + "yargs": "^15.1.0" + }, + "bin": { + "smartwrap": "src/terminal-adapter.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/socks": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", + "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", + "dependencies": { + "ip": "^1.1.5", + "smart-buffer": "^4.1.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.0.tgz", + "integrity": "sha512-lEpa1zsWCChxiynk+lCycKuC502RxDWLKJZoIhnxrWNjLSDGYRFflHA1/228VkRcnv9TIb8w98derGbpKxJRgA==", + "dependencies": { + "agent-base": "6", + "debug": "4", + "socks": "^2.3.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/socks-proxy-agent/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socks-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated", + "dev": true + }, + "node_modules/spawn-wrap": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", + "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", + "dev": true, + "dependencies": { + "foreground-child": "^1.5.6", + "mkdirp": "^0.5.0", + "os-homedir": "^1.0.1", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.2", + "which": "^1.3.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", + "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", + "dev": true + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", + "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", + "dependencies": { + "through2": "^2.0.2" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stream-http": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.2.tgz", + "integrity": "sha512-QllfrBhqF1DPcz46WxKTs6Mz1Bpc+8Qm6vbqOpVav5odAXwbyzwnEczoWqtxrsmlO+cJqtPrp/8gWKWjaKLLlA==", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/stream-transform": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-2.1.0.tgz", + "integrity": "sha512-bwQO+75rzQbug7e5OOHnOR3FgbJ0fCjHmDIdynkwUaFzleBXugGmv2dx3sX3aIHUQRLjrcisRPgN9BWl63uGgw==", + "dependencies": { + "mixme": "^0.5.0" + } + }, + "node_modules/stream-wormhole": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stream-wormhole/-/stream-wormhole-1.1.0.tgz", + "integrity": "sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "dependencies": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/table/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/table/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/table/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/table/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "dependencies": { + "execa": "^0.7.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/term-size/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/term-size/node_modules/execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/term-size/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/term-size/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/term-size/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "node_modules/test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "dependencies": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tough-cookie/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + }, + "node_modules/tty-table": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tty-table/-/tty-table-4.1.3.tgz", + "integrity": "sha512-Aireaxah5bTJkkJ7b2RI8tMZxogscWP4UCgi5dKuOqL8BWPjnnOebC7F+oFYWTLKUaiJm8h+CvsigBaaCtxqGw==", + "dependencies": { + "chalk": "^3.0.0", + "csv": "^5.3.2", + "kleur": "^3.0.3", + "smartwrap": "^2.0.1", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1", + "yargs": "^15.3.1" + }, + "bin": { + "tty-table": "adapters/terminal-adapter.js" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.5.tgz", + "integrity": "sha512-gj5sdqherx4VZKMcBA4vewER7zdK25Td+z1npBqpbDys4eJrLx+SlYjJvq1bDXs2irkuJM5pf8ktaEQVipkrbA==", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undefsafe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", + "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", + "dev": true, + "dependencies": { + "debug": "^2.2.0" + } + }, + "node_modules/undefsafe/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/undefsafe/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/underscore": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", + "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" + }, + "node_modules/unescape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unescape/-/unescape-1.0.1.tgz", + "integrity": "sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==", + "dependencies": { + "extend-shallow": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "dependencies": { + "crypto-random-string": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-notifier": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "dev": true, + "dependencies": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-ci": "^1.0.10", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/update-notifier/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/update-notifier/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/update-notifier/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/update-notifier/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/update-notifier/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/update-notifier/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "deprecated": "Please see https://github.com/lydell/urix#deprecated", + "dev": true + }, + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "dependencies": { + "prepend-http": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/url-template": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", + "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=" + }, + "node_modules/urllib": { + "version": "2.37.2", + "resolved": "https://registry.npmjs.org/urllib/-/urllib-2.37.2.tgz", + "integrity": "sha512-OCEapfbtvXBnDes1srNGS7dUzxDVwr4pxk3AEBwGKJ4kJDKg0j5W1nENwnfxMhyl+H523XCrIrMZvcxnJ+gKHQ==", + "dependencies": { + "any-promise": "^1.3.0", + "content-type": "^1.0.2", + "debug": "^2.6.9", + "default-user-agent": "^1.0.0", + "digest-header": "^0.0.1", + "ee-first": "~1.1.1", + "formstream": "^1.1.0", + "humanize-ms": "^1.2.0", + "iconv-lite": "^0.4.15", + "ip": "^1.1.5", + "proxy-agent": "^4.0.1", + "pump": "^3.0.0", + "qs": "^6.4.0", + "statuses": "^1.3.1", + "utility": "^1.16.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/urllib/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/urllib/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/utility": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/utility/-/utility-1.17.0.tgz", + "integrity": "sha512-KdVkF9An/0239BJ4+dqOa7NPrPIOeQE9AGfx0XS16O9DBiHNHRJMoeU5nL6pRGAkgJOqdOu8R4gBRcXnAocJKw==", + "dependencies": { + "copy-to": "^2.0.1", + "escape-html": "^1.0.3", + "mkdirp": "^0.5.1", + "mz": "^2.7.0", + "unescape": "^1.0.1" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validator": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/validator/-/validator-9.4.1.tgz", + "integrity": "sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/wide-align/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "dependencies": { + "string-width": "^2.1.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/widest-line/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/widest-line/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/widest-line/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/widest-line/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/win-release": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz", + "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", + "dependencies": { + "semver": "^5.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/windows-release": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.3.3.tgz", + "integrity": "sha512-OSOGH1QYiW5yVor9TtmXKQvt2vjQqbYS+DqmsZw+r7xDwLXEeT3JGW0ZppFmHx4diyXmxt238KFR3N9jzevBRg==", + "dependencies": { + "execa": "^1.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "dependencies": { + "mkdirp": "^0.5.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmldom": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.6.0.tgz", + "integrity": "sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/xpath.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz", + "integrity": "sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", + "engines": { + "node": "*" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "dependencies": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs-unparser/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/yargs-unparser/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/yargs-unparser/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/yargs-unparser/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/yargs-unparser/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs-unparser/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs-unparser/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/yargs-unparser/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + }, "dependencies": { "@alicloud/pop-core": { "version": "1.7.10", @@ -277,7 +9664,8 @@ "@octokit/plugin-request-log": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.3.tgz", - "integrity": "sha512-4RFU4li238jMJAzLgAwkBAw+4Loile5haQMQr+uhFq27BmyJXcXSKvoQKqh0agsZEiUlW6iSv3FAgvmGkur7OQ==" + "integrity": "sha512-4RFU4li238jMJAzLgAwkBAw+4Loile5haQMQr+uhFq27BmyJXcXSKvoQKqh0agsZEiUlW6iSv3FAgvmGkur7OQ==", + "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { "version": "2.4.0", @@ -494,7 +9882,8 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true + "dev": true, + "requires": {} }, "adal-node": { "version": "0.1.28", @@ -846,18 +10235,18 @@ "integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=" }, "aws-sdk": { - "version": "2.923.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.923.0.tgz", - "integrity": "sha512-93YK9Mx32qvH5eLrDRVkvwpEc7GJ6mces1qQugmNZCuQT68baILyDs0IMRtHS6NYxxiM6XNRFc7ubgMlnafYjg==", + "version": "2.1152.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1152.0.tgz", + "integrity": "sha512-Lqwk0bDhm3vzpYb3AAM9VgGHeDpbB8+o7UJnP9R+CO23kJfi/XRpKihAcbyKDD/AUQ+O1LJaUVpvaJYLS9Am7w==", "requires": { "buffer": "4.9.2", "events": "1.1.1", "ieee754": "1.1.13", - "jmespath": "0.15.0", + "jmespath": "0.16.0", "querystring": "0.2.0", "sax": "1.2.1", "url": "0.10.3", - "uuid": "3.3.2", + "uuid": "8.0.0", "xml2js": "0.4.19" }, "dependencies": { @@ -866,6 +10255,11 @@ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" }, + "uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==" + }, "xml2js": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", @@ -1470,7 +10864,8 @@ "co-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/co-defer/-/co-defer-1.0.0.tgz", - "integrity": "sha1-Pkp4eo7tawoh7ih8CU9+jeDTyBg=" + "integrity": "sha1-Pkp4eo7tawoh7ih8CU9+jeDTyBg=", + "requires": {} }, "collection-visit": { "version": "1.0.0", @@ -2676,41 +12071,31 @@ "dev": true }, "gaxios": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-2.3.4.tgz", - "integrity": "sha512-US8UMj8C5pRnao3Zykc4AAVr+cffoNKRTg9Rsf2GiuZCW69vgJj38VK2PzlPuQU73FZ/nTk9/Av6/JGcE1N9vA==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", "requires": { "abort-controller": "^3.0.0", "extend": "^3.0.2", "https-proxy-agent": "^5.0.0", "is-stream": "^2.0.0", - "node-fetch": "^2.3.0" + "node-fetch": "^2.6.7" }, "dependencies": { "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" } } }, "gcp-metadata": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-2.0.4.tgz", - "integrity": "sha512-p1lXhJvcKvJHWfQXhkd4Za1kyXRsGZA0JH7Cjs07W9hrg84d/j5tqQhbGewlSLx9gNyuQUid69uLux48YbggLg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", "requires": { - "gaxios": "^2.0.1", - "json-bigint": "^0.3.0" - }, - "dependencies": { - "json-bigint": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.1.tgz", - "integrity": "sha512-DGWnSzmusIreWlEupsUelHrhwmPPE+FiQvg+drKfk2p+bdEYa5mp4PJ8JsCWqae0M2jQNb0HPvnwvf1qOTThzQ==", - "requires": { - "bignumber.js": "^9.0.0" - } - } + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" } }, "generate-object-property": { @@ -2838,48 +12223,90 @@ } }, "google-auth-library": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-4.2.6.tgz", - "integrity": "sha512-oJ6tCA9rbsYeIVY+mcLPFHa2hatz3XO6idYIrlI/KhhlMxZrO3tKyU8O2Pxu5KnSBBP7Wj4HtbM1LLKngNFaFw==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", + "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", "requires": { "arrify": "^2.0.0", "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", "fast-text-encoding": "^1.0.0", - "gaxios": "^2.0.0", - "gcp-metadata": "^2.0.0", - "gtoken": "^3.0.0", - "jws": "^3.1.5", - "lru-cache": "^5.0.0" + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + }, + "dependencies": { + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "requires": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } } }, "google-p12-pem": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.4.tgz", - "integrity": "sha512-S4blHBQWZRnEW44OcR7TL9WR+QCqByRvhNDZ/uuQfpxywfupikf/miba8js1jZi6ZOGv5slgSuoshCWh6EMDzg==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", + "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", "requires": { - "node-forge": "^0.9.0" + "node-forge": "^1.3.1" } }, "googleapis": { - "version": "40.0.1", - "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-40.0.1.tgz", - "integrity": "sha512-B6qZVCautOOspEhru9GZ814I+ztkGWyA4ZEUfaXwXHBruX/HAWqedbsuUEx1w3nCECywK/FLTNUdcbH9zpaMaw==", + "version": "76.0.0", + "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-76.0.0.tgz", + "integrity": "sha512-l/TFSW7IRFcb7wF641BlmuP8Ox1ncuzJk5Fcs2947otlGBm5ktDxFhPkmrcNDaG+LWPQsuDwP1ojL0xV39cpmw==", "requires": { - "google-auth-library": "^4.0.0", - "googleapis-common": "^2.0.2" + "google-auth-library": "^7.0.2", + "googleapis-common": "^5.0.2" } }, "googleapis-common": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-2.0.4.tgz", - "integrity": "sha512-8RRkxr24v1jIKCC1onFWA8RGnwFV55m3Qpil9DLX1yLc9e5qvOJsRoDOhhD2e7jFRONYEhT/BzT8vJZANqSr9w==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-5.1.0.tgz", + "integrity": "sha512-RXrif+Gzhq1QAzfjxulbGvAY3FPj8zq/CYcvgjzDbaBNCD6bUl+86I7mUs4DKWHGruuK26ijjR/eDpWIDgNROA==", "requires": { "extend": "^3.0.2", - "gaxios": "^2.0.1", - "google-auth-library": "^4.2.5", + "gaxios": "^4.0.0", + "google-auth-library": "^7.14.0", "qs": "^6.7.0", "url-template": "^2.0.8", - "uuid": "^3.3.2" + "uuid": "^8.0.0" + }, + "dependencies": { + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + } } }, "got": { @@ -2926,14 +12353,34 @@ "dev": true }, "gtoken": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-3.0.2.tgz", - "integrity": "sha512-BOBi6Zz31JfxhSHRZBIDdbwIbOPyux10WxJHdx8wz/FMP1zyN1xFrsAWsgcLe5ww5v/OZu/MePUEZAjgJXSauA==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", "requires": { - "gaxios": "^2.0.0", - "google-p12-pem": "^2.0.0", - "jws": "^3.1.5", - "mime": "^2.2.0" + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "jws": "^4.0.0" + }, + "dependencies": { + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "requires": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + } } }, "har-schema": { @@ -3702,9 +13149,9 @@ } }, "jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==" }, "js-base64": { "version": "2.6.4", @@ -4683,14 +14130,17 @@ } }, "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } }, "node-forge": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.2.tgz", - "integrity": "sha512-naKSScof4Wn+aoHU6HBsifh92Zeicm1GDQKd1vp3Y/kOi8ub0DozCa9KpvYNCXslFHYRmLNiqRopGdTGwNLpNw==" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" }, "nodemon": { "version": "1.19.4", @@ -6103,7 +15553,8 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true }, "source-map-resolve": { "version": "0.5.3", @@ -6289,6 +15740,21 @@ "resolved": "https://registry.npmjs.org/stream-wormhole/-/stream-wormhole-1.1.0.tgz", "integrity": "sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==" }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, "string-width": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", @@ -6317,21 +15783,6 @@ "define-properties": "^1.1.3" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -6652,6 +16103,11 @@ } } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "tslib": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", @@ -7065,6 +16521,20 @@ "defaults": "^1.0.3" } }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/plugins/azure/monitor/diagnosticsCapturedCategories.js b/plugins/azure/monitor/diagnosticsCapturedCategories.js new file mode 100644 index 0000000000..a30fc7e733 --- /dev/null +++ b/plugins/azure/monitor/diagnosticsCapturedCategories.js @@ -0,0 +1,65 @@ +const async = require('async'); +const helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Diagnostics Captured Categories', + category: 'Monitor', + domain: 'Management and Governance', + description: 'Ensures that Diagnostics Settings is configured to log activities for all appropriate categories.', + more_info: 'Monitor diagnostic setting in Azure controls how the diagnostic logs are exported. When a diagnostic setting is created, ' + + 'by default no log categories are selected. Capturing the appropriate log categories (Administrative, Security, Alert, and Policy) ' + + 'for the activities performed within your Azure subscriptions provides proper alerting.', + recommended_action: 'Ensure the categories Administrative, Alert, Policy, and Security are set to Enabled for all diagnostic settings.', + link: 'https://docs.microsoft.com/en-us/azure/azure-monitor/samples/resource-manager-diagnostic-settings', + apis: ['diagnosticSettingsOperations:list'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + const appropriateCategories = ['Administrative', 'Alert', 'Policy', 'Security']; + + async.each(locations.diagnosticSettingsOperations, (location, rcb) => { + const diagnosticSettings = helpers.addSource(cache, source, + ['diagnosticSettingsOperations', 'list', location]); + + if (!diagnosticSettings) return rcb(); + + if (diagnosticSettings.err || !diagnosticSettings.data) { + helpers.addResult(results, 3, 'Unable to query for Diagnostic Settings : ' + helpers.addError(diagnosticSettings), location); + return rcb(); + } + + if (!diagnosticSettings.data.length) { + helpers.addResult(results, 0, 'No existing Diagnostic Settings found', location); + return rcb(); + } + + diagnosticSettings.data.forEach(settings => { + let enabledCategories = []; + + if (settings.logs && settings.logs.length) { + settings.logs.forEach(log => { + if (log.enabled && appropriateCategories.indexOf(log.category) > -1) { + if (enabledCategories.indexOf(log.category) === -1) { + enabledCategories.push(log.category); + } + } + }); + + if (appropriateCategories.length == enabledCategories.length) { + helpers.addResult(results, 0, 'Diagnostic Setting is configured to log required categories', location, settings.id); + } else { + helpers.addResult(results, 2, 'Diagnostic Setting is not configured to log required categories', location, settings.id); + } + } else { + helpers.addResult(results, 2, 'Diagnostic Setting does not have any logs configured', location, settings.id); + } + }); + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/monitor/diagnosticsCapturedCategories.spec.js b/plugins/azure/monitor/diagnosticsCapturedCategories.spec.js new file mode 100644 index 0000000000..8fc0b2da8c --- /dev/null +++ b/plugins/azure/monitor/diagnosticsCapturedCategories.spec.js @@ -0,0 +1,149 @@ +var expect = require('chai').expect; +var diagnosticsCapturedCategories = require('./diagnosticsCapturedCategories'); + +const diagnosticSettings = [ + { + 'id': 'subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting', + 'type': 'Microsoft.Insights/diagnosticSettings', + 'name': 'test-setting', + 'location': 'global', + 'storageAccountId': '/subscriptions/123/resourceGroups/devresourcegroup/providers/Microsoft.Storage/storageAccounts/test-storage-account', + 'logs': [ + { + 'category': 'Administrative', + 'enabled': true + }, + { + 'category': 'Security', + 'enabled': true + }, + { + 'category': 'ServiceHealth', + 'enabled': true + }, + { + 'category': 'Alert', + 'enabled': true + }, + { + 'category': 'Recommendation', + 'enabled': true + }, + { + 'category': 'Policy', + 'enabled': true + }, + { + 'category': 'Autoscale', + 'enabled': true + }, + { + 'category': 'ResourceHealth', + 'enabled': true + } + ] + }, + { + 'id': 'subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting', + 'type': 'Microsoft.Insights/diagnosticSettings', + 'name': 'test-setting', + 'location': 'global', + 'storageAccountId': '/subscriptions/123/resourceGroups/devresourcegroup/providers/Microsoft.Storage/storageAccounts/test-storage-account', + 'logs': [ + { + 'category': 'Administrative', + 'enabled': true + }, + { + 'category': 'Security', + 'enabled': true + }, + { + 'category': 'ServiceHealth', + 'enabled': true + }, + { + 'category': 'Alert', + 'enabled': false + }, + { + 'category': 'Recommendation', + 'enabled': true + }, + { + 'category': 'Policy', + 'enabled': true + }, + { + 'category': 'Autoscale', + 'enabled': true + }, + { + 'category': 'ResourceHealth', + 'enabled': false + } + ] + } +]; + +const createCache = (diagnosticSettings) => { + let settings = {}; + if (diagnosticSettings) { + settings['data'] = diagnosticSettings; + } + return { + diagnosticSettingsOperations: { + list: { + 'global': settings + } + } + }; +}; + +describe('diagnosticsCapturedCategories', function() { + describe('run', function() { + it('should give passing result if no diagnostic settings found', function(done) { + const cache = createCache([]); + diagnosticsCapturedCategories.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 Diagnostic Settings found'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give unknown result if unable to query for diagnostic settings', function(done) { + const cache = createCache(); + diagnosticsCapturedCategories.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 Diagnostic Settings'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give passing result if logs are enabled for all appropriate categories', function(done) { + const cache = createCache([diagnosticSettings[0]]); + diagnosticsCapturedCategories.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Diagnostic Setting is configured to log required categories'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give failing result if logs are not enabled for all appropriate categories', function(done) { + const cache = createCache([diagnosticSettings[1]]); + diagnosticsCapturedCategories.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('Diagnostic Setting is not configured to log required categories'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + }); +}); diff --git a/plugins/azure/monitor/diagnosticsSettingsEnabled.js b/plugins/azure/monitor/diagnosticsSettingsEnabled.js new file mode 100644 index 0000000000..6c28f6a8f4 --- /dev/null +++ b/plugins/azure/monitor/diagnosticsSettingsEnabled.js @@ -0,0 +1,41 @@ +const async = require('async'); +const helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'Diagnostics Settings Enabled', + category: 'Monitor', + domain: 'Management and Governance', + description: 'Ensures that Diagnostics Settings exist and are exporting activity logs.', + more_info: 'Diagnostic setting should be configured for all appropriate resources for your environment in order to log the interactions within your cloud resources and gain insight into the operations that were performed within that resource itself.', + recommended_action: 'Ensure that a Diagnostic status is enabled for all supported resources in Diagnostics Settings under Monitor.', + link: 'https://docs.microsoft.com/en-us/azure/monitoring-and-diagnostics/monitoring-overview-activity-logs#export-the-activity-log-with-a-log-profile', + apis: ['diagnosticSettingsOperations:list'], + + run: function(cache, settings, callback) { + const results = []; + const source = {}; + const locations = helpers.locations(settings.govcloud); + + async.each(locations.diagnosticSettingsOperations, (location, rcb) => { + const diagnosticSettings = helpers.addSource(cache, source, + ['diagnosticSettingsOperations', 'list', location]); + + if (!diagnosticSettings) return rcb(); + + if (diagnosticSettings.err || !diagnosticSettings.data) { + helpers.addResult(results, 3, 'Unable to query for Diagnostic Settings : ' + helpers.addError(diagnosticSettings), location); + return rcb(); + } + + if (!diagnosticSettings.data.length) { + helpers.addResult(results, 2, 'No existing Diagnostic Settings found', location); + } else { + helpers.addResult(results, 0, 'Diagnostic Settings exist', location); + } + + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; diff --git a/plugins/azure/monitor/diagnosticsSettingsEnabled.spec.js b/plugins/azure/monitor/diagnosticsSettingsEnabled.spec.js new file mode 100644 index 0000000000..c1e4581e2a --- /dev/null +++ b/plugins/azure/monitor/diagnosticsSettingsEnabled.spec.js @@ -0,0 +1,180 @@ +var expect = require('chai').expect; +var diagnosticsSettingsEnabled = require('./diagnosticsSettingsEnabled'); + +const diagnosticSettings = [ + { + 'id': 'subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting', + 'type': 'Microsoft.Insights/diagnosticSettings', + 'name': 'test-setting', + 'location': 'global', + 'storageAccountId': '/subscriptions/123/resourceGroups/devresourcegroup/providers/Microsoft.Storage/storageAccounts/test-storage-account', + 'logs': [ + { + 'category': 'Administrative', + 'enabled': true + }, + { + 'category': 'Security', + 'enabled': true + }, + { + 'category': 'ServiceHealth', + 'enabled': true + }, + { + 'category': 'Alert', + 'enabled': true + }, + { + 'category': 'Recommendation', + 'enabled': true + }, + { + 'category': 'Policy', + 'enabled': true + }, + { + 'category': 'Autoscale', + 'enabled': true + }, + { + 'category': 'ResourceHealth', + 'enabled': true + } + ] + }, + { + 'id': 'subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting', + 'type': 'Microsoft.Insights/diagnosticSettings', + 'name': 'test-setting', + 'location': 'global', + 'storageAccountId': '/subscriptions/123/resourceGroups/devresourcegroup/providers/Microsoft.Storage/storageAccounts/test-storage-account', + 'logs': [ + { + 'category': 'Administrative', + 'enabled': true + }, + { + 'category': 'Security', + 'enabled': true + }, + { + 'category': 'ServiceHealth', + 'enabled': true + }, + { + 'category': 'Alert', + 'enabled': true + }, + { + 'category': 'Recommendation', + 'enabled': true + }, + { + 'category': 'Policy', + 'enabled': true + }, + { + 'category': 'Autoscale', + 'enabled': true + }, + { + 'category': 'ResourceHealth', + 'enabled': false + } + ] + }, + { + 'id': 'subscriptions/123/providers/microsoft.insights/diagnosticSettings/test-setting', + 'type': 'Microsoft.Insights/diagnosticSettings', + 'name': 'test-setting', + 'location': 'global', + 'eventHubAuthorizationRuleId': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.EventHub/namespaces/test-setting/authorizationrules/RootManageSharedAccessKey', + 'eventHubName': '', + 'logs': [ + { + 'category': 'Administrative', + 'enabled': true + }, + { + 'category': 'Security', + 'enabled': true + }, + { + 'category': 'ServiceHealth', + 'enabled': true + }, + { + 'category': 'Alert', + 'enabled': true + }, + { + 'category': 'Recommendation', + 'enabled': true + }, + { + 'category': 'Policy', + 'enabled': true + }, + { + 'category': 'Autoscale', + 'enabled': true + }, + { + 'category': 'ResourceHealth', + 'enabled': true + } + ] + } +]; + +const createCache = (diagnosticSettings) => { + let settings = {}; + if (diagnosticSettings) { + settings['data'] = diagnosticSettings; + } + return { + diagnosticSettingsOperations: { + list: { + 'global': settings + } + } + }; +}; + +describe('diagnosticsSettingsEnabled', function() { + describe('run', function() { + it('should give failing result if no diagnostic settings found', function(done) { + const cache = createCache([]); + diagnosticsSettingsEnabled.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 Diagnostic Settings found'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give passing result if diagnostic settings found', function(done) { + const cache = createCache(diagnosticSettings); + diagnosticsSettingsEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('Diagnostic Settings exist'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + + it('should give unknown result if unable to query for diagnostic settings', function(done) { + const cache = createCache(); + diagnosticsSettingsEnabled.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 Diagnostic Settings'); + expect(results[0].region).to.equal('global'); + done(); + }); + }); + }); +}); diff --git a/plugins/azure/sqlserver/auditRetentionPolicy.js b/plugins/azure/sqlserver/auditRetentionPolicy.js index e454f76555..6e026a2f79 100644 --- a/plugins/azure/sqlserver/auditRetentionPolicy.js +++ b/plugins/azure/sqlserver/auditRetentionPolicy.js @@ -48,7 +48,7 @@ module.exports = { } else { serverBlobAuditingPolicies.data.forEach(serverBlobAuditingPolicy => { if (serverBlobAuditingPolicy.retentionDays && - serverBlobAuditingPolicy.retentionDays > 90) { + serverBlobAuditingPolicy.retentionDays >= 90) { helpers.addResult(results, 0, 'Server Auditing retention is greater than 90 days', location, server.id); } else if (serverBlobAuditingPolicy.retentionDays && serverBlobAuditingPolicy.retentionDays < 90) { diff --git a/plugins/google/vpcnetwork/openAllPorts.js b/plugins/google/vpcnetwork/openAllPorts.js index 43584ba5fb..ab5838ec22 100644 --- a/plugins/google/vpcnetwork/openAllPorts.js +++ b/plugins/google/vpcnetwork/openAllPorts.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, services should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict ports to known IP addresses.', - apis: ['firewalls:list'], + apis: ['firewalls:list', 'projects:get'], compliance: { hipaa: 'HIPAA requires strict access controls to networks and services ' + 'processing sensitive data. Firewalls are the built-in ' + @@ -41,7 +41,7 @@ module.exports = { return rcb(); } - helpers.findOpenAllPorts(firewalls.data, region, results, cache, callback, source); + helpers.findOpenAllPorts(firewalls.data, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openCIFS.js b/plugins/google/vpcnetwork/openCIFS.js index be19046fd8..7bbd05239e 100644 --- a/plugins/google/vpcnetwork/openCIFS.js +++ b/plugins/google/vpcnetwork/openCIFS.js @@ -38,7 +38,7 @@ module.exports = { let service = 'CIFS'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openCassandra.js b/plugins/google/vpcnetwork/openCassandra.js index 77bb8547ad..39cb4da9d6 100644 --- a/plugins/google/vpcnetwork/openCassandra.js +++ b/plugins/google/vpcnetwork/openCassandra.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Cassandra'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openCustomPorts.js b/plugins/google/vpcnetwork/openCustomPorts.js index c4345116ce..26e9d00c82 100644 --- a/plugins/google/vpcnetwork/openCustomPorts.js +++ b/plugins/google/vpcnetwork/openCustomPorts.js @@ -57,7 +57,7 @@ module.exports = { return rcb(); } - helpers.findOpenPorts(firewalls.data, ports, 'custom', region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, 'custom', region, results, cache, source); rcb(); }, function() { diff --git a/plugins/google/vpcnetwork/openDNS.js b/plugins/google/vpcnetwork/openDNS.js index a1d18d3c57..5d8810bc3f 100644 --- a/plugins/google/vpcnetwork/openDNS.js +++ b/plugins/google/vpcnetwork/openDNS.js @@ -39,7 +39,7 @@ module.exports = { let service = 'DNS'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openDocker.js b/plugins/google/vpcnetwork/openDocker.js index bd77f059c6..a00d240675 100644 --- a/plugins/google/vpcnetwork/openDocker.js +++ b/plugins/google/vpcnetwork/openDocker.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Docker'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function() { diff --git a/plugins/google/vpcnetwork/openFTP.js b/plugins/google/vpcnetwork/openFTP.js index 0608b29b8d..27f95539f5 100644 --- a/plugins/google/vpcnetwork/openFTP.js +++ b/plugins/google/vpcnetwork/openFTP.js @@ -38,7 +38,7 @@ module.exports = { let service = 'FTP'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openHadoopNameNode.js b/plugins/google/vpcnetwork/openHadoopNameNode.js index 80148924da..7f42fd2f0a 100644 --- a/plugins/google/vpcnetwork/openHadoopNameNode.js +++ b/plugins/google/vpcnetwork/openHadoopNameNode.js @@ -38,7 +38,7 @@ module.exports = { let service = 'NameNodeWebUI'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openHadoopNameNodeWebUI.js b/plugins/google/vpcnetwork/openHadoopNameNodeWebUI.js index 243306b3a4..084aeea4c6 100644 --- a/plugins/google/vpcnetwork/openHadoopNameNodeWebUI.js +++ b/plugins/google/vpcnetwork/openHadoopNameNodeWebUI.js @@ -38,7 +38,7 @@ module.exports = { let service = 'NameNodeWebUI'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openKibana.js b/plugins/google/vpcnetwork/openKibana.js index 307605da47..1e7238ab30 100644 --- a/plugins/google/vpcnetwork/openKibana.js +++ b/plugins/google/vpcnetwork/openKibana.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Kibana'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openMongo.js b/plugins/google/vpcnetwork/openMongo.js index 499743583c..b8a38f2334 100644 --- a/plugins/google/vpcnetwork/openMongo.js +++ b/plugins/google/vpcnetwork/openMongo.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Mongo'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openMsSQL.js b/plugins/google/vpcnetwork/openMsSQL.js index 0fd4ca9813..9f3e39a3e6 100644 --- a/plugins/google/vpcnetwork/openMsSQL.js +++ b/plugins/google/vpcnetwork/openMsSQL.js @@ -38,7 +38,7 @@ module.exports = { let service = 'MSSQL'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openMySQL.js b/plugins/google/vpcnetwork/openMySQL.js index dd5cbef845..fa17f1f03a 100644 --- a/plugins/google/vpcnetwork/openMySQL.js +++ b/plugins/google/vpcnetwork/openMySQL.js @@ -38,7 +38,7 @@ module.exports = { let service = 'MySQL'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openNetBIOS.js b/plugins/google/vpcnetwork/openNetBIOS.js index 5c0d39ef75..49fbf85f94 100644 --- a/plugins/google/vpcnetwork/openNetBIOS.js +++ b/plugins/google/vpcnetwork/openNetBIOS.js @@ -38,7 +38,7 @@ module.exports = { let service = 'NetBIOS'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openOracle.js b/plugins/google/vpcnetwork/openOracle.js index a154d98ecd..0b27de363d 100644 --- a/plugins/google/vpcnetwork/openOracle.js +++ b/plugins/google/vpcnetwork/openOracle.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Oracle'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openOracleAutoDataWarehouse.js b/plugins/google/vpcnetwork/openOracleAutoDataWarehouse.js index d16c6738bb..936c737eec 100644 --- a/plugins/google/vpcnetwork/openOracleAutoDataWarehouse.js +++ b/plugins/google/vpcnetwork/openOracleAutoDataWarehouse.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Oracle Auto Data Warehouse'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openPostgreSQL.js b/plugins/google/vpcnetwork/openPostgreSQL.js index 03c5666229..fb5d79edc7 100644 --- a/plugins/google/vpcnetwork/openPostgreSQL.js +++ b/plugins/google/vpcnetwork/openPostgreSQL.js @@ -38,7 +38,7 @@ module.exports = { let service = 'PostgreSQL'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openRDP.js b/plugins/google/vpcnetwork/openRDP.js index 34f352ac24..241b25104b 100644 --- a/plugins/google/vpcnetwork/openRDP.js +++ b/plugins/google/vpcnetwork/openRDP.js @@ -38,7 +38,7 @@ module.exports = { let service = 'RDP'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openRPC.js b/plugins/google/vpcnetwork/openRPC.js index 830cdbe8e9..1ec8f12146 100644 --- a/plugins/google/vpcnetwork/openRPC.js +++ b/plugins/google/vpcnetwork/openRPC.js @@ -38,7 +38,7 @@ module.exports = { let service = 'RPC'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openRedis.js b/plugins/google/vpcnetwork/openRedis.js index 27c868a80b..b639e51285 100644 --- a/plugins/google/vpcnetwork/openRedis.js +++ b/plugins/google/vpcnetwork/openRedis.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Redis'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openSMBoTCP.js b/plugins/google/vpcnetwork/openSMBoTCP.js index 176cbe3196..61a44d346e 100644 --- a/plugins/google/vpcnetwork/openSMBoTCP.js +++ b/plugins/google/vpcnetwork/openSMBoTCP.js @@ -38,7 +38,7 @@ module.exports = { let service = 'SMBoTCP'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openSMTP.js b/plugins/google/vpcnetwork/openSMTP.js index 1c553286ff..7f7fabdccd 100644 --- a/plugins/google/vpcnetwork/openSMTP.js +++ b/plugins/google/vpcnetwork/openSMTP.js @@ -38,7 +38,7 @@ module.exports = { let service = 'SMTP'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openSQLServer.js b/plugins/google/vpcnetwork/openSQLServer.js index 9cf651ce8e..920368f09c 100644 --- a/plugins/google/vpcnetwork/openSQLServer.js +++ b/plugins/google/vpcnetwork/openSQLServer.js @@ -39,7 +39,7 @@ module.exports = { let service = 'SQL Server'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openSSH.js b/plugins/google/vpcnetwork/openSSH.js index 774a5eb12f..1696e7e400 100644 --- a/plugins/google/vpcnetwork/openSSH.js +++ b/plugins/google/vpcnetwork/openSSH.js @@ -38,7 +38,7 @@ module.exports = { let service = 'SSH'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openSalt.js b/plugins/google/vpcnetwork/openSalt.js index 7d6a551bc9..e61b7e1ddf 100644 --- a/plugins/google/vpcnetwork/openSalt.js +++ b/plugins/google/vpcnetwork/openSalt.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Salt'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openTelnet.js b/plugins/google/vpcnetwork/openTelnet.js index 5969711f1a..821a8e2344 100644 --- a/plugins/google/vpcnetwork/openTelnet.js +++ b/plugins/google/vpcnetwork/openTelnet.js @@ -38,7 +38,7 @@ module.exports = { let service = 'Telnet'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openVNCClient.js b/plugins/google/vpcnetwork/openVNCClient.js index d1411070ab..2ceafd0bbe 100644 --- a/plugins/google/vpcnetwork/openVNCClient.js +++ b/plugins/google/vpcnetwork/openVNCClient.js @@ -38,7 +38,7 @@ module.exports = { let service = 'VNC Client'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ diff --git a/plugins/google/vpcnetwork/openVNCServer.js b/plugins/google/vpcnetwork/openVNCServer.js index d3cf5d13ff..6fc35edc4a 100644 --- a/plugins/google/vpcnetwork/openVNCServer.js +++ b/plugins/google/vpcnetwork/openVNCServer.js @@ -38,7 +38,7 @@ module.exports = { let service = 'VNC Server'; - helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, callback, source); + helpers.findOpenPorts(firewalls.data, ports, service, region, results, cache, source); rcb(); }, function(){ From e38c6ed66db9dcccc6b1c5f99d33a645cb8c8e98 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:39:16 +0500 Subject: [PATCH 262/350] Added Some changes --- .../imgBuilderComponentsEncrypted.js | 16 ++++++++-------- .../imgBuilderComponentsEncrypted.spec.js | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js index 8cc1c437f2..e854316df2 100644 --- a/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js +++ b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js @@ -39,13 +39,13 @@ module.exports = { if (!listComponents) return rcb(); - if (listComponents.err) { - helpers.addResult(results, 3, - 'Unable to query component version list: ' + helpers.addError(listComponents), region); - return rcb(); - } + // if (listComponents.err) { + // helpers.addResult(results, 3, + // 'Unable to query component version list: ' + helpers.addError(listComponents), region); + // return rcb(); + // } - if (!listComponents.data || !listComponents.data.length) { + if (listComponents.err || !listComponents.data || !listComponents.data.length) { helpers.addResult(results, 0, 'No component version list found', region); return rcb(); } @@ -115,12 +115,12 @@ module.exports = { if (currentEncryptionLevel >= desiredEncryptionLevel) { helpers.addResult(results, 0, - `Image builder component is encrypted with ${currentEncryptionLevelString} \ + `Image Builder component is encrypted with ${currentEncryptionLevelString} \ which is greater than or equal to the desired encryption level ${config.desiredEncryptionLevelString}`, region, resource); } else { helpers.addResult(results, 2, - `Image builder component is encrypted with ${currentEncryptionLevelString} \ + `Image Builder component is encrypted with ${currentEncryptionLevelString} \ which is less than the desired encryption level ${config.desiredEncryptionLevelString}`, region, resource); } diff --git a/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.spec.js b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.spec.js index 41ec9f6b63..d2219c817d 100644 --- a/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.spec.js +++ b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.spec.js @@ -167,23 +167,23 @@ const createCache = (recipe, keys, kmsAliases, getComponent, describeKey, recipe describe('imgBuilderComponentsEncrypted', function () { describe('run', function () { - it('should PASS if Image builder component is encrypted with awscmk', function (done) { + it('should PASS if Image Builder component is encrypted with awscmk', function (done) { const cache = createCache([listComponents[0]], listKeys, listAliases, getComponent[0], describeKey[0]); imgBuilderComponentsEncrypted.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('Image builder component is encrypted with awscmk'); + expect(results[0].message).to.include('Image Builder component is encrypted with awscmk'); expect(results[0].region).to.equal('us-east-1'); done(); }); }); - it('should FAIL if Image builder component is encrypted with awskms', function (done) { + 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) => { 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'); + expect(results[0].message).to.include('Image Builder component is encrypted with'); expect(results[0].region).to.equal('us-east-1'); done(); }); From a450607e0c7476373a195ab4be76c80020a364e7 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:40:51 +0500 Subject: [PATCH 263/350] Update plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js --- plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js index e854316df2..12fd0b6713 100644 --- a/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js +++ b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js @@ -14,7 +14,7 @@ module.exports = { 'KMS:describeKey'], settings: { image_component_desired_encryption_level: { - name: 'Imagebuilder Component Target Encryption Level', + 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' From 089b5d88b782b9de60d44c91f51a6a3f81c9932c Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:42:36 +0500 Subject: [PATCH 264/350] Added Some changes --- .../imagebuilder/imgBuilderComponentsEncrypted.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js index e854316df2..71317f89f7 100644 --- a/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js +++ b/plugins/aws/imagebuilder/imgBuilderComponentsEncrypted.js @@ -39,13 +39,13 @@ module.exports = { if (!listComponents) return rcb(); - // if (listComponents.err) { - // helpers.addResult(results, 3, - // 'Unable to query component version list: ' + helpers.addError(listComponents), region); - // return rcb(); - // } + if (listComponents.err) { + helpers.addResult(results, 3, + 'Unable to query component version list: ' + helpers.addError(listComponents), region); + return rcb(); + } - if (listComponents.err || !listComponents.data || !listComponents.data.length) { + if (!listComponents.data || !listComponents.data.length) { helpers.addResult(results, 0, 'No component version list found', region); return rcb(); } From c8c7b93417a38c3dfc93c1ec468b5df6731a3768 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:46:39 +0500 Subject: [PATCH 265/350] Update plugins/aws/msk/mskClusterPublicAccess.js --- plugins/aws/msk/mskClusterPublicAccess.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/msk/mskClusterPublicAccess.js b/plugins/aws/msk/mskClusterPublicAccess.js index 426a741c3c..3edc60e245 100644 --- a/plugins/aws/msk/mskClusterPublicAccess.js +++ b/plugins/aws/msk/mskClusterPublicAccess.js @@ -45,7 +45,7 @@ module.exports = { cluster.BrokerNodeGroupInfo.ConnectivityInfo.PublicAccess.Type && cluster.BrokerNodeGroupInfo.ConnectivityInfo.PublicAccess.Type.toUpperCase() === 'DISABLED') { helpers.addResult(results, 0, - 'msk cluster does not have public access enabled', region, resource); + 'MSK cluster does not have public access enabled', region, resource); } else { helpers.addResult(results, 2, 'msk cluster has public access enabled', region, resource); From c2ed98d680aceb99f30e904fad90b171ec78e94e Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:47:10 +0500 Subject: [PATCH 266/350] Update plugins/aws/msk/mskClusterPublicAccess.js --- plugins/aws/msk/mskClusterPublicAccess.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/msk/mskClusterPublicAccess.js b/plugins/aws/msk/mskClusterPublicAccess.js index 3edc60e245..afb815854b 100644 --- a/plugins/aws/msk/mskClusterPublicAccess.js +++ b/plugins/aws/msk/mskClusterPublicAccess.js @@ -48,7 +48,7 @@ module.exports = { 'MSK cluster does not have public access enabled', region, resource); } else { helpers.addResult(results, 2, - 'msk cluster has public access enabled', region, resource); + 'MSK cluster has public access enabled', region, resource); } } From b6b3299690f8c45961bc51c5fed16177c3c46c98 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:47:35 +0500 Subject: [PATCH 267/350] Update plugins/aws/msk/mskClusterPublicAccess.spec.js --- plugins/aws/msk/mskClusterPublicAccess.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/msk/mskClusterPublicAccess.spec.js b/plugins/aws/msk/mskClusterPublicAccess.spec.js index 83a9d7eac4..083b9a6f31 100644 --- a/plugins/aws/msk/mskClusterPublicAccess.spec.js +++ b/plugins/aws/msk/mskClusterPublicAccess.spec.js @@ -94,7 +94,7 @@ const createErrorCache = () => { describe('mskClusterPublicAccess', function () { describe('run', function () { - it('should FAIL if msk cluster has public access enabled', function (done) { + it('should FAIL if MSK cluster has public access enabled', function (done) { const cache = createCache([listClusters[0]]); mskClusterPublicAccess.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); From 5a71fa25b5376e67916a8ecb7162b33df478b7a1 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:48:03 +0500 Subject: [PATCH 268/350] Update plugins/aws/msk/mskClusterPublicAccess.spec.js --- plugins/aws/msk/mskClusterPublicAccess.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/msk/mskClusterPublicAccess.spec.js b/plugins/aws/msk/mskClusterPublicAccess.spec.js index 083b9a6f31..e95b67baf4 100644 --- a/plugins/aws/msk/mskClusterPublicAccess.spec.js +++ b/plugins/aws/msk/mskClusterPublicAccess.spec.js @@ -99,7 +99,7 @@ describe('mskClusterPublicAccess', function () { mskClusterPublicAccess.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('msk cluster has public access enabled'); + expect(results[0].message).to.include('MSK cluster has public access enabled'); done(); }); }); From f54d63b94b1ad524e36f0e010ebbd7a2443cf26b Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:48:30 +0500 Subject: [PATCH 269/350] Update plugins/aws/msk/mskClusterPublicAccess.spec.js --- plugins/aws/msk/mskClusterPublicAccess.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/msk/mskClusterPublicAccess.spec.js b/plugins/aws/msk/mskClusterPublicAccess.spec.js index e95b67baf4..ca1dd2bd35 100644 --- a/plugins/aws/msk/mskClusterPublicAccess.spec.js +++ b/plugins/aws/msk/mskClusterPublicAccess.spec.js @@ -109,7 +109,7 @@ describe('mskClusterPublicAccess', function () { mskClusterPublicAccess.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('msk cluster does not have public access enabled'); + expect(results[0].message).to.include('MSK cluster does not have public access enabled'); done(); }); }); From c3c3576ab034006b76d36762b2e7f0cc7c767d8a Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:48:48 +0500 Subject: [PATCH 270/350] Update plugins/aws/msk/mskClusterPublicAccess.spec.js --- plugins/aws/msk/mskClusterPublicAccess.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/msk/mskClusterPublicAccess.spec.js b/plugins/aws/msk/mskClusterPublicAccess.spec.js index ca1dd2bd35..5c849111a8 100644 --- a/plugins/aws/msk/mskClusterPublicAccess.spec.js +++ b/plugins/aws/msk/mskClusterPublicAccess.spec.js @@ -104,7 +104,7 @@ describe('mskClusterPublicAccess', function () { }); }); - it('should PASS if msk cluster does not have public access enabled', function (done) { + it('should PASS if MSK cluster does not have public access enabled', function (done) { const cache = createCache([listClusters[1]]); mskClusterPublicAccess.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); From 652bd0359c07da6ce59ad0e3cf6af876a825108d Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 21 Jun 2022 16:21:42 +0500 Subject: [PATCH 271/350] Apply suggestions from code review --- plugins/aws/acm/acmValidation.spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/aws/acm/acmValidation.spec.js b/plugins/aws/acm/acmValidation.spec.js index 237d343984..07a843a757 100644 --- a/plugins/aws/acm/acmValidation.spec.js +++ b/plugins/aws/acm/acmValidation.spec.js @@ -87,7 +87,6 @@ const describeCertificate = [ } }, { - "Certificate": { "CertificateArn": "arn:aws:acm:us-east-1:000011122222:certificate/8951d876-8417-4d5c-8caa-5f73a3b1211e", "DomainName": "*.viteace.com", From daeb3e4ddaaaf37e4b31c890e9f553b564cfce6a Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 21 Jun 2022 16:42:48 +0500 Subject: [PATCH 272/350] Apply suggestions from code review --- plugins/oracle/objectstore/bucketVersioning.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/oracle/objectstore/bucketVersioning.js b/plugins/oracle/objectstore/bucketVersioning.js index e9cc09ee9e..a93871c6e5 100644 --- a/plugins/oracle/objectstore/bucketVersioning.js +++ b/plugins/oracle/objectstore/bucketVersioning.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'To minimize data loss in case of inadvertent or malicious deletes, make sure that all your object store buckets are configured with object versioning.', recommended_action: 'Enable bucket versioning for all object store buckets.', link: 'https://docs.oracle.com/en-us/iaas/Content/Object/Tasks/usingversioning.htm', - apis: ['namespace:get','bucket:list', 'bucket:get'], + apis: ['namespace:get', 'bucket:list', 'bucket:get'], run: function(cache, settings, callback) { var results = []; @@ -35,10 +35,10 @@ module.exports = { if (bucket.versioning && bucket.versioning === 'Enabled') { helpers.addResult(results, 0, - `Object store bucket (${bucket.name}) has versioning enabled.`, region, bucket.id); + `Object store bucket (${bucket.name}) has versioning enabled`, region, bucket.id); } else { helpers.addResult(results, 2, - `Object store bucket (${bucket.name}) does not have versioning enabled.`, region, bucket.id); + `Object store bucket (${bucket.name}) does not have versioning enabled`, region, bucket.id); } }); } From 335bd3550ac7c51bd2db6774e7a6bf035b02af47 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 21 Jun 2022 16:56:58 +0500 Subject: [PATCH 273/350] Apply suggestions from code review --- plugins/oracle/oke/okeSecretsEncrypted.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oracle/oke/okeSecretsEncrypted.js b/plugins/oracle/oke/okeSecretsEncrypted.js index 19f504b144..223030657c 100644 --- a/plugins/oracle/oke/okeSecretsEncrypted.js +++ b/plugins/oracle/oke/okeSecretsEncrypted.js @@ -14,7 +14,7 @@ module.exports = { oke_encryption_level: { name: 'OKE Encryption Level', description: 'Desired protection level for OKE Secrets. default: oracle-managed, cloudcmek: customer managed encryption keys, ' + - 'cloudhsm: customer managed HSM encryption key, external: imported or externally managed key', + 'cloudhsm: customer managed HSM encryption key', regex: '^(default|cloudcmek|cloudhsm)$', default: 'cloudcmek' } From 9ad7a65472db682e52865418e1450af432990008 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 21 Jun 2022 16:57:20 +0500 Subject: [PATCH 274/350] Update plugins/oracle/blockstorage/blockVolumeCMKEncryption.js --- plugins/oracle/blockstorage/blockVolumeCMKEncryption.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oracle/blockstorage/blockVolumeCMKEncryption.js b/plugins/oracle/blockstorage/blockVolumeCMKEncryption.js index d0902a8b5a..e4813956c7 100644 --- a/plugins/oracle/blockstorage/blockVolumeCMKEncryption.js +++ b/plugins/oracle/blockstorage/blockVolumeCMKEncryption.js @@ -14,7 +14,7 @@ module.exports = { volume_encryption_level: { name: 'Block Volume Encryption Level', description: 'Desired protection level for block volumes. default: oracle-managed, cloudcmek: customer managed encryption keys, ' + - 'cloudhsm: customer managed HSM encryption key, external: imported or externally managed key', + 'cloudhsm: customer managed HSM encryption key', regex: '^(default|cloudcmek|cloudhsm)$', default: 'cloudcmek' } From f0afb24eeece5e0aefbc2772adb6a18b7ea83219 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 21 Jun 2022 17:02:15 +0500 Subject: [PATCH 275/350] Apply suggestions from code review --- plugins/oracle/filestorage/fileSystemsCMKEncryption.js | 2 +- plugins/oracle/oke/okeSecretsEncrypted.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/oracle/filestorage/fileSystemsCMKEncryption.js b/plugins/oracle/filestorage/fileSystemsCMKEncryption.js index 19606ad342..467e76fe37 100644 --- a/plugins/oracle/filestorage/fileSystemsCMKEncryption.js +++ b/plugins/oracle/filestorage/fileSystemsCMKEncryption.js @@ -14,7 +14,7 @@ module.exports = { file_system_encryption_level: { name: 'File System Encryption Level', description: 'Desired protection level for File Storage file systems. default: oracle-managed, cloudcmek: customer managed encryption keys, ' + - 'cloudhsm: customer managed HSM encryption key, external: imported or externally managed key', + 'cloudhsm: customer managed HSM encryption key', regex: '^(default|cloudcmek|cloudhsm)$', default: 'cloudcmek' } diff --git a/plugins/oracle/oke/okeSecretsEncrypted.js b/plugins/oracle/oke/okeSecretsEncrypted.js index 19f504b144..223030657c 100644 --- a/plugins/oracle/oke/okeSecretsEncrypted.js +++ b/plugins/oracle/oke/okeSecretsEncrypted.js @@ -14,7 +14,7 @@ module.exports = { oke_encryption_level: { name: 'OKE Encryption Level', description: 'Desired protection level for OKE Secrets. default: oracle-managed, cloudcmek: customer managed encryption keys, ' + - 'cloudhsm: customer managed HSM encryption key, external: imported or externally managed key', + 'cloudhsm: customer managed HSM encryption key', regex: '^(default|cloudcmek|cloudhsm)$', default: 'cloudcmek' } From 6b4f3cf1d2ec046166a673a8fe9cf6bc4ebd47c8 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 21 Jun 2022 17:03:49 +0500 Subject: [PATCH 276/350] Apply suggestions from code review --- plugins/oracle/compute/bootVolumeCMKEncryption.js | 2 +- plugins/oracle/oke/okeSecretsEncrypted.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/oracle/compute/bootVolumeCMKEncryption.js b/plugins/oracle/compute/bootVolumeCMKEncryption.js index 9c15b24e35..86702c06aa 100644 --- a/plugins/oracle/compute/bootVolumeCMKEncryption.js +++ b/plugins/oracle/compute/bootVolumeCMKEncryption.js @@ -14,7 +14,7 @@ module.exports = { volume_encryption_level: { name: 'Boot Volume Encryption Level', description: 'Desired protection level for boot volumes. default: oracle-managed, cloudcmek: customer managed encryption keys, ' + - 'cloudhsm: customer managed HSM encryption key, external: imported or externally managed key', + 'cloudhsm: customer managed HSM encryption key', regex: '^(default|cloudcmek|cloudhsm)$', default: 'cloudcmek' } diff --git a/plugins/oracle/oke/okeSecretsEncrypted.js b/plugins/oracle/oke/okeSecretsEncrypted.js index 19f504b144..223030657c 100644 --- a/plugins/oracle/oke/okeSecretsEncrypted.js +++ b/plugins/oracle/oke/okeSecretsEncrypted.js @@ -14,7 +14,7 @@ module.exports = { oke_encryption_level: { name: 'OKE Encryption Level', description: 'Desired protection level for OKE Secrets. default: oracle-managed, cloudcmek: customer managed encryption keys, ' + - 'cloudhsm: customer managed HSM encryption key, external: imported or externally managed key', + 'cloudhsm: customer managed HSM encryption key', regex: '^(default|cloudcmek|cloudhsm)$', default: 'cloudcmek' } From 8f5af08ecbc0af0ae561d15e7bf72124f3faeba1 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 21 Jun 2022 17:53:12 +0500 Subject: [PATCH 277/350] Added Some changes --- plugins/aws/backup/backupNotificationEnabled.js | 3 +-- plugins/aws/backup/backupNotificationEnabled.spec.js | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/aws/backup/backupNotificationEnabled.js b/plugins/aws/backup/backupNotificationEnabled.js index bf89c9e1e1..7cb5a85776 100644 --- a/plugins/aws/backup/backupNotificationEnabled.js +++ b/plugins/aws/backup/backupNotificationEnabled.js @@ -42,9 +42,8 @@ module.exports = { let getBackupVaultNotifications = helpers.addSource(cache, source, ['backup', 'getBackupVaultNotifications', region, vault.BackupVaultName]); - if (getBackupVaultNotifications && getBackupVaultNotifications.err && getBackupVaultNotifications.err.message && - getBackupVaultNotifications.err.message == `Failed reading notifications from database for Backup vault ${vault.BackupVaultName}`) { + getBackupVaultNotifications.err.message.toUpperCase().includes('FAILED READING NOTIFICATIONS FROM DATABASE')) { helpers.addResult(results, 2, 'Backup vault does not have any notifications configured', region, resource); continue; diff --git a/plugins/aws/backup/backupNotificationEnabled.spec.js b/plugins/aws/backup/backupNotificationEnabled.spec.js index 82e26dfa53..9766e3f45f 100644 --- a/plugins/aws/backup/backupNotificationEnabled.spec.js +++ b/plugins/aws/backup/backupNotificationEnabled.spec.js @@ -81,7 +81,7 @@ describe('backupNotificationEnabled', function () { }); it('should FAIL if Backup vault does not have any notifications configured', function (done) { - const cache = createCache([listBackupVaults[0]], null , null, { message: 'Failed reading notifications from database for Backup vault sadeed1'} ); + const cache = createCache([listBackupVaults[0]], null , null, { message: 'Failed reading notifications from database'} ); backupNotificationEnabled.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); From 35d44f792e0bfb30d3c68dd3ef74887b3fdade10 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 21 Jun 2022 18:49:08 +0500 Subject: [PATCH 278/350] Added Some changes --- .../aws/cloudtrail/cloudtrailBucketAccessLogging.js | 2 +- .../cloudtrail/cloudtrailBucketAccessLogging.spec.js | 12 ++++++++++-- plugins/aws/cloudtrail/cloudtrailBucketDelete.js | 2 +- .../aws/cloudtrail/cloudtrailBucketDelete.spec.js | 11 ++++++++++- plugins/aws/cloudtrail/cloudtrailBucketPrivate.js | 2 +- .../aws/cloudtrail/cloudtrailBucketPrivate.spec.js | 11 ++++++++++- 6 files changed, 33 insertions(+), 7 deletions(-) diff --git a/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js b/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js index a13d932e62..a3bfc726b9 100644 --- a/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js +++ b/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js @@ -59,7 +59,7 @@ module.exports = { if (!listBuckets.data.find(bucket => bucket.Name == trail.S3BucketName)) { helpers.addResult(results, 2, - 'Unable to locate S3 bucket, it may has been deleted', + 'Unable to locate S3 bucket, it may have been deleted', region, 'arn:aws:s3:::' + trail.S3BucketName); return cb(); } diff --git a/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.spec.js b/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.spec.js index 3663559486..4070c36b60 100644 --- a/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.spec.js +++ b/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.spec.js @@ -125,7 +125,6 @@ describe('cloudtrailBucketAccessLogging', function () { it('should PASS if bucket has S3 access logs enabled', function (done) { const cache = createCache([trails[0]], [listBuckets[0]], getBucketLogging[0]); cloudtrailBucketAccessLogging.run(cache, {}, (err, results) => { - console.log(results); expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -141,7 +140,7 @@ describe('cloudtrailBucketAccessLogging', function () { }); }); - it('should FAIL if Unable to locate S3 bucket, it may has been deleted', function (done) { + it('should FAIL if Unable to locate S3 bucket, it may have been deleted', function (done) { const cache = createCache([trails[2]], [listBuckets[1]], getBucketLogging[1]); cloudtrailBucketAccessLogging.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); @@ -150,6 +149,15 @@ describe('cloudtrailBucketAccessLogging', function () { }); }); + it('should PASS if no S3 bucket to check', function (done) { + const cache = createCache([], [], null); + cloudtrailBucketAccessLogging.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + it('should UNKNOWN if unable to query for trails', function (done) { const cache = createErrorCache(); cloudtrailBucketAccessLogging.run(cache, {}, (err, results) => { diff --git a/plugins/aws/cloudtrail/cloudtrailBucketDelete.js b/plugins/aws/cloudtrail/cloudtrailBucketDelete.js index bfd4ce50bd..0f0a25754e 100644 --- a/plugins/aws/cloudtrail/cloudtrailBucketDelete.js +++ b/plugins/aws/cloudtrail/cloudtrailBucketDelete.js @@ -57,7 +57,7 @@ module.exports = { if (!listBuckets.data.find(bucket => bucket.Name == trail.S3BucketName)) { helpers.addResult(results, 2, - 'Unable to locate S3 bucket, it may has been deleted', + 'Unable to locate S3 bucket, it may have been deleted', region, 'arn:aws:s3:::' + trail.S3BucketName); return cb(); } diff --git a/plugins/aws/cloudtrail/cloudtrailBucketDelete.spec.js b/plugins/aws/cloudtrail/cloudtrailBucketDelete.spec.js index 404414f33a..f81174bdc8 100644 --- a/plugins/aws/cloudtrail/cloudtrailBucketDelete.spec.js +++ b/plugins/aws/cloudtrail/cloudtrailBucketDelete.spec.js @@ -140,7 +140,7 @@ describe('cloudtrailBucketDelete', function () { }); }); - it('should FAIL if Unable to locate S3 bucket, it may has been deleted', function (done) { + it('should FAIL if Unable to locate S3 bucket, it may have been deleted', function (done) { const cache = createCache([trails[2]], [listBuckets[1]], getBucketVersioning[1]); cloudtrailBucketDelete.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); @@ -149,6 +149,15 @@ describe('cloudtrailBucketDelete', function () { }); }); + it('should PASS if no S3 bucket to check', function (done) { + const cache = createCache([], [], null); + cloudtrailBucketDelete.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + it('should UNKNOWN if unable to query for trails', function (done) { const cache = createErrorCache(); cloudtrailBucketDelete.run(cache, {}, (err, results) => { diff --git a/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js b/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js index 77b2f49c89..6f3e97fb7d 100644 --- a/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js +++ b/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js @@ -55,7 +55,7 @@ module.exports = { if (!listBuckets.data.find(bucket => bucket.Name == trail.S3BucketName)) { helpers.addResult(results, 2, - 'Unable to locate S3 bucket, it may has been deleted', + 'Unable to locate S3 bucket, it may have been deleted', region, 'arn:aws:s3:::' + trail.S3BucketName); return cb(); } diff --git a/plugins/aws/cloudtrail/cloudtrailBucketPrivate.spec.js b/plugins/aws/cloudtrail/cloudtrailBucketPrivate.spec.js index a1baefa295..8ab9e89c94 100644 --- a/plugins/aws/cloudtrail/cloudtrailBucketPrivate.spec.js +++ b/plugins/aws/cloudtrail/cloudtrailBucketPrivate.spec.js @@ -159,7 +159,7 @@ describe('cloudtrailBucketPrivate', function () { }); }); - it('should FAIL if Unable to locate S3 bucket, it may has been deleted', function (done) { + it('should FAIL if Unable to locate S3 bucket, it may have been deleted', function (done) { const cache = createCache([trails[2]], [listBuckets[1]], getBucketAcl[0]); cloudtrailBucketPrivate.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); @@ -168,6 +168,15 @@ describe('cloudtrailBucketPrivate', function () { }); }); + it('should PASS if no S3 bucket to check', function (done) { + const cache = createCache([], [], null); + cloudtrailBucketPrivate.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + it('should UNKNOWN if unable to query for trails', function (done) { const cache = createErrorCache(); cloudtrailBucketPrivate.run(cache, {}, (err, results) => { From a3b991683415b01a75091494ae2bb2cdc1a6a058 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Tue, 21 Jun 2022 19:55:40 +0500 Subject: [PATCH 279/350] SSM Agent Auto Update Enabled Plugin Failure --- plugins/aws/ssm/ssmAgentAutoUpdateEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/ssm/ssmAgentAutoUpdateEnabled.js b/plugins/aws/ssm/ssmAgentAutoUpdateEnabled.js index 5b3702efe0..b02ecee116 100644 --- a/plugins/aws/ssm/ssmAgentAutoUpdateEnabled.js +++ b/plugins/aws/ssm/ssmAgentAutoUpdateEnabled.js @@ -69,7 +69,7 @@ module.exports = { describeInstanceInformation.data.forEach(function(instance) { var resource = 'arn:' + awsOrGov + ':ec2:' + region + ':' + accountId + ':instance/' + instance.InstanceId; - if (associatedInstances.includes(resource) || associatedInstances.includes('*')) { + if (associatedInstances.includes(instance.InstanceId) || associatedInstances.includes('*')) { helpers.addResult(results, 0, 'Instance has SSM Agent auto update enabled', region, resource); } else { From f4ec81c632c320b3ad633616841c71175421c06d Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Wed, 22 Jun 2022 01:41:08 +0500 Subject: [PATCH 280/350] Oracle - VCN Inbound Security Lists --- exports.js | 1 + .../oracle/networking/inboundSecurityLists.js | 56 +++++++ .../networking/inboundSecurityLists.spec.js | 138 ++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 plugins/oracle/networking/inboundSecurityLists.js create mode 100644 plugins/oracle/networking/inboundSecurityLists.spec.js diff --git a/exports.js b/exports.js index b24a16826f..2bcd0bee6b 100644 --- a/exports.js +++ b/exports.js @@ -858,6 +858,7 @@ module.exports = { 'lbNSGEnabled' : require(__dirname + '/plugins/oracle/networking/lbNSGEnabled.js'), 'lbNoInstances' : require(__dirname + '/plugins/oracle/networking/lbNoInstances.js'), 'wafPublicIpEnabled' : require(__dirname + '/plugins/oracle/networking/wafPublicIpEnabled.js'), + 'inboundSecurityLists' : require(__dirname + '/plugins/oracle/networking/inboundSecurityLists.js'), 'multipleSubnets' : require(__dirname + '/plugins/oracle/networking/multipleSubnets.js'), 'subnetMultiAd' : require(__dirname + '/plugins/oracle/networking/subnetMultiAd.js'), diff --git a/plugins/oracle/networking/inboundSecurityLists.js b/plugins/oracle/networking/inboundSecurityLists.js new file mode 100644 index 0000000000..4f8961815e --- /dev/null +++ b/plugins/oracle/networking/inboundSecurityLists.js @@ -0,0 +1,56 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'VCN Inbound Security List', + category: 'Networking', + domain: 'Network Access Control', + description: 'Ensure all security lists have ingress rules configured.', + more_info: 'To control network access to your instancesx, it is recommended that Virtual Cloud Networks (VCN) security lists are configured with ingress rules which provide stateful and stateless firewall capability.', + link: 'https://docs.cloud.oracle.com/iaas/Content/Network/Concepts/securityrules.htm', + recommended_action: 'Add ingress rules to all security lists.', + apis: ['vcn:list', 'securityList:list'], + + run: function (cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.securityList, function (region, rcb) { + + if (helpers.checkRegionSubscription(cache, source, results, region)) { + var securityLists = helpers.addSource(cache, source, + ['securityList', 'list', region]); + + if (!securityLists || securityLists.err || !securityLists.data) { + helpers.addResult(results, 3, + 'Unable to query for security lists: ' + helpers.addError(securityLists), region); + return rcb(); + } + if (!securityLists.data.length) { + helpers.addResult(results, 0, 'No security lists found', region); + return rcb(); + } + + securityLists.data.forEach(securityList => { + if (securityList.ingressSecurityRules && securityList.ingressSecurityRules.length) { + helpers.addResult(results, 0, + `Security list has ingress rules configured`, region, securityList.displayName); + } + else { + helpers.addResult(results, 2, + `Security list does not have ingress rules configured`, region, securityList.displayName); + } + + + }); + + + } + rcb(); + }, function () { + // Global checking goes here + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/networking/inboundSecurityLists.spec.js b/plugins/oracle/networking/inboundSecurityLists.spec.js new file mode 100644 index 0000000000..1df38f1c63 --- /dev/null +++ b/plugins/oracle/networking/inboundSecurityLists.spec.js @@ -0,0 +1,138 @@ +var assert = require('assert'); +var expect = require('chai').expect; +var plugin = require('./inboundSecurityLists'); + +const createCache = (err, data) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + securityList: { + list: { + 'us-ashburn-1': { + err: err, + data: data + } + } + } + } +}; + +describe('inboundSecurityLists', function () { + describe('run', function () { + it('should give unknown result if an security list error is passed or no data is present', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security lists') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['error'], + null + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if no security lists records are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No security lists found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if security list has ingress rules configured', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('Security list has ingress rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [ + { + "id": "list2", + "displayName": "list-2", + "timeCreated": "2019-07-29T22:10:50.075Z", + "ingressSecurityRules": [{ + "isStateless": false, + "protocol": '6', + "source": '0.0.0.0/0', + "sourceType": 'CIDR_BLOCK', + }], + "lifecycleState": "AVAILABLE", + "vcnId": "v1" + } + ] + ); + + plugin.run(cache, {}, callback); + }); + + it('should give failing result if security list does not have ingress rules configured', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('Security list does not have ingress rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [ + { + "id": "list2", + "displayName": "list-2", + "timeCreated": "2019-07-29T22:10:50.075Z", + "ingressSecurityRules": [], + "lifecycleState": "AVAILABLE", + "vcnId": "v1" + } + ] + ); + + plugin.run(cache, {}, callback); + }); + }) +}) \ No newline at end of file From b463eedcfa2c70f398f97b945be2ab018665d371 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Wed, 22 Jun 2022 20:51:28 +0500 Subject: [PATCH 281/350] Added Results per resource for Open Port plugins --- helpers/aws/functions.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/helpers/aws/functions.js b/helpers/aws/functions.js index 0cd849e3b9..7037cac5eb 100644 --- a/helpers/aws/functions.js +++ b/helpers/aws/functions.js @@ -165,11 +165,23 @@ function findOpenPorts(groups, ports, service, region, results, cache, config, c addResult(results, 2, resultsString, region, resource); } + } else { + found = true; + let strings = []; + + for (const key in ports) { + strings.push(`${key.toUpperCase()}:${ports[key]}`) + } + if(strings.length){ + addResult(results, 0, + `Security group: ${groups[g].GroupId} (${groups[g].GroupName}) does not have ${strings.join(', ')} open to 0.0.0.0/0 or ::0`, + region, resource); + } } } if (!found && !usedGroup) { - addResult(results, 0, 'No public open ports found', region); + addResult(results, 0, 'No EC2 security groups found', region); } return; From 84becc2aa21fca89d99392470c13703c18bc02bd Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Wed, 22 Jun 2022 22:18:04 +0500 Subject: [PATCH 282/350] Solved linting issues --- helpers/aws/functions.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/helpers/aws/functions.js b/helpers/aws/functions.js index 7037cac5eb..a8ba909fb2 100644 --- a/helpers/aws/functions.js +++ b/helpers/aws/functions.js @@ -170,12 +170,12 @@ function findOpenPorts(groups, ports, service, region, results, cache, config, c let strings = []; for (const key in ports) { - strings.push(`${key.toUpperCase()}:${ports[key]}`) + strings.push(`${key.toUpperCase()}:${ports[key]}`); } - if(strings.length){ + if (strings.length){ addResult(results, 0, - `Security group: ${groups[g].GroupId} (${groups[g].GroupName}) does not have ${strings.join(', ')} open to 0.0.0.0/0 or ::0`, - region, resource); + `Security group: ${groups[g].GroupId} (${groups[g].GroupName}) does not have ${strings.join(', ')} open to 0.0.0.0/0 or ::0`, + region, resource); } } } From 3942447255354df231921d9278a646d5c03416f4 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Thu, 23 Jun 2022 15:25:35 +0500 Subject: [PATCH 283/350] Added updated eks latest platform versions --- plugins/aws/eks/eksLatestPlatformVersion.js | 8 ++++---- plugins/aws/eks/eksLatestPlatformVersion.spec.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/aws/eks/eksLatestPlatformVersion.js b/plugins/aws/eks/eksLatestPlatformVersion.js index 2d6e750862..57c90c6fc2 100644 --- a/plugins/aws/eks/eksLatestPlatformVersion.js +++ b/plugins/aws/eks/eksLatestPlatformVersion.js @@ -22,10 +22,10 @@ module.exports = { var accountId = helpers.addSource(cache, source, ['sts', 'getCallerIdentity', acctRegion, 'data']); var latestVersions = { - '1.22' : 1, - '1.21' : 6, - '1.20' : 5, - '1.19': 9 + '1.22' : 2, + '1.21' : 7, + '1.20' : 6, + '1.19': 10 }; var deprecatedVersions = { diff --git a/plugins/aws/eks/eksLatestPlatformVersion.spec.js b/plugins/aws/eks/eksLatestPlatformVersion.spec.js index 58efa5f09e..74c1faee3e 100644 --- a/plugins/aws/eks/eksLatestPlatformVersion.spec.js +++ b/plugins/aws/eks/eksLatestPlatformVersion.spec.js @@ -85,7 +85,7 @@ describe('eksLatestPlatformVersion', function () { "name": "das", "arn": "arn:aws:eks:us-east-1:012345678911:cluster/das", "version": "1.21", - "platformVersion": "eks.6", + "platformVersion": "eks.7", } } ); From 304c77e76d37b8fa683c609e49532fddc97ddd6f Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Fri, 24 Jun 2022 17:41:33 +0500 Subject: [PATCH 284/350] Added Some changes --- plugins/aws/ec2/ebsEncryptedSnapshots.js | 21 +--- plugins/aws/ec2/ebsEncryptedSnapshots.spec.js | 113 +----------------- 2 files changed, 7 insertions(+), 127 deletions(-) diff --git a/plugins/aws/ec2/ebsEncryptedSnapshots.js b/plugins/aws/ec2/ebsEncryptedSnapshots.js index 0e34d7750c..f10aa36a2c 100644 --- a/plugins/aws/ec2/ebsEncryptedSnapshots.js +++ b/plugins/aws/ec2/ebsEncryptedSnapshots.js @@ -39,26 +39,15 @@ module.exports = { return rcb(); } - var unencryptedSnapshots = []; - describeSnapshots.data.forEach(function(snapshot){ - if (!snapshot.Encrypted){ - // arn:aws:ec2:region:account-id:snapshot/snapshot-id - var arn = 'arn:aws:ec2:' + region + ':' + snapshot.OwnerId + ':snapshot/' + snapshot.SnapshotId; - unencryptedSnapshots.push(arn); + var arn = 'arn:aws:ec2:' + region + ':' + snapshot.OwnerId + ':snapshot/' + snapshot.SnapshotId; + if (snapshot.Encrypted){ + helpers.addResult(results, 0, 'EBS snapshot is encrypted', region, arn); + } else { + helpers.addResult(results, 2, 'EBS snapshot is unencrypted', region, arn); } }); - if (unencryptedSnapshots.length > 20) { - helpers.addResult(results, 2, 'More than 20 EBS snapshots are unencrypted', region); - } else if (unencryptedSnapshots.length) { - for (var u in unencryptedSnapshots) { - helpers.addResult(results, 2, 'EBS snapshot is unencrypted', region, unencryptedSnapshots[u]); - } - } else { - helpers.addResult(results, 0, 'No unencrypted snapshots found', region); - } - rcb(); }, function(){ callback(null, results, source); diff --git a/plugins/aws/ec2/ebsEncryptedSnapshots.spec.js b/plugins/aws/ec2/ebsEncryptedSnapshots.spec.js index b6a2d46ba5..826ed4625a 100644 --- a/plugins/aws/ec2/ebsEncryptedSnapshots.spec.js +++ b/plugins/aws/ec2/ebsEncryptedSnapshots.spec.js @@ -19,107 +19,7 @@ const describeSnapshots = [ "Encrypted": false, "OwnerId": '111122223333', "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, - { - "Encrypted": false, - "OwnerId": '111122223333', - "SnapshotId": 'snap-0a97ac5b19a598f50' - }, + }, ]; @@ -161,7 +61,7 @@ const createNullCache = () => { describe('ebsEncryptedSnapshots', function () { describe('run', function () { - it('should PASS if no unencrypted snapshots found', function (done) { + it('should PASS if EBS snapshot is encrypted', function (done) { const cache = createCache([describeSnapshots[0]]); ebsEncryptedSnapshots.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); @@ -179,15 +79,6 @@ describe('ebsEncryptedSnapshots', function () { }); }); - it('should FAIL if more than 20 EBS snapshots are unencrypted', function (done) { - const cache = createCache(describeSnapshots); - ebsEncryptedSnapshots.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(2); - done(); - }); - }); - it('should PASS if no EBS snapshots present', function (done) { const cache = createCache([]); ebsEncryptedSnapshots.run(cache, {}, (err, results) => { From ade1695fe4a0bae590d4b0ed80076830247869cf Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sat, 25 Jun 2022 21:10:04 +0500 Subject: [PATCH 285/350] GCP,Oracle - separate results in Open Port plugins --- helpers/google/functions.js | 13 ++++++------- helpers/oracle/functions.js | 24 ++++++------------------ 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/helpers/google/functions.js b/helpers/google/functions.js index d1928d041f..90a0b2fb07 100644 --- a/helpers/google/functions.js +++ b/helpers/google/functions.js @@ -79,7 +79,6 @@ function findOpenPorts(ngs, protocols, service, location, results, cache, source } var project = projects.data[0].name; - let found = false; for (let sgroups of ngs) { let strings = []; let resource = createResourceName('firewalls', sgroups.name, project, 'global'); @@ -109,13 +108,11 @@ function findOpenPorts(ngs, protocols, service, location, results, cache, source var string = `` + (protocol === '*' ? `All protocols` : protocol.toUpperCase()) + ` port ` + port + ` open to ` + sourcefilter; strings.push(string); if (strings.indexOf(string) === -1) strings.push(string); - found = true; } } else if (parseInt(portRange) === port) { var string = `` + (protocol === '*' ? `All protocols` : protocol.toUpperCase()) + ` port ` + port + ` open to ` + sourcefilter; if (strings.indexOf(string) === -1) strings.push(string); - found = true; } }); } @@ -130,10 +127,12 @@ function findOpenPorts(ngs, protocols, service, location, results, cache, source ') has ' + service + ': ' + strings.join(' and '), location, resource); } - } - - if (!found) { - shared.addResult(results, 0, 'No public open ports found', location); + else { + shared.addResult(results, 0, + 'Firewall Rule:(' + sgroups.name + + ') does not have ' + service + ' port open ' , location, + resource); + } } } diff --git a/helpers/oracle/functions.js b/helpers/oracle/functions.js index feaff068ad..ed65ac7e4b 100644 --- a/helpers/oracle/functions.js +++ b/helpers/oracle/functions.js @@ -19,7 +19,6 @@ var ipProtocol = { }; function findOpenPorts(groups, ports, service, region, results, isSecurityRule, securityGroups) { - var found = false; if (isSecurityRule) { for (var p in groups) { var messages = []; @@ -44,7 +43,6 @@ function findOpenPorts(groups, ports, service, region, results, isSecurityRule, var message = portIndex.toUpperCase() + ' port ' + port + ' open to 0.0.0.0/0'; if (messages.indexOf(message) === -1) messages.push(message); - found = true; } } } else if (permission.isValid && @@ -67,7 +65,6 @@ function findOpenPorts(groups, ports, service, region, results, isSecurityRule, var message = portIndex.toUpperCase() + ' port ' + port + ' open to 0.0.0.0/0'; if (messages.indexOf(message) === -1) messages.push(message); - found = true; } } } @@ -92,7 +89,6 @@ function findOpenPorts(groups, ports, service, region, results, isSecurityRule, var message = portIndex.toUpperCase() + ' port ' + port + ' open to ::/0'; if (messages.indexOf(message) === -1) messages.push(message); - found = true; } } } else if (permission.isValid && @@ -115,7 +111,6 @@ function findOpenPorts(groups, ports, service, region, results, isSecurityRule, var message = portIndex.toUpperCase() + ' port ' + port + ' open to ::/0'; if (messages.indexOf(message) === -1) messages.push(message); - found = true; } } } @@ -154,7 +149,6 @@ function findOpenPorts(groups, ports, service, region, results, isSecurityRule, var message = portIndex.toUpperCase() + ' port ' + port + ' open to 0.0.0.0/0'; if (messages.indexOf(message) === -1) messages.push(message); - found = true; } } } else if (permission.udpOptions && permission.source === '0.0.0.0/0') { @@ -171,7 +165,6 @@ function findOpenPorts(groups, ports, service, region, results, isSecurityRule, var message = portIndex.toUpperCase() + ' port ' + port + ' open to 0.0.0.0/0'; if (messages.indexOf(message) === -1) messages.push(message); - found = true; } } } @@ -190,7 +183,6 @@ function findOpenPorts(groups, ports, service, region, results, isSecurityRule, var message = portIndex.toUpperCase() + ' port ' + port + ' open to ::/0'; if (messages.indexOf(message) === -1) messages.push(message); - found = true; } } } else if (permission.udpOptions && permission.source === '::/0') { @@ -207,7 +199,6 @@ function findOpenPorts(groups, ports, service, region, results, isSecurityRule, var message = portIndex.toUpperCase() + ' port ' + port + ' open to ::/0'; if (messages.indexOf(message) === -1) messages.push(message); - found = true; } } } @@ -219,17 +210,14 @@ function findOpenPorts(groups, ports, service, region, results, isSecurityRule, ' has ' + service + ': ' + messages.join(' and '), region, resource); } - + else { + shared.addResult(results, 0, + 'The Security List: ' + sgroups.displayName + + ' does not have ' + service + ' port open', region, + resource); + } } } - if (!found && - isSecurityRule) { - shared.addResult(results, 0, 'No open ports found in Network Security Groups', region); - } else { - shared.addResult(results, 0, 'No open ports found in Security Lists', region); - - } - return; } From bb1ec4662d010b941a30bd78b8dfbf29cec04f57 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sat, 25 Jun 2022 21:53:59 +0500 Subject: [PATCH 286/350] Oracle - fixed specs for open port plugins --- plugins/google/vpcnetwork/openCustomPorts.spec.js | 1 - plugins/oracle/networking/openCIFS.spec.js | 6 ++---- plugins/oracle/networking/openDNS.spec.js | 6 ++---- plugins/oracle/networking/openDocker.spec.js | 6 ++---- plugins/oracle/networking/openFTP.spec.js | 6 ++---- plugins/oracle/networking/openHadoopNameNode.spec.js | 6 ++---- plugins/oracle/networking/openHadoopNameNodeWebUI.spec.js | 6 ++---- plugins/oracle/networking/openKibana.spec.js | 6 ++---- plugins/oracle/networking/openMySQL.spec.js | 6 ++---- plugins/oracle/networking/openNetBIOS.spec.js | 6 ++---- plugins/oracle/networking/openOracle.spec.js | 6 ++---- .../oracle/networking/openOracleAutoDataWarehouse.spec.js | 6 ++---- plugins/oracle/networking/openPostgreSQL.spec.js | 6 ++---- plugins/oracle/networking/openRDP.spec.js | 6 ++---- plugins/oracle/networking/openRPC.spec.js | 6 ++---- plugins/oracle/networking/openSMBoTCP.spec.js | 6 ++---- plugins/oracle/networking/openSMTP.spec.js | 6 ++---- plugins/oracle/networking/openSQLServer.spec.js | 6 ++---- plugins/oracle/networking/openSSH.spec.js | 6 ++---- plugins/oracle/networking/openSalt.spec.js | 6 ++---- plugins/oracle/networking/openTelnet.spec.js | 6 ++---- plugins/oracle/networking/openVNCClient.spec.js | 6 ++---- plugins/oracle/networking/openVNCServer.spec.js | 6 ++---- 23 files changed, 44 insertions(+), 89 deletions(-) diff --git a/plugins/google/vpcnetwork/openCustomPorts.spec.js b/plugins/google/vpcnetwork/openCustomPorts.spec.js index b5f99b370c..21daff4a53 100644 --- a/plugins/google/vpcnetwork/openCustomPorts.spec.js +++ b/plugins/google/vpcnetwork/openCustomPorts.spec.js @@ -99,7 +99,6 @@ describe('openCustomPorts', function () { const callback = (err, results) => { expect(results.length).to.be.above(0); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); expect(results[0].region).to.equal('global'); done() }; diff --git a/plugins/oracle/networking/openCIFS.spec.js b/plugins/oracle/networking/openCIFS.spec.js index 7f7fe30e09..9ff23db469 100644 --- a/plugins/oracle/networking/openCIFS.spec.js +++ b/plugins/oracle/networking/openCIFS.spec.js @@ -227,7 +227,6 @@ describe('openCIFS', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -247,9 +246,8 @@ describe('openCIFS', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openDNS.spec.js b/plugins/oracle/networking/openDNS.spec.js index 478fd97a66..2b55c5ead8 100644 --- a/plugins/oracle/networking/openDNS.spec.js +++ b/plugins/oracle/networking/openDNS.spec.js @@ -226,7 +226,6 @@ describe('openDNS', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -246,9 +245,8 @@ describe('openDNS', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openDocker.spec.js b/plugins/oracle/networking/openDocker.spec.js index 51eb3995d0..9fba726332 100644 --- a/plugins/oracle/networking/openDocker.spec.js +++ b/plugins/oracle/networking/openDocker.spec.js @@ -233,7 +233,6 @@ describe('openDocker', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -253,9 +252,8 @@ describe('openDocker', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openFTP.spec.js b/plugins/oracle/networking/openFTP.spec.js index a5849a525b..bdac671d91 100644 --- a/plugins/oracle/networking/openFTP.spec.js +++ b/plugins/oracle/networking/openFTP.spec.js @@ -233,7 +233,6 @@ describe('openFTP', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -253,9 +252,8 @@ describe('openFTP', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openHadoopNameNode.spec.js b/plugins/oracle/networking/openHadoopNameNode.spec.js index 0df7605346..b66cf8f452 100644 --- a/plugins/oracle/networking/openHadoopNameNode.spec.js +++ b/plugins/oracle/networking/openHadoopNameNode.spec.js @@ -233,7 +233,6 @@ describe('openHadoopNameNode', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -253,9 +252,8 @@ describe('openHadoopNameNode', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openHadoopNameNodeWebUI.spec.js b/plugins/oracle/networking/openHadoopNameNodeWebUI.spec.js index ad14e6faa1..3300fde41c 100644 --- a/plugins/oracle/networking/openHadoopNameNodeWebUI.spec.js +++ b/plugins/oracle/networking/openHadoopNameNodeWebUI.spec.js @@ -233,7 +233,6 @@ describe('openHadoopNameNodeWebUI', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -253,9 +252,8 @@ describe('openHadoopNameNodeWebUI', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openKibana.spec.js b/plugins/oracle/networking/openKibana.spec.js index 2b2ffaedbe..fe6c70dcc2 100644 --- a/plugins/oracle/networking/openKibana.spec.js +++ b/plugins/oracle/networking/openKibana.spec.js @@ -226,7 +226,6 @@ describe('openKibana', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -246,9 +245,8 @@ describe('openKibana', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openMySQL.spec.js b/plugins/oracle/networking/openMySQL.spec.js index 0955b7b02c..2173fd9419 100644 --- a/plugins/oracle/networking/openMySQL.spec.js +++ b/plugins/oracle/networking/openMySQL.spec.js @@ -233,7 +233,6 @@ describe('openMySQL', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -253,9 +252,8 @@ describe('openMySQL', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openNetBIOS.spec.js b/plugins/oracle/networking/openNetBIOS.spec.js index cc06b64b79..e0cf63c951 100644 --- a/plugins/oracle/networking/openNetBIOS.spec.js +++ b/plugins/oracle/networking/openNetBIOS.spec.js @@ -233,7 +233,6 @@ describe('openNetBIOS', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -253,9 +252,8 @@ describe('openNetBIOS', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openOracle.spec.js b/plugins/oracle/networking/openOracle.spec.js index 6457485912..f364cb76b5 100644 --- a/plugins/oracle/networking/openOracle.spec.js +++ b/plugins/oracle/networking/openOracle.spec.js @@ -226,7 +226,6 @@ describe('openOracle', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -246,9 +245,8 @@ describe('openOracle', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openOracleAutoDataWarehouse.spec.js b/plugins/oracle/networking/openOracleAutoDataWarehouse.spec.js index 6e36f33e08..3d4de0d9c4 100644 --- a/plugins/oracle/networking/openOracleAutoDataWarehouse.spec.js +++ b/plugins/oracle/networking/openOracleAutoDataWarehouse.spec.js @@ -226,7 +226,6 @@ describe('openOracleAutoDataWarehouse', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -246,9 +245,8 @@ describe('openOracleAutoDataWarehouse', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openPostgreSQL.spec.js b/plugins/oracle/networking/openPostgreSQL.spec.js index 797e9fd3d0..549d66e3d0 100644 --- a/plugins/oracle/networking/openPostgreSQL.spec.js +++ b/plugins/oracle/networking/openPostgreSQL.spec.js @@ -226,7 +226,6 @@ describe('openPostgreSQL', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -246,9 +245,8 @@ describe('openPostgreSQL', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openRDP.spec.js b/plugins/oracle/networking/openRDP.spec.js index 2baefa07d5..85dfc08a5f 100644 --- a/plugins/oracle/networking/openRDP.spec.js +++ b/plugins/oracle/networking/openRDP.spec.js @@ -226,7 +226,6 @@ describe('openRDP', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -246,9 +245,8 @@ describe('openRDP', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openRPC.spec.js b/plugins/oracle/networking/openRPC.spec.js index 62ecf0379c..4d31455ca4 100644 --- a/plugins/oracle/networking/openRPC.spec.js +++ b/plugins/oracle/networking/openRPC.spec.js @@ -226,7 +226,6 @@ describe('openRPC', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -246,9 +245,8 @@ describe('openRPC', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openSMBoTCP.spec.js b/plugins/oracle/networking/openSMBoTCP.spec.js index e43ac94fbe..3bbc8ea20f 100644 --- a/plugins/oracle/networking/openSMBoTCP.spec.js +++ b/plugins/oracle/networking/openSMBoTCP.spec.js @@ -226,7 +226,6 @@ describe('openSMBoTCP', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -246,9 +245,8 @@ describe('openSMBoTCP', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openSMTP.spec.js b/plugins/oracle/networking/openSMTP.spec.js index 472e5f222c..20cd9ae7ea 100644 --- a/plugins/oracle/networking/openSMTP.spec.js +++ b/plugins/oracle/networking/openSMTP.spec.js @@ -226,7 +226,6 @@ describe('openSMTP', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -246,9 +245,8 @@ describe('openSMTP', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openSQLServer.spec.js b/plugins/oracle/networking/openSQLServer.spec.js index d11fb2ffb7..27e8c328d6 100644 --- a/plugins/oracle/networking/openSQLServer.spec.js +++ b/plugins/oracle/networking/openSQLServer.spec.js @@ -226,7 +226,6 @@ describe('openSQLServer', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -246,9 +245,8 @@ describe('openSQLServer', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openSSH.spec.js b/plugins/oracle/networking/openSSH.spec.js index 4aec4064a4..6a8408e1d3 100644 --- a/plugins/oracle/networking/openSSH.spec.js +++ b/plugins/oracle/networking/openSSH.spec.js @@ -212,7 +212,6 @@ describe('openSSH', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -232,9 +231,8 @@ describe('openSSH', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openSalt.spec.js b/plugins/oracle/networking/openSalt.spec.js index f21d7db0c8..c5bb59cf0b 100644 --- a/plugins/oracle/networking/openSalt.spec.js +++ b/plugins/oracle/networking/openSalt.spec.js @@ -233,7 +233,6 @@ describe('openSalt', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -253,9 +252,8 @@ describe('openSalt', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openTelnet.spec.js b/plugins/oracle/networking/openTelnet.spec.js index bb99d4886d..b32cc664bc 100644 --- a/plugins/oracle/networking/openTelnet.spec.js +++ b/plugins/oracle/networking/openTelnet.spec.js @@ -212,7 +212,6 @@ describe('openTelnet', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -232,9 +231,8 @@ describe('openTelnet', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openVNCClient.spec.js b/plugins/oracle/networking/openVNCClient.spec.js index dcc679bfd4..abe8038fde 100644 --- a/plugins/oracle/networking/openVNCClient.spec.js +++ b/plugins/oracle/networking/openVNCClient.spec.js @@ -212,7 +212,6 @@ describe('openVNCClient', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -232,9 +231,8 @@ describe('openVNCClient', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; diff --git a/plugins/oracle/networking/openVNCServer.spec.js b/plugins/oracle/networking/openVNCServer.spec.js index e0f7e1266d..c61177d9e9 100644 --- a/plugins/oracle/networking/openVNCServer.spec.js +++ b/plugins/oracle/networking/openVNCServer.spec.js @@ -212,7 +212,6 @@ describe('openVNCServer', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No open ports found in Security Lists') expect(results[0].region).to.equal('us-ashburn-1') done() }; @@ -232,9 +231,8 @@ describe('openVNCServer', function () { it('should PASS if no open ports found in network security groups', function (done) { const callback = (err, results) => { expect(results.length).to.be.above(0) - expect(results[1].status).to.equal(0) - expect(results[1].message).to.include('No open ports found in Network Security Groups') - expect(results[1].region).to.equal('us-ashburn-1') + expect(results[0].status).to.equal(0) + expect(results[0].region).to.equal('us-ashburn-1') done() }; From e95af1906aaef6bf3e002161f1fc75f66aed4c64 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sun, 26 Jun 2022 05:42:31 +0500 Subject: [PATCH 287/350] OCI - deafult Tgas For Resources Plugin --- collectors/oracle/collector.js | 8 + exports.js | 1 + helpers/oracle/regions.js | 1 + other_modules/oci/services.json | 12 ++ .../identity/defaultTagsForResources.js | 50 +++++++ .../identity/defaultTagsForResources.spec.js | 139 ++++++++++++++++++ 6 files changed, 211 insertions(+) create mode 100644 plugins/oracle/identity/defaultTagsForResources.js create mode 100644 plugins/oracle/identity/defaultTagsForResources.spec.js diff --git a/collectors/oracle/collector.js b/collectors/oracle/collector.js index a268483d60..be04d82fec 100644 --- a/collectors/oracle/collector.js +++ b/collectors/oracle/collector.js @@ -132,6 +132,14 @@ var calls = { filterValue: ['compartmentId'], } }, + defaultTags: { + list: { + api: 'iam', + filterKey: ['compartmentId'], + filterValue: ['compartmentId'], + restVersion: '/20160918' + } + }, waasPolicy: { list: { api: 'waas', diff --git a/exports.js b/exports.js index c37bad6793..902bf499b8 100644 --- a/exports.js +++ b/exports.js @@ -828,6 +828,7 @@ module.exports = { 'userCustomerSecretKeysRotated' : require(__dirname + '/plugins/oracle/identity/userCustomerSecretKeysRotated.js'), 'userAPIKeysRotated' : require(__dirname + '/plugins/oracle/identity/userAPIKeysRotated.js'), 'usersPasswordLastUsed' : require(__dirname + '/plugins/oracle/identity/usersPasswordLastUsed.js'), + 'defaultTagsForResources' : require(__dirname + '/plugins/oracle/identity/defaultTagsForResources.js'), 'openSSH' : require(__dirname + '/plugins/oracle/networking/openSSH.js'), 'openOracleAutoDataWarehouse' : require(__dirname + '/plugins/oracle/networking/openOracleAutoDataWarehouse.js'), diff --git a/helpers/oracle/regions.js b/helpers/oracle/regions.js index db04409479..3259814c48 100644 --- a/helpers/oracle/regions.js +++ b/helpers/oracle/regions.js @@ -51,6 +51,7 @@ module.exports = { bucket: regions, waasPolicy: regions, policy: regions, + defaultTags: regions, subnet: regions, dbHome: regions, database: regions, diff --git a/other_modules/oci/services.json b/other_modules/oci/services.json index f2ea92c1b9..3db8868118 100644 --- a/other_modules/oci/services.json +++ b/other_modules/oci/services.json @@ -317,6 +317,18 @@ "endpoint": "identity.{{region}}.oraclecloud.com" } }, + "defaultTags": { + "list" : { + "allowedQueryStrings": [ + "compartmentId", + "page", + "limit" + ], + "method": "GET", + "path": "tagDefaults", + "endpoint": "identity.{{region}}.oraclecloud.com" + } + }, "group": { "list": { "allowedQueryStrings": [ diff --git a/plugins/oracle/identity/defaultTagsForResources.js b/plugins/oracle/identity/defaultTagsForResources.js new file mode 100644 index 0000000000..a4878e9a28 --- /dev/null +++ b/plugins/oracle/identity/defaultTagsForResources.js @@ -0,0 +1,50 @@ +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Default Tags For Resources', + category: 'Logging and Monitoring', + domain: 'Identity', + description: 'Ensures default tags are used on resources.', + more_info: 'Having default tags like "CreatedBy" on resources help determine who created the resource in case of an accident.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Tagging/Tasks/managingtagdefaults.htm', + recommended_action: 'Create default tags at the root compartment to ensure that all resources get tagged.', + apis: ['defaultTags:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + + var region = helpers.objectFirstKey(cache['regionSubscription']['list']); + + var defaultTags = helpers.addSource(cache, source, + ['defaultTags', 'list', region]); + + if (!defaultTags) return callback(null, results, source); + + if (defaultTags.err || !defaultTags.data) { + helpers.addResult(results, 3, + 'Unable to query for default tags: ' + helpers.addError(defaultTags), region); + return callback(null, results, source); + } + + if (!defaultTags.data.length) { + helpers.addResult(results, 2, 'No default tags found', region); + return callback(null, results, source); + } + + const compartment = defaultTags.data[0].compartmentId; + + const resourceTag = defaultTags.data.find(tag => + tag.value && tag.value === '${iam.principal.name}' + && tag.lifecycleState && tag.lifecycleState === 'ACTIVE'); + + + if (resourceTag) { + helpers.addResult(results, 0, 'Compartment is using default tags for resources', region, compartment); + } else { + helpers.addResult(results, 2, 'Compartment is not using default tags for resources', region, compartment); + } + + callback(null, results, source); + } +}; \ No newline at end of file diff --git a/plugins/oracle/identity/defaultTagsForResources.spec.js b/plugins/oracle/identity/defaultTagsForResources.spec.js new file mode 100644 index 0000000000..bc920c9164 --- /dev/null +++ b/plugins/oracle/identity/defaultTagsForResources.spec.js @@ -0,0 +1,139 @@ +var expect = require('chai').expect; +var plugin = require('./defaultTagsForResources'); + +const defaultTagsList = [ + { + value: '${iam.principal.name}', + tagNamespaceId: 'namespace-1', + tagDefinitionId: 'tag-1', + tagDefinitionName: 'CreatedBy', + isRequired: false, + id: 'tag-1', + compartmentId: 'compartment-1', + timeCreated: '2022-01-04T16:42:07.246Z', + lifecycleState: 'ACTIVE' + }, + { + value: '${oci.datetime}', + tagNamespaceId: 'namespace-1', + tagDefinitionId: 'tag-1', + tagDefinitionName: 'CreatedOn', + isRequired: false, + id: 'tag-1', + compartmentId: 'compartment-1', + timeCreated: '2022-01-04T16:42:07.561Z', + lifecycleState: 'ACTIVE' + } +]; + +const createCache = (err, data) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + defaultTags: { + list: { + 'us-ashburn-1': { + err: err, + data: data + } + } + } + } +}; + +describe('defaultTags', function () { + describe('run', function () { + it('should give unknown result if unable to query for default tags', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for default tags') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + {err: 'error'}, + undefined + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no default tags found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No default tags found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if compartment does not have default tags for resources', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('is not using') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [defaultTagsList[1]] + ); + + plugin.run(cache, {}, callback); + }); + + it('should give passing result if comaprtment has default tags for resources enabled', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('is using') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [defaultTagsList[0]] + ); + + plugin.run(cache, {}, callback); + }); + + }); +}); \ No newline at end of file From 9b6b53aae2c92bd952ffcb0e77efab67256658f4 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sun, 26 Jun 2022 06:48:56 +0500 Subject: [PATCH 288/350] OCI - Notification topic with subscription plugin --- collectors/oracle/collector.js | 16 ++ exports.js | 1 + helpers/oracle/regions.js | 2 + other_modules/oci/services.json | 26 ++ .../identity/notificationTopicSubscription.js | 128 ++++++++++ .../notificationTopicSubscription.spec.js | 228 ++++++++++++++++++ 6 files changed, 401 insertions(+) create mode 100644 plugins/oracle/identity/notificationTopicSubscription.js create mode 100644 plugins/oracle/identity/notificationTopicSubscription.spec.js diff --git a/collectors/oracle/collector.js b/collectors/oracle/collector.js index a268483d60..bba6268ba1 100644 --- a/collectors/oracle/collector.js +++ b/collectors/oracle/collector.js @@ -140,6 +140,22 @@ var calls = { filterValue: ['compartmentId'], } }, + topics: { + list: { + api: 'notification', + restVersion: '/20181201', + filterKey: ['compartmentId'], + filterValue: ['compartmentId'], + } + }, + subscriptions: { + list: { + api: 'notification', + restVersion: '/20181201', + filterKey: ['compartmentId'], + filterValue: ['compartmentId'], + } + }, policy: { list: { api: 'iam', diff --git a/exports.js b/exports.js index c37bad6793..6f366bdb68 100644 --- a/exports.js +++ b/exports.js @@ -828,6 +828,7 @@ module.exports = { 'userCustomerSecretKeysRotated' : require(__dirname + '/plugins/oracle/identity/userCustomerSecretKeysRotated.js'), 'userAPIKeysRotated' : require(__dirname + '/plugins/oracle/identity/userAPIKeysRotated.js'), 'usersPasswordLastUsed' : require(__dirname + '/plugins/oracle/identity/usersPasswordLastUsed.js'), + 'notificationTopicSubscription' : require(__dirname + '/plugins/oracle/identity/notificationTopicSubscription.js'), 'openSSH' : require(__dirname + '/plugins/oracle/networking/openSSH.js'), 'openOracleAutoDataWarehouse' : require(__dirname + '/plugins/oracle/networking/openOracleAutoDataWarehouse.js'), diff --git a/helpers/oracle/regions.js b/helpers/oracle/regions.js index db04409479..182c24b7cc 100644 --- a/helpers/oracle/regions.js +++ b/helpers/oracle/regions.js @@ -50,6 +50,8 @@ module.exports = { compartment: regions, bucket: regions, waasPolicy: regions, + topics: regions, + subscriptions: regions, policy: regions, subnet: regions, dbHome: regions, diff --git a/other_modules/oci/services.json b/other_modules/oci/services.json index f2ea92c1b9..8e1cc5bc58 100644 --- a/other_modules/oci/services.json +++ b/other_modules/oci/services.json @@ -37,6 +37,32 @@ } } }, + "notification": { + "topics": { + "list": { + "allowedQueryStrings": [ + "compartmentId", + "limit", + "page" + ], + "method": "GET", + "path": "topics", + "endpoint": "notification.{{region}}.oraclecloud.com" + } + }, + "subscriptions": { + "list": { + "allowedQueryStrings": [ + "compartmentId", + "limit", + "page" + ], + "method": "GET", + "path": "subscriptions", + "endpoint": "notification.{{region}}.oraclecloud.com" + } + } + }, "core": { "instance": { "list": { diff --git a/plugins/oracle/identity/notificationTopicSubscription.js b/plugins/oracle/identity/notificationTopicSubscription.js new file mode 100644 index 0000000000..571abed501 --- /dev/null +++ b/plugins/oracle/identity/notificationTopicSubscription.js @@ -0,0 +1,128 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Notification Topic With Active Subscription', + category: 'Identity', + domain: 'Logging and Monitoring', + description: 'Ensure that there is at least one notification topic and subscription to receive monitoring alerts.', + more_info: 'HCreating and subscribing to one or more notification topics allows administrators to be notified of any changes in the Oracle Cloud Infrastructure.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Notification/Tasks/managingtopicsandsubscriptions.htm', + recommended_action: 'Create at least one notification topic with an active subscription.', + apis: ['topics:list','subscriptions:list'], + + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.subscriptions, function(region, rcb) { + + if (helpers.checkRegionSubscription(cache, source, results, region)) { + + var topics = helpers.addSource(cache, source, + ['topics', 'list', region]); + + if (!topics) return rcb(); + + if (topics.err || !topics.data) { + helpers.addResult(results, 3, + 'Unable to query for topics: ' + helpers.addError(topics), region); + return rcb(); + } + if (!topics.data.length) { + helpers.addResult(results, 2, 'No topics found', region); + return rcb(); + } + + const activeTopic = topics.data.find(topic => + topic.lifecycleState && topic.lifecycleState === 'ACTIVE' + ); + + if (!activeTopic) { + helpers.addResult(results, 2, + 'No active topics found in the region', region); + return rcb(); + } + + var subscriptions = helpers.addSource(cache, source, + ['subscriptions', 'list', region]); + + if (!subscriptions) return rcb(); + + if (subscriptions.err || !subscriptions.data) { + helpers.addResult(results, 3, + 'Unable to query for subscriptions: ' + helpers.addError(subscriptions), region); + return rcb(); + } + if (!subscriptions.data.length) { + helpers.addResult(results, 2, 'No subscriptions found in the region', region); + return rcb(); + } + + const activeSubscription = subscriptions.data.find(subscription => + subscription.lifecycleState && subscription.lifecycleState === 'ACTIVE' + ); + + if (activeSubscription) { + helpers.addResult(results, 0, + 'There is at least one notification topic with an active subscription', region); + } else { + helpers.addResult(results, 2, + 'No notification topics with active subscriptions found', region); + } + } + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; + +// async.each(regions.subscriptions, function (region, rcb) { + +// if (helpers.checkRegionSubscription(cache, source, results, region)) { + +// var topics = helpers.addSource(cache, source, +// ['topics', 'list', region]); + +// if (!topics) return rcb(); + +// if (topics.err || !topics.data) { +// helpers.addResult(results, 3, +// 'Unable to query for topics: ' + helpers.addError(topics), region); +// } +// if (!topics.data.length) { +// helpers.addResult(results, 2, 'No topics found in the region', region); +// } + +// var subscriptions = helpers.addSource(cache, source, +// ['subscriptions', 'list', region]); + +// if (!subscriptions) return rcb(); + +// if (subscriptions.err || !subscriptions.data) { +// helpers.addResult(results, 3, +// 'Unable to query for osubscriptions: ' + helpers.addError(subscriptions), region); +// } +// if (!subscriptions.data.length) { +// helpers.addResult(results, 2, 'No subscriptions found in the region', region); +// } + +// const activeSubscription = subscriptions.data.find(subscription => +// subscription.lifecycleState && subscription.lifecycleState === 'ACTIVE' +// ); + +// if (activeSubscription) { +// helpers.addResult(results, 0, +// `There is at least one notification topic with an active subscription`, region); +// } else { +// helpers.addResult(results, 2, +// 'No notification topics with active subscriptions found'); +// } +// } +// rcb(); +// }, function () { +// callback(null, results, source); +// }); \ No newline at end of file diff --git a/plugins/oracle/identity/notificationTopicSubscription.spec.js b/plugins/oracle/identity/notificationTopicSubscription.spec.js new file mode 100644 index 0000000000..38d943223f --- /dev/null +++ b/plugins/oracle/identity/notificationTopicSubscription.spec.js @@ -0,0 +1,228 @@ +var expect = require('chai').expect; +var plugin = require('./notificationTopicSubscription'); + +const topics = [{ + name: 'topic-1', + topicId: 'topic-1', + shortTopicId: null, + compartmentId: 'compartment-1', + lifecycleState: 'ACTIVE', + description: null, + timeCreated: '2022-06-26T00:56:58.950Z', + }, + { + name: 'topic-2', + topicId: 'topic-1', + shortTopicId: null, + compartmentId: 'compartment-1', + lifecycleState: 'DELETED', + description: null, + timeCreated: '2022-06-26T00:56:58.950Z', + } +]; +const subscriptions = [ + { + id: 'sub-1', + topicId: 'topic-1', + protocol: 'EMAIL', + endpoint: 'myemail@gmail.com', + lifecycleState: 'PENDING', + compartmentId: 'compartment-1', + createdTime: 1656205041117, + }, + { + id: 'sub-2', + topicId: 'topic-1', + protocol: 'EMAIL', + endpoint: 'myemail@gmail.com', + lifecycleState: 'ACTIVE', + compartmentId: 'compartment-1', + createdTime: 1656205041117, + } +]; + +const createCache = (err, subscriptions, topicsErr, topics) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + subscriptions: { + list: { + 'us-ashburn-1': { + err: err, + data: subscriptions + } + } + }, + topics: { + list: { + 'us-ashburn-1': { + err: topicsErr, + data: topics + } + } + } + } +}; + +describe('notificationTopicSubscription', function () { + describe('run', function () { + it('should give unknown result if unable to query for topics', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for topics') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + null, + ['err'], + undefined + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no topics found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No topics found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + null, + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no active topics found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No active topics found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + null, + null, + [topics[1]] + ); + + plugin.run(cache, {}, callback); + }) + it('should give unknown result if unable to query for subscriptions', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for subscriptions') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['err'], + undefined, + null, + topics + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no subscriptions found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No subscriptions found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [], + null, + topics + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no active subscriptions found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No notification topics with active subscriptions found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [subscriptions[0]], + null, + topics + ); + + plugin.run(cache, {}, callback); + }) + + + it('should give passing result if there is one topic with active subscription', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('There is at least one') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [subscriptions[1]], + null, + topics + ); + + plugin.run(cache, {}, callback); + }) + + + }); +}); \ No newline at end of file From d7882dd7941573eea6d426c001b1db987abc3b75 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 14:20:09 +0500 Subject: [PATCH 289/350] Apply suggestions from code review --- plugins/oracle/objectstore/bucketCMKEncryption.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oracle/objectstore/bucketCMKEncryption.js b/plugins/oracle/objectstore/bucketCMKEncryption.js index daa486bf49..54858c5032 100644 --- a/plugins/oracle/objectstore/bucketCMKEncryption.js +++ b/plugins/oracle/objectstore/bucketCMKEncryption.js @@ -14,7 +14,7 @@ module.exports = { bucket_encryption_level: { name: 'Bucket Encryption Level', description: 'Desired protection level for Object store buckets. default: oracle-managed, cloudcmek: customer managed encryption keys, ' + - 'cloudhsm: customer managed HSM encryption key, external: imported or externally managed key', + 'cloudhsm: customer managed HSM encryption key', regex: '^(default|cloudcmek|cloudhsm)$', default: 'cloudcmek' } From ff717698ea2a5c52f29ec3b4beafd3b52d06563f Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 14:24:37 +0500 Subject: [PATCH 290/350] Apply suggestions from code review --- plugins/oracle/oke/okePrivateEndpoint.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oracle/oke/okePrivateEndpoint.js b/plugins/oracle/oke/okePrivateEndpoint.js index 86d72d5e79..21b858b4b0 100644 --- a/plugins/oracle/oke/okePrivateEndpoint.js +++ b/plugins/oracle/oke/okePrivateEndpoint.js @@ -5,7 +5,7 @@ module.exports = { title: 'OKE Private Endpoint', category: 'OKE', domain: 'Containers', - description: 'Ensures the private endpoint setting is enabled for OKE clusters', + description: 'Ensures the private endpoint setting is enabled for OKE clusters.', more_info: 'OKE private endpoints can be used to route all traffic between the Kubernetes worker and control plane nodes over a private VCN endpoint rather than across the public internet.', recommended_action: 'Enable the private endpoint setting for all OKE clusters.', link: 'https://docs.oracle.com/en-us/iaas/Content/ContEng/Concepts/contengclustersnodes.htm#processes', From 7f89fbb80a1ded637bf2decdfdd868bc2f5e38ae Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 14:25:29 +0500 Subject: [PATCH 291/350] Apply suggestions from code review --- plugins/oracle/oke/okeSecretsEncrypted.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oracle/oke/okeSecretsEncrypted.js b/plugins/oracle/oke/okeSecretsEncrypted.js index 19f504b144..223030657c 100644 --- a/plugins/oracle/oke/okeSecretsEncrypted.js +++ b/plugins/oracle/oke/okeSecretsEncrypted.js @@ -14,7 +14,7 @@ module.exports = { oke_encryption_level: { name: 'OKE Encryption Level', description: 'Desired protection level for OKE Secrets. default: oracle-managed, cloudcmek: customer managed encryption keys, ' + - 'cloudhsm: customer managed HSM encryption key, external: imported or externally managed key', + 'cloudhsm: customer managed HSM encryption key', regex: '^(default|cloudcmek|cloudhsm)$', default: 'cloudcmek' } From 36fb28685cd8bf2adf0faa1e34df0b4c96c52501 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 15:12:48 +0500 Subject: [PATCH 292/350] Apply suggestions from code review --- plugins/aws/computeoptimizer/ebsVolumesOptimized.js | 6 +++--- plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js index 66dbe6b1ed..05f12e24f3 100644 --- a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js @@ -5,7 +5,7 @@ module.exports = { title: 'EBS Volumes Optimized', category: 'Compute Optimizer', domain: 'Management and Governance', - description: 'Ensure that Compute Optimizer EBS volume recommendations are in order to take the actions to optimize Amazon EBS volumes that are under-performing.', + description: 'Ensure that Compute Optimizer EBS volume recommendations are enabled.', more_info: 'An EBS volume is considered optimized when Compute Optimizer determines that the volume is correctly provisioned to run your workload, based on the chosen volume type, volume size, and IOPS specification. For optimized resources, Compute Optimizer might sometimes recommend a new generation volume type.', link: 'https://docs.aws.amazon.com/compute-optimizer/latest/ug/view-ebs-recommendations.html', recommended_action: 'Enable Compute Optimizer Opt In options for EBS volume recommendations', @@ -49,7 +49,7 @@ module.exports = { if (!notOptimized.value && !optimized.value){ helpers.addResult(results, 0, - 'EBS volumes have no recommendations enabled', region); + 'No recommendations found for EBS volumes', region); } else if (notOptimized.value){ helpers.addResult(results, 2, `EBS volumes are not optimized, NOT_OPTIMIZED: ${notOptimized.value}`, region); @@ -59,7 +59,7 @@ module.exports = { } } else { helpers.addResult(results, 2, - 'No EBS volumes configured', region); + 'Recommendation summaries are not configured for EBS Volumes', region); } rcb(); diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js index a321553e21..4d4be38df8 100644 --- a/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js @@ -102,13 +102,13 @@ describe('ebsVolumesOptimized', function () { }); }); - it('should PASS if EBS volumes have no recommendations enabled', function (done) { + it('should PASS if EBS volumes have no recommendations found for EBS volumes', function (done) { const cache = createCache([getRecommendationSummaries[2]]); ebsVolumesOptimized.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('EBS volumes have no recommendations enabled'); + expect(results[0].message).to.include('No recommendations found for EBS volumes'); done(); }); }); From 0f2b3e06dc39cf44476ed1ff84aec120fb57c91e Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 15:12:58 +0500 Subject: [PATCH 293/350] Apply suggestions from code review --- plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js index 4d4be38df8..dba028a446 100644 --- a/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js @@ -119,7 +119,7 @@ describe('ebsVolumesOptimized', 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('Optimization for summaries is not configured'); + expect(results[0].message).to.include('No Compute Optimizer recommendation summaries found'); done(); }); }); From d373fc875e25621c4372136ad0277551e64720f3 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 15:13:05 +0500 Subject: [PATCH 294/350] Update plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js --- plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js index dba028a446..f98124290f 100644 --- a/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js @@ -113,7 +113,7 @@ describe('ebsVolumesOptimized', function () { }); }); - it('should PASS if Optimization for summaries is not configured', function (done) { + it('should PASS if No Compute Optimizer recommendation summaries found', function (done) { const cache = createCache([]); ebsVolumesOptimized.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); From 8e6efba8b6606a54c014403006a8cd8db3162048 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 15:13:13 +0500 Subject: [PATCH 295/350] Update plugins/aws/computeoptimizer/ebsVolumesOptimized.js --- plugins/aws/computeoptimizer/ebsVolumesOptimized.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js index 05f12e24f3..7743fd2cea 100644 --- a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js @@ -37,7 +37,7 @@ module.exports = { if (!getRecommendationSummaries.data.length) { helpers.addResult(results, 0, - 'Optimization for summaries is not configured', region); + 'No Compute Optimizer recommendation summaries found', region); return rcb(); } From 07f635c1b07e390a923409147b9581cc7cd169b7 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 15:33:32 +0500 Subject: [PATCH 296/350] Apply suggestions from code review --- plugins/aws/computeoptimizer/ebsVolumesOptimized.js | 2 +- plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js index 7743fd2cea..a84e45a50c 100644 --- a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js @@ -52,7 +52,7 @@ module.exports = { 'No recommendations found for EBS volumes', region); } else if (notOptimized.value){ helpers.addResult(results, 2, - `EBS volumes are not optimized, NOT_OPTIMIZED: ${notOptimized.value}`, region); + `Found ${notOptimized.value} unoptimized EBS volumes`, region); } else { helpers.addResult(results, 0, 'All EBS volumes are optimized', region); diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js index f98124290f..d151474e54 100644 --- a/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.spec.js @@ -97,7 +97,7 @@ describe('ebsVolumesOptimized', 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('EBS volumes are not optimized'); + expect(results[0].message).to.include('unoptimized EBS volumes'); done(); }); }); From 1cb91f191ef0691baaf337dfdce43626abb5bfa2 Mon Sep 17 00:00:00 2001 From: M-Akhtar Date: Sun, 26 Jun 2022 16:02:21 +0500 Subject: [PATCH 297/350] Made some changes --- exports.js | 2 +- ...onError.js => optimizerRecommendationsEnabled.js} | 6 +++--- ...ec.js => optimizerRecommendationsEnabled.spec.js} | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) rename plugins/aws/computeoptimizer/{optimizedConfigurationError.js => optimizerRecommendationsEnabled.js} (91%) rename plugins/aws/computeoptimizer/{optimizedConfigurationError.spec.js => optimizerRecommendationsEnabled.spec.js} (86%) diff --git a/exports.js b/exports.js index 56c6e59f44..bb23da0f6c 100644 --- a/exports.js +++ b/exports.js @@ -84,7 +84,7 @@ module.exports = { 'globalLoggingDuplicated' : require(__dirname + '/plugins/aws/cloudtrail/globalLoggingDuplicated.js'), 'cloudtrailNotificationsEnabled': require(__dirname + '/plugins/aws/cloudtrail/cloudtrailNotificationsEnabled.js'), - 'optimizedConfigurationError' : require(__dirname + '/plugins/aws/computeoptimizer/optimizedConfigurationError.js'), + 'optimizerRecommendationsEnabled': require(__dirname + '/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.js'), 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), 'configComplaintRules' : require(__dirname + '/plugins/aws/configservice/configComplaintRules.js'), diff --git a/plugins/aws/computeoptimizer/optimizedConfigurationError.js b/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.js similarity index 91% rename from plugins/aws/computeoptimizer/optimizedConfigurationError.js rename to plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.js index 421e624033..47321e3b1c 100644 --- a/plugins/aws/computeoptimizer/optimizedConfigurationError.js +++ b/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.js @@ -2,13 +2,13 @@ var async = require('async'); var helpers = require('../../../helpers/aws'); module.exports = { - title: 'Optimized Configuration Error', + title: 'Compute Optimizer Recommendations Enabled', category: 'Compute Optimizer', domain: 'Management and Governance', - description: 'Ensure that Compute Optimizer is enabled to avoid any Opt In exception error.', + description: 'Ensure that Compute Optimizer is enabled for your AWS account.', more_info: 'AWS Compute Optimizer is a service that analyzes the configuration and utilization metrics of your AWS resources. It reports whether your resources are optimal, and generates optimization recommendations to reduce the cost and improve the performance of your workloads.', link: 'https://docs.aws.amazon.com/compute-optimizer/latest/ug/what-is-compute-optimizer.html', - recommended_action: 'Enable Compute Optimizer Opt In options to avoid Opt In Required exception error', + recommended_action: 'Enable Compute Optimizer Opt In options for current of all AWS account in your organization.', apis: ['ComputeOptimizer:getRecommendationSummaries'], run: function(cache, settings, callback) { diff --git a/plugins/aws/computeoptimizer/optimizedConfigurationError.spec.js b/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.spec.js similarity index 86% rename from plugins/aws/computeoptimizer/optimizedConfigurationError.spec.js rename to plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.spec.js index 66dccb0f79..9a1c0e5750 100644 --- a/plugins/aws/computeoptimizer/optimizedConfigurationError.spec.js +++ b/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.spec.js @@ -1,5 +1,5 @@ var expect = require('chai').expect; -var optimizedConfigurationError = require('./optimizedConfigurationError'); +var optimizerRecommendationsEnabled = require('./optimizerRecommendationsEnabled'); const getRecommendationSummaries = [ { @@ -48,11 +48,11 @@ const createCache = (recommendation, recommendationErr) => { }; }; -describe('optimizedConfigurationError', function () { +describe('optimizerRecommendationsEnabled', function () { describe('run', function () { it('should PASS if Compute Optimizer is Enabled', function (done) { const cache = createCache([getRecommendationSummaries[0]]); - optimizedConfigurationError.run(cache, {}, (err, results) => { + optimizerRecommendationsEnabled.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'); @@ -63,7 +63,7 @@ describe('optimizedConfigurationError', function () { it('should FAIL if Compute Optimizer is not enabled', function (done) { const cache = createCache(null, { message: 'Aws account is not registered for recommendation.', code: 'OptInRequiredException' }); - optimizedConfigurationError.run(cache, {}, (err, results) => { + optimizerRecommendationsEnabled.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'); @@ -75,7 +75,7 @@ describe('optimizedConfigurationError', function () { it('should UNKNOWN if Unable to get recommendation summaries', function (done) { const cache = createCache(null, { message: "Unable to get recommendation summaries" }); - optimizedConfigurationError.run(cache, {}, (err, results) => { + optimizerRecommendationsEnabled.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'); @@ -85,7 +85,7 @@ describe('optimizedConfigurationError', function () { }); it('should not return anything if get recommendation summaries status response is not found', () => { - optimizedConfigurationError.run({}, {}, (err, results) => { + optimizerRecommendationsEnabled.run({}, {}, (err, results) => { expect(results.length).to.equal(0); }) }); From f535f3577e025f138a61d9752896b6524f830a13 Mon Sep 17 00:00:00 2001 From: M-Akhtar Date: Sun, 26 Jun 2022 16:04:22 +0500 Subject: [PATCH 298/350] Made some changes --- plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.js b/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.js index 47321e3b1c..3af67d6407 100644 --- a/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.js +++ b/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.js @@ -23,7 +23,7 @@ module.exports = { if (!getRecommendationSummaries) return rcb(); if (getRecommendationSummaries && getRecommendationSummaries.err && getRecommendationSummaries.err.code && - getRecommendationSummaries.err.code === 'OptInRequiredException'){ + getRecommendationSummaries.err.code.toUpperCase() === 'OPTINREQUIREDEXCEPTION'){ helpers.addResult(results, 2, 'Compute Optimizer is not enabled', region); } else if (getRecommendationSummaries.err || !getRecommendationSummaries.data || From ceec4fc0b3e086df147b9329e71fc075bf976fd1 Mon Sep 17 00:00:00 2001 From: M-Akhtar Date: Sun, 26 Jun 2022 16:05:21 +0500 Subject: [PATCH 299/350] Made some changes --- .../computeoptimizer/optimizerRecommendationsEnabled.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.spec.js b/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.spec.js index 9a1c0e5750..a9f5b57a4b 100644 --- a/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.spec.js +++ b/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.spec.js @@ -79,7 +79,7 @@ describe('optimizerRecommendationsEnabled', 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 get recommendation summaries'); + expect(results[0].message).to.include('Unable to get Compute Optimizer recommendation summaries'); done(); }); }); From 97fcbfa2912b028793ccedeea8d679c8f9a17ff0 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Sun, 26 Jun 2022 16:08:29 +0500 Subject: [PATCH 300/350] Fixed error --- plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.js b/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.js index 3af67d6407..d3950d3abc 100644 --- a/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.js +++ b/plugins/aws/computeoptimizer/optimizerRecommendationsEnabled.js @@ -29,7 +29,7 @@ module.exports = { } else if (getRecommendationSummaries.err || !getRecommendationSummaries.data || !getRecommendationSummaries.data.length) { helpers.addResult(results, 3, - 'Unable to get recommendation summaries: ' + helpers.addError(getRecommendationSummaries), region); + 'Unable to get Compute Optimizer recommendation summaries: ' + helpers.addError(getRecommendationSummaries), region); } else { helpers.addResult(results, 0, 'Compute Optimizer is Enabled', region); From 8aeb930cc7dfb547f36151477e2b4ac1ef388b90 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 16:28:57 +0500 Subject: [PATCH 301/350] Update plugins/aws/computeoptimizer/ebsVolumesOptimized.js --- plugins/aws/computeoptimizer/ebsVolumesOptimized.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js index a84e45a50c..b53342035a 100644 --- a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js @@ -5,7 +5,7 @@ module.exports = { title: 'EBS Volumes Optimized', category: 'Compute Optimizer', domain: 'Management and Governance', - description: 'Ensure that Compute Optimizer EBS volume recommendations are enabled.', + description: 'Ensure that Compute Optimizer recommendation summaries does not include unoptimized EBS Volumes.', more_info: 'An EBS volume is considered optimized when Compute Optimizer determines that the volume is correctly provisioned to run your workload, based on the chosen volume type, volume size, and IOPS specification. For optimized resources, Compute Optimizer might sometimes recommend a new generation volume type.', link: 'https://docs.aws.amazon.com/compute-optimizer/latest/ug/view-ebs-recommendations.html', recommended_action: 'Enable Compute Optimizer Opt In options for EBS volume recommendations', From 58b8533aeb44ba9bc3a59572f3df630064500e6e Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 16:30:23 +0500 Subject: [PATCH 302/350] Update plugins/aws/computeoptimizer/ebsVolumesOptimized.js --- plugins/aws/computeoptimizer/ebsVolumesOptimized.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js index b53342035a..f0bb0e1e81 100644 --- a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js @@ -5,7 +5,7 @@ module.exports = { title: 'EBS Volumes Optimized', category: 'Compute Optimizer', domain: 'Management and Governance', - description: 'Ensure that Compute Optimizer recommendation summaries does not include unoptimized EBS Volumes.', + description: 'Ensure that Compute Optimizer does not have active recommendation summaries for unoptimized EBS Volumes.', more_info: 'An EBS volume is considered optimized when Compute Optimizer determines that the volume is correctly provisioned to run your workload, based on the chosen volume type, volume size, and IOPS specification. For optimized resources, Compute Optimizer might sometimes recommend a new generation volume type.', link: 'https://docs.aws.amazon.com/compute-optimizer/latest/ug/view-ebs-recommendations.html', recommended_action: 'Enable Compute Optimizer Opt In options for EBS volume recommendations', From 624d557ef522246b11aba9ee7c50709498dea190 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 16:44:48 +0500 Subject: [PATCH 303/350] Apply suggestions from code review --- plugins/aws/computeoptimizer/ebsVolumesOptimized.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js index f0bb0e1e81..e2b11b651e 100644 --- a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js @@ -8,7 +8,7 @@ module.exports = { description: 'Ensure that Compute Optimizer does not have active recommendation summaries for unoptimized EBS Volumes.', more_info: 'An EBS volume is considered optimized when Compute Optimizer determines that the volume is correctly provisioned to run your workload, based on the chosen volume type, volume size, and IOPS specification. For optimized resources, Compute Optimizer might sometimes recommend a new generation volume type.', link: 'https://docs.aws.amazon.com/compute-optimizer/latest/ug/view-ebs-recommendations.html', - recommended_action: 'Enable Compute Optimizer Opt In options for EBS volume recommendations', + recommended_action: 'Resolve Compute Optimizer recommendations for EBS Volumes.', apis: ['ComputeOptimizer:getRecommendationSummaries'], run: function(cache, settings, callback) { From 4055ac267e4b7bbd73fcfa65c260e88f5d283c49 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 16:45:22 +0500 Subject: [PATCH 304/350] Apply suggestions from code review --- plugins/aws/computeoptimizer/ebsVolumesOptimized.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js index e2b11b651e..8c8f9bcc73 100644 --- a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js @@ -8,7 +8,7 @@ module.exports = { description: 'Ensure that Compute Optimizer does not have active recommendation summaries for unoptimized EBS Volumes.', more_info: 'An EBS volume is considered optimized when Compute Optimizer determines that the volume is correctly provisioned to run your workload, based on the chosen volume type, volume size, and IOPS specification. For optimized resources, Compute Optimizer might sometimes recommend a new generation volume type.', link: 'https://docs.aws.amazon.com/compute-optimizer/latest/ug/view-ebs-recommendations.html', - recommended_action: 'Resolve Compute Optimizer recommendations for EBS Volumes.', + recommended_action: 'Resolve Compute Optimizer recommendations for EBS volumes.', apis: ['ComputeOptimizer:getRecommendationSummaries'], run: function(cache, settings, callback) { From e2babd4bad36ccf745960e482192d7d697cc6bc5 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 16:47:37 +0500 Subject: [PATCH 305/350] Update plugins/aws/computeoptimizer/ebsVolumesOptimized.js --- plugins/aws/computeoptimizer/ebsVolumesOptimized.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js index 8c8f9bcc73..2458424cb2 100644 --- a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js @@ -23,7 +23,7 @@ module.exports = { if (!getRecommendationSummaries) return rcb(); if (getRecommendationSummaries && getRecommendationSummaries.err && - getRecommendationSummaries.err.code === 'OptInRequiredException'){ + getRecommendationSummaries.err.code.toUpperCase() === 'OPTINREQUIREDEXCEPTION'){ helpers.addResult(results, 0, 'Compute Optimizer is not enabled', region); return rcb(); From bf89a17167c2bde895720addb91c1dce57800147 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Sun, 26 Jun 2022 17:54:49 +0500 Subject: [PATCH 306/350] fixed issue --- plugins/aws/computeoptimizer/ebsVolumesOptimized.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js index 2458424cb2..d00f4a6be1 100644 --- a/plugins/aws/computeoptimizer/ebsVolumesOptimized.js +++ b/plugins/aws/computeoptimizer/ebsVolumesOptimized.js @@ -22,7 +22,8 @@ module.exports = { if (!getRecommendationSummaries) return rcb(); - if (getRecommendationSummaries && getRecommendationSummaries.err && + if (getRecommendationSummaries && getRecommendationSummaries.err && + getRecommendationSummaries.err.code && getRecommendationSummaries.err.code.toUpperCase() === 'OPTINREQUIREDEXCEPTION'){ helpers.addResult(results, 0, 'Compute Optimizer is not enabled', region); From 8bc2ddc45fe049e9768567e54b455b7ab8b1b975 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Sun, 26 Jun 2022 18:04:46 +0500 Subject: [PATCH 307/350] Made few changes --- plugins/aws/computeoptimizer/asgOptimized.js | 22 ++++++++++--------- .../aws/computeoptimizer/asgOptimized.spec.js | 12 +++++----- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/plugins/aws/computeoptimizer/asgOptimized.js b/plugins/aws/computeoptimizer/asgOptimized.js index 00eafec348..1fe6ef2dfe 100644 --- a/plugins/aws/computeoptimizer/asgOptimized.js +++ b/plugins/aws/computeoptimizer/asgOptimized.js @@ -5,10 +5,10 @@ module.exports = { title: 'Auto Scaling Group Optimized', category: 'Compute Optimizer', domain: 'Management and Governance', - description: 'Ensure that Compute Optimizer ASGs findings are in order to take the actions to optimize Amazon Auto Scaling groups that are under-performing.', + description: 'Ensure that Compute Optimizer does not have active recommendation summaries for unoptimized Auto Scaling groups.', more_info: 'An Auto Scaling group is considered optimized when Compute Optimizer determines that the group is correctly provisioned to run your workload, based on the chosen instance type. For optimized Auto Scaling groups, Compute Optimizer might sometimes recommend a new generation instance type.', link: 'https://docs.aws.amazon.com/compute-optimizer/latest/ug/view-asg-recommendations.html', - recommended_action: 'Enable Compute Optimizer Opt In options for Auto Scaling Groups recommendations', + recommended_action: 'Resolve Compute Optimizer recommendations for Auto Scaling groups.', apis: ['ComputeOptimizer:getRecommendationSummaries'], run: function(cache, settings, callback) { @@ -22,8 +22,9 @@ module.exports = { if (!getRecommendationSummaries) return rcb(); - if (getRecommendationSummaries && getRecommendationSummaries.err && - getRecommendationSummaries.err.code === 'OptInRequiredException'){ + if (getRecommendationSummaries && getRecommendationSummaries.err && + getRecommendationSummaries.err.code && + getRecommendationSummaries.err.code.toUpperCase() === 'OPTINREQUIREDEXCEPTION'){ helpers.addResult(results, 0, 'Compute Optimizer is not enabled', region); return rcb(); @@ -37,11 +38,12 @@ module.exports = { if (!getRecommendationSummaries.data.length) { helpers.addResult(results, 0, - 'Optimization for summaries is not configured', region); + 'No Compute Optimizer recommendation summaries found', region); return rcb(); } - let findings = getRecommendationSummaries.data.find(resourceType => resourceType.recommendationResourceType === 'AutoScalingGroup'); + let findings = getRecommendationSummaries.data.find(resourceType => resourceType.recommendationResourceType && + resourceType.recommendationResourceType.toUpperCase() === 'AUTOSCALINGGROUP'); if (findings) { let notOptimized = findings.summaries.find(notOpt => notOpt.name && notOpt.name.toUpperCase() === 'NOT_OPTIMIZED'); @@ -49,17 +51,17 @@ module.exports = { if (!notOptimized.value && !Optimized.value){ helpers.addResult(results, 0, - 'Auto Scaling Groups have no recommendations enabled', region); + 'No recommendations found for Auto Scaling groups', region); } else if (notOptimized.value){ helpers.addResult(results, 2, - `Auto Scaling Groups are not optimized, NOT_OPTIMIZED: ${notOptimized.value}`, region); + `Found ${notOptimized.value} unoptimized Auto Scaling groups`, region); } else { helpers.addResult(results, 0, - 'All Auto Scaling Groups are optimized', region); + 'All Auto Scaling groups are optimized', region); } } else { helpers.addResult(results, 2, - 'No Auto Scaling Group configured', region); + 'Recommendation summaries are not configured for Auto Scaling groups', region); } rcb(); diff --git a/plugins/aws/computeoptimizer/asgOptimized.spec.js b/plugins/aws/computeoptimizer/asgOptimized.spec.js index 71ed154cd8..eb83ec28b2 100644 --- a/plugins/aws/computeoptimizer/asgOptimized.spec.js +++ b/plugins/aws/computeoptimizer/asgOptimized.spec.js @@ -86,7 +86,7 @@ describe('asgOptimized', 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('All Auto Scaling Groups are optimized'); + expect(results[0].message).to.include('All Auto Scaling groups are optimized'); done(); }); }); @@ -97,29 +97,29 @@ describe('asgOptimized', 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('Auto Scaling Groups are not optimized'); + expect(results[0].message).to.include('unoptimized Auto Scaling groups'); done(); }); }); - it('should PASS if Auto Scaling Groups have no recommendations enabled', function (done) { + it('should PASS if no recommendations found for Auto Scaling groups', function (done) { const cache = createCache([getRecommendationSummaries[2]]); asgOptimized.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('Auto Scaling Groups have no recommendations enabled'); + expect(results[0].message).to.include('No recommendations found for Auto Scaling groups'); done(); }); }); - it('should PASS if Optimization for summaries is not configured', function (done) { + it('should PASS if no Compute Optimizer recommendation summaries found', function (done) { const cache = createCache([]); asgOptimized.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('Optimization for summaries is not configured'); + expect(results[0].message).to.include('No Compute Optimizer recommendation summaries found'); done(); }); }); From 2850a61d1b30972c46e7bb3ad79709dabbd517b3 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Sun, 26 Jun 2022 18:23:22 +0500 Subject: [PATCH 308/350] made few changes --- .../computeoptimizer/ec2InstancesOptimized.js | 19 +++++++++++-------- .../ec2InstancesOptimized.spec.js | 6 +++--- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/plugins/aws/computeoptimizer/ec2InstancesOptimized.js b/plugins/aws/computeoptimizer/ec2InstancesOptimized.js index 1e8f8aa2a3..ff50a04dd8 100644 --- a/plugins/aws/computeoptimizer/ec2InstancesOptimized.js +++ b/plugins/aws/computeoptimizer/ec2InstancesOptimized.js @@ -5,10 +5,10 @@ module.exports = { title: 'EC2 Instances Optimized', category: 'Compute Optimizer', domain: 'Management and Governance', - description: 'Ensure that Compute Optimizer EC2 findings are in order to take the actions to optimize Amazon EC2 instances that are under-provisioned and over-provisioned.', + description: 'Ensure that Compute Optimizer does not have active recommendation summaries for over-provisioned or under-provisioned EC2 instances.', more_info: 'An EC2 instance is considered optimized when all specifications of an instance, such as CPU, memory, and network, meet the performance requirements of your workload, and the instance is not over-provisioned. For optimized instances, Compute Optimizer might sometimes recommend a new generation instance type.', link: 'https://docs.aws.amazon.com/compute-optimizer/latest/ug/view-ec2-recommendations.html', - recommended_action: 'Enable Compute Optimizer Opt In options for Ec2 instances recommendations', + recommended_action: 'Resolve Compute Optimizer recommendations for EC2 instances.', apis: ['ComputeOptimizer:getRecommendationSummaries'], run: function(cache, settings, callback) { @@ -22,8 +22,9 @@ module.exports = { if (!getRecommendationSummaries) return rcb(); - if (getRecommendationSummaries && getRecommendationSummaries.err && - getRecommendationSummaries.err.code === 'OptInRequiredException'){ + if (getRecommendationSummaries && getRecommendationSummaries.err && + getRecommendationSummaries.err.code && + getRecommendationSummaries.err.code.toUpperCase() === 'OPTINREQUIREDEXCEPTION'){ helpers.addResult(results, 0, 'Compute Optimizer is not enabled', region); return rcb(); @@ -37,28 +38,30 @@ module.exports = { if (!getRecommendationSummaries.data.length) { helpers.addResult(results, 0, - 'Optimization for summaries is not configured', region); + 'No Compute Optimizer recommendation summaries found', region); return rcb(); } - let findings = getRecommendationSummaries.data.find(resourceType => resourceType.recommendationResourceType === 'Ec2Instance'); + let findings = getRecommendationSummaries.data.find(resourceType => resourceType.recommendationResourceType && + resourceType.recommendationResourceType.toUpperCase() === 'EC2INSTANCE'); if (findings) { let underProvisioned = findings.summaries.find(underProv => underProv.name === 'UNDER_PROVISIONED' ); let optimized = findings.summaries.find(opt => opt.name === 'OPTIMIZED' ); let overProvisioned = findings.summaries.find(overProv => overProv.name === 'OVER_PROVISIONED' ); + if (!underProvisioned.value && !overProvisioned.value && !optimized.value){ helpers.addResult(results, 0, 'EC2 instances have no recommendations enabled', region); } else if (underProvisioned.value || overProvisioned.value){ helpers.addResult(results, 2, - `EC2 instances are not optimized, under provisioned: ${underProvisioned.value}, over provisioned: ${underProvisioned.value} `, region); + `Found ${underProvisioned.value} under-provisioned and ${overProvisioned.value} over-provisioned EC2 instances`, region); } else { helpers.addResult(results, 0, 'All EC2 instances are optimized', region); } } else { helpers.addResult(results, 2, - 'No EC2 instances configured', region); + 'Recommendation summaries are not configured for EC2 instances', region); } rcb(); diff --git a/plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js b/plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js index c569e933d0..359cf73b67 100644 --- a/plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js +++ b/plugins/aws/computeoptimizer/ec2InstancesOptimized.spec.js @@ -109,7 +109,7 @@ describe('ec2InstancesOptimized', 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('EC2 instances are not optimized'); + expect(results[0].message).to.include('over-provisioned EC2 instances'); done(); }); }); @@ -125,13 +125,13 @@ describe('ec2InstancesOptimized', function () { }); }); - it('should PASS if Optimization for summaries is not configured', function (done) { + it('should PASS if no Compute Optimizer recommendation summaries found', function (done) { const cache = createCache([]); ec2InstancesOptimized.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('Optimization for summaries is not configured'); + expect(results[0].message).to.include('No Compute Optimizer recommendation summaries found'); done(); }); }); From a8434f78d3caab884f2b571affd680ae4dd1188f Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 19:53:25 +0500 Subject: [PATCH 309/350] Apply suggestions from code review --- plugins/aws/msk/mskClusterPublicAccess.js | 4 ++-- plugins/aws/msk/mskClusterPublicAccess.spec.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/aws/msk/mskClusterPublicAccess.js b/plugins/aws/msk/mskClusterPublicAccess.js index afb815854b..5336dad6b1 100644 --- a/plugins/aws/msk/mskClusterPublicAccess.js +++ b/plugins/aws/msk/mskClusterPublicAccess.js @@ -45,10 +45,10 @@ module.exports = { cluster.BrokerNodeGroupInfo.ConnectivityInfo.PublicAccess.Type && cluster.BrokerNodeGroupInfo.ConnectivityInfo.PublicAccess.Type.toUpperCase() === 'DISABLED') { helpers.addResult(results, 0, - 'MSK cluster does not have public access enabled', region, resource); + 'MSK cluster is not publicly accessible', region, resource); } else { helpers.addResult(results, 2, - 'MSK cluster has public access enabled', region, resource); + 'MSK cluster is publicly accessible', region, resource); } } diff --git a/plugins/aws/msk/mskClusterPublicAccess.spec.js b/plugins/aws/msk/mskClusterPublicAccess.spec.js index 5c849111a8..a4e042973e 100644 --- a/plugins/aws/msk/mskClusterPublicAccess.spec.js +++ b/plugins/aws/msk/mskClusterPublicAccess.spec.js @@ -99,7 +99,7 @@ describe('mskClusterPublicAccess', function () { mskClusterPublicAccess.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('MSK cluster has public access enabled'); + expect(results[0].message).to.include('MSK cluster is not publicly accessible'); done(); }); }); @@ -109,7 +109,7 @@ describe('mskClusterPublicAccess', function () { mskClusterPublicAccess.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('MSK cluster does not have public access enabled'); + expect(results[0].message).to.include('MSK cluster is not publicly accessible'); done(); }); }); From 5fd73313bae52c01af4cd9c1c70fa9be1cb18d61 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 19:58:49 +0500 Subject: [PATCH 310/350] Apply suggestions from code review --- plugins/aws/msk/mskClusterUnauthAccess.js | 12 ++++++------ plugins/aws/msk/mskClusterUnauthAccess.spec.js | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/aws/msk/mskClusterUnauthAccess.js b/plugins/aws/msk/mskClusterUnauthAccess.js index 7fee953e35..39da16d781 100644 --- a/plugins/aws/msk/mskClusterUnauthAccess.js +++ b/plugins/aws/msk/mskClusterUnauthAccess.js @@ -6,10 +6,10 @@ module.exports = { category: 'MSK', domain: 'Compute', severity: 'Medium', - description: 'Ensure that Unauthentication is disabled within the cluster feature for your Amazon MSK clusters.', - more_info: 'Amazon MSK authenticate clients to allow or deny Apache Kafka actions. Alternatively, TLS or SASL/SCRAM can be used to authenticate clients, and Apache Kafka ACLs to allow or deny actions.', + description: 'Ensure that unauthenticated access feature is disabled for your Amazon MSK clusters.', + more_info: 'Amazon MSK authenticates clients to allow or deny Apache Kafka actions. Alternatively, TLS or SASL/SCRAM can be used to authenticate clients, and Apache Kafka ACLs to allow or deny actions.', link: 'https://docs.aws.amazon.com/msk/latest/developerguide/msk-authentication.html', - recommended_action: 'Check for Unauthentication disabled within the cluster for all MSK clusters to allow or deny actions for clients', + recommended_action: 'Ensure that MSK clusters does not have unauthenticated access enabled.', apis: ['Kafka:listClusters'], run: function(cache, settings, callback) { @@ -41,12 +41,12 @@ module.exports = { if (cluster.ClientAuthentication && cluster.ClientAuthentication.Unauthenticated && - cluster.ClientAuthentication.Unauthenticated.Enabled == true) { + cluster.ClientAuthentication.Unauthenticated.Enabled) { helpers.addResult(results, 2, - 'Unauthentication is enabled for clients, and all actions are allowed', region, resource); + 'Cluster had unauthenticated access enabled', region, resource); } else { helpers.addResult(results, 0, - 'Unauthentication is disabled for clients, and all actions are not allowed', region, resource); + 'Cluster does not have unauthenticated access enabled', region, resource); } } diff --git a/plugins/aws/msk/mskClusterUnauthAccess.spec.js b/plugins/aws/msk/mskClusterUnauthAccess.spec.js index b8adce496e..e19ea84e19 100644 --- a/plugins/aws/msk/mskClusterUnauthAccess.spec.js +++ b/plugins/aws/msk/mskClusterUnauthAccess.spec.js @@ -98,7 +98,7 @@ describe('mskClusterUnauthAccess', function () { mskClusterUnauthAccess.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('Unauthentication is enabled for clients, and all actions are allowed'); + expect(results[0].message).to.include('Cluster has authenticated access enabled'); done(); }); }); @@ -108,7 +108,7 @@ describe('mskClusterUnauthAccess', function () { mskClusterUnauthAccess.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('Unauthentication is disabled for clients, and all actions are not allowed'); + expect(results[0].message).to.include('Cluster does not have unauthenticated access enabled'); done(); }); }); From 9883ccc6e86abc5fd37a0b089e03a5f0c766d437 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 20:01:16 +0500 Subject: [PATCH 311/350] Apply suggestions from code review --- plugins/aws/msk/mskClusterPublicAccess.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/msk/mskClusterPublicAccess.spec.js b/plugins/aws/msk/mskClusterPublicAccess.spec.js index a4e042973e..1fad74e391 100644 --- a/plugins/aws/msk/mskClusterPublicAccess.spec.js +++ b/plugins/aws/msk/mskClusterPublicAccess.spec.js @@ -99,7 +99,7 @@ describe('mskClusterPublicAccess', function () { mskClusterPublicAccess.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('MSK cluster is not publicly accessible'); + expect(results[0].message).to.include('MSK cluster is publicly accessible'); done(); }); }); From 2122086544e29f10554823cd6d5abbe54db94460 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 20:01:59 +0500 Subject: [PATCH 312/350] Apply suggestions from code review --- plugins/aws/msk/mskClusterUnauthAccess.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/msk/mskClusterUnauthAccess.js b/plugins/aws/msk/mskClusterUnauthAccess.js index 39da16d781..e8725e6799 100644 --- a/plugins/aws/msk/mskClusterUnauthAccess.js +++ b/plugins/aws/msk/mskClusterUnauthAccess.js @@ -43,7 +43,7 @@ module.exports = { cluster.ClientAuthentication.Unauthenticated && cluster.ClientAuthentication.Unauthenticated.Enabled) { helpers.addResult(results, 2, - 'Cluster had unauthenticated access enabled', region, resource); + 'Cluster has unauthenticated access enabled', region, resource); } else { helpers.addResult(results, 0, 'Cluster does not have unauthenticated access enabled', region, resource); From 32b606e425f184c38ba869ee49b4b1547e2a535e Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 20:04:05 +0500 Subject: [PATCH 313/350] Apply suggestions from code review --- plugins/aws/msk/mskClusterUnauthAccess.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/msk/mskClusterUnauthAccess.spec.js b/plugins/aws/msk/mskClusterUnauthAccess.spec.js index e19ea84e19..bc51070f55 100644 --- a/plugins/aws/msk/mskClusterUnauthAccess.spec.js +++ b/plugins/aws/msk/mskClusterUnauthAccess.spec.js @@ -98,7 +98,7 @@ describe('mskClusterUnauthAccess', function () { mskClusterUnauthAccess.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('Cluster has authenticated access enabled'); + expect(results[0].message).to.include('Cluster has unauthenticated access enabled'); done(); }); }); From c03184bbf4ef0186de10da959f79ad8e90c44bb8 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 22:57:35 +0500 Subject: [PATCH 314/350] Apply suggestions from code review --- .../identity/notificationTopicSubscription.js | 54 +------------------ 1 file changed, 2 insertions(+), 52 deletions(-) diff --git a/plugins/oracle/identity/notificationTopicSubscription.js b/plugins/oracle/identity/notificationTopicSubscription.js index 571abed501..5345ec850f 100644 --- a/plugins/oracle/identity/notificationTopicSubscription.js +++ b/plugins/oracle/identity/notificationTopicSubscription.js @@ -6,7 +6,7 @@ module.exports = { category: 'Identity', domain: 'Logging and Monitoring', description: 'Ensure that there is at least one notification topic and subscription to receive monitoring alerts.', - more_info: 'HCreating and subscribing to one or more notification topics allows administrators to be notified of any changes in the Oracle Cloud Infrastructure.', + more_info: 'Creating and subscribing to one or more notification topics allows administrators to be notified of any changes in the Oracle Cloud Infrastructure.', link: 'https://docs.oracle.com/en-us/iaas/Content/Notification/Tasks/managingtopicsandsubscriptions.htm', recommended_action: 'Create at least one notification topic with an active subscription.', apis: ['topics:list','subscriptions:list'], @@ -18,9 +18,7 @@ module.exports = { var regions = helpers.regions(settings.govcloud); async.each(regions.subscriptions, function(region, rcb) { - if (helpers.checkRegionSubscription(cache, source, results, region)) { - var topics = helpers.addSource(cache, source, ['topics', 'list', region]); @@ -49,9 +47,8 @@ module.exports = { var subscriptions = helpers.addSource(cache, source, ['subscriptions', 'list', region]); - if (!subscriptions) return rcb(); - if (subscriptions.err || !subscriptions.data) { + if (!subscriptions || subscriptions.err || !subscriptions.data) { helpers.addResult(results, 3, 'Unable to query for subscriptions: ' + helpers.addError(subscriptions), region); return rcb(); @@ -79,50 +76,3 @@ module.exports = { }); } }; - -// async.each(regions.subscriptions, function (region, rcb) { - -// if (helpers.checkRegionSubscription(cache, source, results, region)) { - -// var topics = helpers.addSource(cache, source, -// ['topics', 'list', region]); - -// if (!topics) return rcb(); - -// if (topics.err || !topics.data) { -// helpers.addResult(results, 3, -// 'Unable to query for topics: ' + helpers.addError(topics), region); -// } -// if (!topics.data.length) { -// helpers.addResult(results, 2, 'No topics found in the region', region); -// } - -// var subscriptions = helpers.addSource(cache, source, -// ['subscriptions', 'list', region]); - -// if (!subscriptions) return rcb(); - -// if (subscriptions.err || !subscriptions.data) { -// helpers.addResult(results, 3, -// 'Unable to query for osubscriptions: ' + helpers.addError(subscriptions), region); -// } -// if (!subscriptions.data.length) { -// helpers.addResult(results, 2, 'No subscriptions found in the region', region); -// } - -// const activeSubscription = subscriptions.data.find(subscription => -// subscription.lifecycleState && subscription.lifecycleState === 'ACTIVE' -// ); - -// if (activeSubscription) { -// helpers.addResult(results, 0, -// `There is at least one notification topic with an active subscription`, region); -// } else { -// helpers.addResult(results, 2, -// 'No notification topics with active subscriptions found'); -// } -// } -// rcb(); -// }, function () { -// callback(null, results, source); -// }); \ No newline at end of file From 4cc547a3f8f1be4586a7758a194c9eb672539d40 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 23:06:13 +0500 Subject: [PATCH 315/350] Apply suggestions from code review --- helpers/oracle/regions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/oracle/regions.js b/helpers/oracle/regions.js index aef308e2fb..a966212338 100644 --- a/helpers/oracle/regions.js +++ b/helpers/oracle/regions.js @@ -53,7 +53,7 @@ module.exports = { topics: regions, subscriptions: regions, policy: regions, - defaultTags: regions, + defaultTags: ['default'], subnet: regions, dbHome: regions, database: regions, From 131ceef87381c53a9fe7d0fee249564f0d69b0af Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 23:06:20 +0500 Subject: [PATCH 316/350] Update plugins/oracle/identity/defaultTagsForResources.js --- plugins/oracle/identity/defaultTagsForResources.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oracle/identity/defaultTagsForResources.js b/plugins/oracle/identity/defaultTagsForResources.js index a4878e9a28..a0f52ae77f 100644 --- a/plugins/oracle/identity/defaultTagsForResources.js +++ b/plugins/oracle/identity/defaultTagsForResources.js @@ -3,7 +3,7 @@ var helpers = require('../../../helpers/oracle'); module.exports = { title: 'Default Tags For Resources', category: 'Logging and Monitoring', - domain: 'Identity', + domain: 'Management and Governance', description: 'Ensures default tags are used on resources.', more_info: 'Having default tags like "CreatedBy" on resources help determine who created the resource in case of an accident.', link: 'https://docs.oracle.com/en-us/iaas/Content/Tagging/Tasks/managingtagdefaults.htm', From b4c44023a88caa8bfd25d7bd2e05e4ef490dae45 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sun, 26 Jun 2022 23:15:43 +0500 Subject: [PATCH 317/350] Apply suggestions from code review --- plugins/oracle/networking/inboundSecurityLists.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/oracle/networking/inboundSecurityLists.js b/plugins/oracle/networking/inboundSecurityLists.js index 4f8961815e..eab338e670 100644 --- a/plugins/oracle/networking/inboundSecurityLists.js +++ b/plugins/oracle/networking/inboundSecurityLists.js @@ -35,11 +35,11 @@ module.exports = { securityLists.data.forEach(securityList => { if (securityList.ingressSecurityRules && securityList.ingressSecurityRules.length) { helpers.addResult(results, 0, - `Security list has ingress rules configured`, region, securityList.displayName); + `Security list has ingress rules configured`, region, securityList.id); } else { helpers.addResult(results, 2, - `Security list does not have ingress rules configured`, region, securityList.displayName); + `Security list does not have ingress rules configured`, region, securityList.id); } From 4ea13f671ed0546e1e3b97b3417c73ecf7370b57 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Mon, 27 Jun 2022 00:39:42 +0500 Subject: [PATCH 318/350] Separate Results for Open All Ports Plugin --- helpers/google/functions.js | 15 ++++++--------- helpers/oracle/functions.js | 15 ++++++--------- .../networking/openAllPortsProtocols.spec.js | 1 - 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/helpers/google/functions.js b/helpers/google/functions.js index 90a0b2fb07..301b84fce2 100644 --- a/helpers/google/functions.js +++ b/helpers/google/functions.js @@ -147,7 +147,6 @@ function findOpenAllPorts(ngs, location, results, cache, source) { } var project = projects.data[0].name; - let found = false; let protocols = {'tcp': '*', 'udp' : '*'}; for (let sgroups of ngs) { let strings = []; @@ -174,12 +173,10 @@ function findOpenAllPorts(ngs, location, results, cache, source) { if (parseInt(startPort) === 0 && parseInt(endPort) === 65535) { var string = 'all ports open to the public'; if (strings.indexOf(string) === -1) strings.push(string); - found = true; } } else if (portRange === 'all') { var string = 'all ports open to the public'; if (strings.indexOf(string) === -1) strings.push(string); - found = true; } }); } @@ -190,8 +187,6 @@ function findOpenAllPorts(ngs, location, results, cache, source) { (sourceAddressPrefix.includes('*') || sourceAddressPrefix.includes('') || sourceAddressPrefix.includes('0.0.0.0/0') || sourceAddressPrefix.includes('/0') || sourceAddressPrefix.includes('/0') || sourceAddressPrefix.includes('internet'))) { var string = 'all ports open to the public'; if (strings.indexOf(string) === -1) strings.push(string); - found = true; - } } } @@ -202,10 +197,12 @@ function findOpenAllPorts(ngs, location, results, cache, source) { ') has ' + strings.join(' and '), location, resource); } - } - - if (!found) { - shared.addResult(results, 0, 'No public open ports found', location); + else { + shared.addResult(results, 0, + 'Firewall Rule:(' + sgroups.name + + ') does not have all ports open to the public', location, + resource); + } } } diff --git a/helpers/oracle/functions.js b/helpers/oracle/functions.js index ed65ac7e4b..d3d92b8806 100644 --- a/helpers/oracle/functions.js +++ b/helpers/oracle/functions.js @@ -222,7 +222,6 @@ function findOpenPorts(groups, ports, service, region, results, isSecurityRule, } function findOpenPortsAll(groups, ports, service, region, results) { - var found = false; for (g in groups) { var messages = []; var sgroups = groups[g]; @@ -239,7 +238,6 @@ function findOpenPortsAll(groups, ports, service, region, results) { permission.source === '0.0.0.0/0') { message = 'all protocols open to 0.0.0.0/0'; if (messages.indexOf(message) === -1) messages.push(message); - found = true; } else if (permission.source && permission.source === '0.0.0.0/0' && @@ -250,7 +248,6 @@ function findOpenPortsAll(groups, ports, service, region, results) { !permission.tcpOptions.destinationPortRange))) { message = `all ${ipProtocol.tcp.name} ports open to 0.0.0.0/0`; if (messages.indexOf(message) === -1) messages.push(message); - found = true; } else if (permission.source && permission.source === '0.0.0.0/0' && @@ -261,7 +258,6 @@ function findOpenPortsAll(groups, ports, service, region, results) { !permission.udpOptions.destinationPortRange))) { message = `all ${ipProtocol.udp.name} ports open to 0.0.0.0/0`; if (messages.indexOf(message) === -1) messages.push(message); - found = true; } } @@ -271,12 +267,13 @@ function findOpenPortsAll(groups, ports, service, region, results) { ' has ' + service + ': ' + messages.join(' and '), region, resource); } + else { + shared.addResult(results, 0, + 'The Security List: ' + sgroups.displayName + + ' does not have all ports open to the public', region, + resource); + } } - - if (!found) { - shared.addResult(results, 0, 'No public open ports found', region); - } - } function checkRegionSubscription (cache, source, results, region) { diff --git a/plugins/oracle/networking/openAllPortsProtocols.spec.js b/plugins/oracle/networking/openAllPortsProtocols.spec.js index 52f1146ecd..458f689ec1 100644 --- a/plugins/oracle/networking/openAllPortsProtocols.spec.js +++ b/plugins/oracle/networking/openAllPortsProtocols.spec.js @@ -178,7 +178,6 @@ describe('openAllPortsProtocols', function () { const callback = (err, results) => { expect(results.length).to.be.above(0) expect(results[0].status).to.equal(0) - expect(results[0].message).to.include('No public open ports found') expect(results[0].region).to.equal('us-ashburn-1') done() }; From 2a8a2758cec38206a95fbe49390e5a006de43863 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Mon, 27 Jun 2022 03:35:38 +0500 Subject: [PATCH 319/350] OCI - OKE Security Groups Plugin --- exports.js | 1 + plugins/oracle/oke/okeSecurityGroups.js | 116 +++++++++ plugins/oracle/oke/okeSecurityGroups.spec.js | 250 +++++++++++++++++++ 3 files changed, 367 insertions(+) create mode 100644 plugins/oracle/oke/okeSecurityGroups.js create mode 100644 plugins/oracle/oke/okeSecurityGroups.spec.js diff --git a/exports.js b/exports.js index 63e8ed91b1..c7d33a4f9f 100644 --- a/exports.js +++ b/exports.js @@ -909,6 +909,7 @@ module.exports = { 'okePrivateEndpoint' : require(__dirname + '/plugins/oracle/oke/okePrivateEndpoint.js'), 'okeSecretsEncrypted' : require(__dirname + '/plugins/oracle/oke/okeSecretsEncrypted.js'), + 'okeSecurityGroups' : require(__dirname + '/plugins/oracle/oke/okeSecurityGroups.js'), }, google: { 'excessiveFirewallRules' : require(__dirname + '/plugins/google/vpcnetwork/excessiveFirewallRules.js'), diff --git a/plugins/oracle/oke/okeSecurityGroups.js b/plugins/oracle/oke/okeSecurityGroups.js new file mode 100644 index 0000000000..d8eb1fd876 --- /dev/null +++ b/plugins/oracle/oke/okeSecurityGroups.js @@ -0,0 +1,116 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'OKE Security Groups', + category: 'OKE', + domain: 'Containers', + description: 'Ensures the OKE clusters only allows inbound traffic on port 443.', + more_info: 'The OKE clusters only requires port 443 access. Security groups for the clusters should not add additional port access.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Security/Reference/oke_security.htm', + recommended_action: 'Configure security groups for the OKE clusters to allow access only on port 443.', + apis: ['vcn:list', 'cluster:list', 'networkSecurityGroup:list', 'securityRule:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.cluster, function(region, rcb){ + + if (helpers.checkRegionSubscription(cache, source, results, region)) { + + var clusters = helpers.addSource(cache, source, + ['cluster', 'list', region]); + + if (!clusters) return rcb(); + + if (clusters.err || !clusters.data) { + helpers.addResult(results, 3, + 'Unable to query for OKE clusters: ' + helpers.addError(clusters), region); + return rcb(); + } + + if (!clusters.data.length) { + helpers.addResult(results, 0, 'No OKE clusters found', region); + return rcb(); + } + + var securityGroups = helpers.addSource(cache, source, + ['networkSecurityGroup', 'list', region]); + + if (!securityGroups || securityGroups.err || !securityGroups.data) { + helpers.addResult(results, 3, + 'Unable to query for network security groups: ' + helpers.addError(securityGroups), region); + return rcb(); + + } + + var securityRules = helpers.addSource(cache, source, + ['securityRule', 'list', region]); + + if (!securityRules || securityRules.err || !securityRules.data) { + helpers.addResult(results, 3, + 'Unable to query for security rules: ' + helpers.addError(securityRules), region); + return rcb(); + + } + + securityGroups.data.forEach(securityGroup => { + if (securityRules && securityRules.data.find(securityRule => securityRule.networkSecurityGroups === securityGroup.id)) { + securityGroup.securityRules = securityRules.data.filter(securityRule => securityRule.networkSecurityGroups === securityGroup.id); + } + }); + + clusters.data.forEach(cluster => { + if (!cluster.vcnId) return; + + var allowsOtherPorts = false; + const clusterSecurityGroups = securityGroups.data.filter(securityGroup => securityGroup.vcnId === cluster.vcnId); + + clusterSecurityGroups.forEach(group => { + + if (!group.securityRules || !group.securityRules.length) { + allowsOtherPorts = true; + return; + } + + if (group.securityRules) { + group.securityRules.map(rule => { + if (rule.direction === 'INGRESS') { + var ruleOptions = rule.tcpOptions || rule.udpOptions; + if (!ruleOptions) { + allowsOtherPorts = true; + } else if (ruleOptions.sourcePortRange + && ruleOptions.sourcePortRange.max && ruleOptions.sourcePortRange.max != 443 + && ruleOptions.sourcePortRange.minf && ruleOptions.sourcePortRange.minf != 443 + && ruleOptions.destinationPortRange + && ruleOptions.destinationPortRange.max && ruleOptions.destinationPortRange.max != 443 + && ruleOptions.destinationPortRange.minf && ruleOptions.destinationPortRange.minf != 443 + ) { + allowsOtherPorts = true; + } + } + } + ); + } + }); + + if (allowsOtherPorts) { + helpers.addResult(results, 2, 'OKE cluster security groups allow additional access on unnecessary ports', region, cluster.id); + } else { + helpers.addResult(results, 0, 'OKE cluster security groups do not allow additional access on unnecessary ports', region, cluster.id); + } + }); + } + + rcb(); + }, function(){ + // Global checking goes here + callback(null, results, source); + }); + } +}; + + + \ No newline at end of file diff --git a/plugins/oracle/oke/okeSecurityGroups.spec.js b/plugins/oracle/oke/okeSecurityGroups.spec.js new file mode 100644 index 0000000000..3663451e1d --- /dev/null +++ b/plugins/oracle/oke/okeSecurityGroups.spec.js @@ -0,0 +1,250 @@ +var expect = require('chai').expect; +var plugin = require('./okeSecurityGroups'); + +const clusters = [ + { + id: 'ocid1.cluster.oc1', + name: 'cluster1', + compartmentId: 'ocid1.tenancy.oc1.aaa111111', + endpointConfig: { + subnetId: 'ocid1.subnet.oc1.aaaaa', + isPublicIpEnabled: false + }, + vcnId: 'ocid1.vcn.oc1.vcn-1', + kubernetesVersion: 'v1.22.5' + } +] +const securityRules = [ + { + direction: 'INGRESS', + id: '1111', + isStateless: false, + isValid: true, + protocol: '6', + source: 'ocid1.networksecuritygroup.oc1.nsg-1', + sourceType: 'NETWORK_SECURITY_GROUP', + tcpOptions: { + destinationPortRange: { max: 443, min: 443 }, + sourcePortRange: { max: 443, min: 443 } + }, + timeCreated: '2022-06-26T22:08:03.792Z', + networkSecurityGroups: 'ocid1.networksecuritygroup.oc1.nsg-1' + }, + { + direction: 'INGRESS', + id: '111', + isStateless: false, + isValid: true, + protocol: 'all', + source: 'ocid1.networksecuritygroup.oc1.nsg-1', + sourceType: 'NETWORK_SECURITY_GROUP', + timeCreated: '2022-06-26T22:09:22.114Z', + networkSecurityGroups: 'ocid1.networksecuritygroup.oc1.nsg-1' + } + +]; + +const securityGroups = [ + { + compartmentId: 'ocid1.tenancy.oc1.11111', + displayName: 'firstgroup', + freeformTags: {}, + id: 'ocid1.networksecuritygroup.oc1.nsg-1', + lifecycleState: 'AVAILABLE', + timeCreated: '2022-01-09T13:03:47.999Z', + vcnId: 'ocid1.vcn.oc1.vcn-1' + } +] + +const createCache = (data, err, securityGroupData, securityGroupErr, securityRuleData, securityRuleErr) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + cluster: { + list: { + 'us-ashburn-1': { + err: err, + data: data + } + } + }, + networkSecurityGroup: { + list: { + 'us-ashburn-1': { + err: securityGroupErr, + data: securityGroupData + } + } + }, + securityRule: { + list: { + 'us-ashburn-1': { + err: securityRuleErr, + data: securityRuleData + } + } + } + } +}; + +describe('okeSecurityGroups', function () { + describe('run', function () { + + it('should give unknown result if a cluster error occurs', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for OKE clusters') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + ['error'], + securityGroups, + null, + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if no oke clusters are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No OKE clusters found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + [], + null, + null, + securityGroups, + null, + securityRules, + null + + ); + + plugin.run(cache, {}, callback); + }) + + + it('should give unknown result if a security rule error occurs', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for security rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + clusters, + null, + securityGroups, + null, + null, + ['error'] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give unknown result if a security group error occurs', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for network security groups') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + clusters, + null, + null, + ['error'], + securityRules, + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if oke cluster security groups allow acces on unnecessary port ranges', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('OKE cluster security groups allow additional access on unnecessary ports') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + clusters, + null, + securityGroups, + null, + securityRules, + null + + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if oke cluster security groups do not allow acces on unnecessary port ranges', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('do not allow additional access on unnecessary ports') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + clusters, + null, + securityGroups, + null, + [securityRules[0]], + null + + ); + + plugin.run(cache, {}, callback); + }) + + + }) +}) \ No newline at end of file From a8d15555378e99ea90a5f2dc8b0e5843e7b7a8f1 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Tue, 5 Jul 2022 04:28:23 +0500 Subject: [PATCH 320/350] OCI - Event Rules Plugins --- collectors/oracle/collector.js | 8 + exports.js | 10 + helpers/oracle/functions.js | 37 +++- helpers/oracle/regions.js | 1 + other_modules/oci/services.json | 14 ++ plugins/oracle/identity/iamGroupChanges.js | 51 ++++++ .../oracle/identity/iamGroupChanges.spec.js | 165 +++++++++++++++++ plugins/oracle/identity/iamPolicyChanges.js | 51 ++++++ .../oracle/identity/iamPolicyChanges.spec.js | 165 +++++++++++++++++ .../identity/identityProviderChanges.js | 51 ++++++ .../identity/identityProviderChanges.spec.js | 165 +++++++++++++++++ .../oracle/identity/idpGroupMappingChanges.js | 51 ++++++ .../identity/idpGroupMappingChanges.spec.js | 165 +++++++++++++++++ plugins/oracle/identity/userChanges.js | 53 ++++++ plugins/oracle/identity/userChanges.spec.js | 165 +++++++++++++++++ .../networking/networkGatewayChanges.js | 74 ++++++++ .../networking/networkGatewayChanges.spec.js | 171 ++++++++++++++++++ .../oracle/networking/routeTableChanges.js | 52 ++++++ .../networking/routeTableChanges.spec.js | 165 +++++++++++++++++ .../oracle/networking/securityGroupChanges.js | 52 ++++++ .../networking/securityGroupChanges.spec.js | 165 +++++++++++++++++ .../oracle/networking/securityListChanges.js | 52 ++++++ .../networking/securityListChanges.spec.js | 165 +++++++++++++++++ plugins/oracle/networking/vcnChanges.js | 51 ++++++ plugins/oracle/networking/vcnChanges.spec.js | 165 +++++++++++++++++ 25 files changed, 2263 insertions(+), 1 deletion(-) create mode 100644 plugins/oracle/identity/iamGroupChanges.js create mode 100644 plugins/oracle/identity/iamGroupChanges.spec.js create mode 100644 plugins/oracle/identity/iamPolicyChanges.js create mode 100644 plugins/oracle/identity/iamPolicyChanges.spec.js create mode 100644 plugins/oracle/identity/identityProviderChanges.js create mode 100644 plugins/oracle/identity/identityProviderChanges.spec.js create mode 100644 plugins/oracle/identity/idpGroupMappingChanges.js create mode 100644 plugins/oracle/identity/idpGroupMappingChanges.spec.js create mode 100644 plugins/oracle/identity/userChanges.js create mode 100644 plugins/oracle/identity/userChanges.spec.js create mode 100644 plugins/oracle/networking/networkGatewayChanges.js create mode 100644 plugins/oracle/networking/networkGatewayChanges.spec.js create mode 100644 plugins/oracle/networking/routeTableChanges.js create mode 100644 plugins/oracle/networking/routeTableChanges.spec.js create mode 100644 plugins/oracle/networking/securityGroupChanges.js create mode 100644 plugins/oracle/networking/securityGroupChanges.spec.js create mode 100644 plugins/oracle/networking/securityListChanges.js create mode 100644 plugins/oracle/networking/securityListChanges.spec.js create mode 100644 plugins/oracle/networking/vcnChanges.js create mode 100644 plugins/oracle/networking/vcnChanges.spec.js diff --git a/collectors/oracle/collector.js b/collectors/oracle/collector.js index 4c3a0df0d3..725655430f 100644 --- a/collectors/oracle/collector.js +++ b/collectors/oracle/collector.js @@ -156,6 +156,14 @@ var calls = { filterValue: ['compartmentId'], } }, + rules: { + list: { + api: 'events', + restVersion: '/20181201', + filterKey: ['compartmentId'], + filterValue: ['compartmentId'], + } + }, topics: { list: { api: 'notification', diff --git a/exports.js b/exports.js index c7d33a4f9f..7ff32ef25a 100644 --- a/exports.js +++ b/exports.js @@ -845,6 +845,11 @@ module.exports = { 'usersPasswordLastUsed' : require(__dirname + '/plugins/oracle/identity/usersPasswordLastUsed.js'), 'defaultTagsForResources' : require(__dirname + '/plugins/oracle/identity/defaultTagsForResources.js'), 'notificationTopicSubscription' : require(__dirname + '/plugins/oracle/identity/notificationTopicSubscription.js'), + 'identityProviderChanges' : require(__dirname + '/plugins/oracle/identity/identityProviderChanges.js'), + 'idpGroupMappingChanges' : require(__dirname + '/plugins/oracle/identity/idpGroupMappingChanges.js'), + 'iamGroupChanges' : require(__dirname + '/plugins/oracle/identity/iamGroupChanges.js'), + 'iamPolicyChanges' : require(__dirname + '/plugins/oracle/identity/iamPolicyChanges.js'), + 'userChanges' : require(__dirname + '/plugins/oracle/identity/userChanges.js'), 'openSSH' : require(__dirname + '/plugins/oracle/networking/openSSH.js'), 'openOracleAutoDataWarehouse' : require(__dirname + '/plugins/oracle/networking/openOracleAutoDataWarehouse.js'), @@ -869,6 +874,11 @@ module.exports = { 'openKibana' : require(__dirname + '/plugins/oracle/networking/openKibana.js'), 'openSalt' : require(__dirname + '/plugins/oracle/networking/openSalt.js'), 'openSMTP' : require(__dirname + '/plugins/oracle/networking/openSMTP.js'), + 'vcnChanges' : require(__dirname + '/plugins/oracle/networking/vcnChanges.js'), + 'routeTableChanges' : require(__dirname + '/plugins/oracle/networking/routeTableChanges.js'), + 'securityListChanges' : require(__dirname + '/plugins/oracle/networking/securityListChanges.js'), + 'securityGroupChanges' : require(__dirname + '/plugins/oracle/networking/securityGroupChanges.js'), + 'networkGatewayChanges' : require(__dirname + '/plugins/oracle/networking/networkGatewayChanges.js'), 'statelessSecurityRules' : require(__dirname + '/plugins/oracle/networking/statelessSecurityRules.js'), 'defaultSecurityList' : require(__dirname + '/plugins/oracle/networking/defaultSecurityList.js'), diff --git a/helpers/oracle/functions.js b/helpers/oracle/functions.js index 5ca4ff35f5..6780a2fded 100644 --- a/helpers/oracle/functions.js +++ b/helpers/oracle/functions.js @@ -289,7 +289,41 @@ function findOpenPortsAll(groups, ports, service, region, results) { if (!found) { shared.addResult(results, 0, 'No public open ports found', region); } +} +function checkEventRules(rules, eventsToCheck, displayName, compartment, region, results) { + let enabledRules = []; + let rulesFound = false; + rules.map(rule => { + if (rule.lifecycleState === 'ACTIVE' && rule.isEnabled && rule.condition) { + try { + const conditions = JSON.parse(rule.condition); + if (conditions && conditions.eventType && conditions.eventType.length) { + enabledRules = [...enabledRules, ...conditions.eventType]; + } + } + catch (err) { + return []; + } + } + }); + rulesFound = eventsToCheck.every(event => enabledRules.includes(event.value)); + let activeRules = []; + let inactiveRules = []; + if (!rulesFound) { + activeRules = eventsToCheck.filter(event => enabledRules.includes(event.value)).map(rule => rule.displayName); + inactiveRules = eventsToCheck.filter(event => !enabledRules.includes(event.value)).map(rule => rule.displayName); + } + + if (!rulesFound && !activeRules.length) { + shared.addResult(results, 2, `No event rules are configured for ${displayName} changes`, region, compartment); + } + else if (!rulesFound && inactiveRules.length) { + shared.addResult(results, 2, `Event rules are missing for ${displayName} ${inactiveRules.join(', ')} events`, region, compartment); + } + else if (rulesFound) { + shared.addResult(results, 0, `Event rules are configured for all ${displayName} changes`, region, compartment); + } } function checkRegionSubscription (cache, source, results, region) { @@ -397,5 +431,6 @@ module.exports = { normalizePolicyStatement: normalizePolicyStatement, testStatement: testStatement, getProtectionLevel: getProtectionLevel, - listToObj: listToObj + listToObj: listToObj, + checkEventRules: checkEventRules }; diff --git a/helpers/oracle/regions.js b/helpers/oracle/regions.js index 4e10c3b37b..1d1c28f678 100644 --- a/helpers/oracle/regions.js +++ b/helpers/oracle/regions.js @@ -51,6 +51,7 @@ module.exports = { compartment: regions, bucket: regions, waasPolicy: regions, + rules: regions, topics: regions, subscriptions: regions, policy: regions, diff --git a/other_modules/oci/services.json b/other_modules/oci/services.json index f578bb7c6d..52bafe9f5c 100644 --- a/other_modules/oci/services.json +++ b/other_modules/oci/services.json @@ -74,6 +74,20 @@ } } }, + "events": { + "rules": { + "list": { + "allowedQueryStrings": [ + "compartmentId", + "limit", + "page" + ], + "method": "GET", + "path": "rules", + "endpoint": "events.{{region}}.oci.oraclecloud.com" + } + } + }, "core": { "instance": { "list": { diff --git a/plugins/oracle/identity/iamGroupChanges.js b/plugins/oracle/identity/iamGroupChanges.js new file mode 100644 index 0000000000..e62c9d1f72 --- /dev/null +++ b/plugins/oracle/identity/iamGroupChanges.js @@ -0,0 +1,51 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'IAM Group Changes', + category: 'Identity', + domain: 'Management and Governance', + description: 'Ensure an event rule is configured for IAM Group changes.', + more_info: 'Monitoring changes to IAM groups like create, update and delete will help in identifying changes to satisfy least privilege principle.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', + recommended_action: 'Configure an event rule for IAM Group changes like create, update and delete.', + apis: ['rules:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.rules, function(region, rcb) { + if (helpers.checkRegionSubscription(cache, source, results, region)) { + var rules = helpers.addSource(cache, source, + ['rules', 'list', region]); + + if (!rules) return rcb(); + + if (rules.err || !rules.data) { + helpers.addResult(results, 3, + 'Unable to query for rules: ' + helpers.addError(rules), region); + return rcb(); + } + if (!rules.data.length) { + helpers.addResult(results, 2, 'No rules found', region); + return rcb(); + } + + const compartment = rules.data[0].compartmentId; + const eventsToCheck = [ + { displayName: 'Create', value: 'com.oraclecloud.identitycontrolplane.creategroup' }, + { displayName: 'Update', value: 'com.oraclecloud.identitycontrolplane.updategroup' }, + { displayName: 'Delete', value: 'com.oraclecloud.identitycontrolplane.deletegroup' } + ]; + + helpers.checkEventRules(rules.data, eventsToCheck, 'IAM Group', compartment, region, results); + + } + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/identity/iamGroupChanges.spec.js b/plugins/oracle/identity/iamGroupChanges.spec.js new file mode 100644 index 0000000000..834e343d3c --- /dev/null +++ b/plugins/oracle/identity/iamGroupChanges.spec.js @@ -0,0 +1,165 @@ +var expect = require('chai').expect; +var plugin = require('./iamGroupChanges'); + +const rules = [ + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.identitycontrolplane.creategroup","com.oraclecloud.identitycontrolplane.updategroup","com.oraclecloud.identitycontrolplane.deletegroup"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.identitycontrolplane.creategroup"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.iad.abuwcljsa53hgf43hbifj3qmhewwgttyedhcngvbb3yyqqzgegtc4dpz2zca', + displayName: 'rule 2', + description: null, + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.objectstorage.createbucket"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-04T01:06:54.834Z' + } + +]; + + +const createCache = (err, rules) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + rules: { + list: { + 'us-ashburn-1': { + err: err, + data: rules + } + } + }, + } +}; + +describe('iamGroupChanges', function () { + describe('run', function () { + it('should give unknown result if unable to query for rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['err'], + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no rules found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No rules found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no IAM group rules are configured', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No event rules are configured for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[2]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if Event rules are missing for some IAM Group changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('Event rules are missing for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[1]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if event rules are configured for all IAM Group changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('Event rules are configured for all') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[0]] + ); + + plugin.run(cache, {}, callback); + }) + + + }); +}); \ No newline at end of file diff --git a/plugins/oracle/identity/iamPolicyChanges.js b/plugins/oracle/identity/iamPolicyChanges.js new file mode 100644 index 0000000000..7a24555edc --- /dev/null +++ b/plugins/oracle/identity/iamPolicyChanges.js @@ -0,0 +1,51 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'IAM Policy Changes', + category: 'Identity', + domain: 'Management and Governance', + description: 'Ensure an event rule is configured for IAM Policy changes.', + more_info: 'Monitoring changes to IAM policies like create, update and delete will help in identifying changes to the security posture.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', + recommended_action: 'Configure an event rule for IAM policy changes like create, update and delete.', + apis: ['rules:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.rules, function(region, rcb) { + if (helpers.checkRegionSubscription(cache, source, results, region)) { + var rules = helpers.addSource(cache, source, + ['rules', 'list', region]); + + if (!rules) return rcb(); + + if (rules.err || !rules.data) { + helpers.addResult(results, 3, + 'Unable to query for rules: ' + helpers.addError(rules), region); + return rcb(); + } + if (!rules.data.length) { + helpers.addResult(results, 2, 'No rules found', region); + return rcb(); + } + + const compartment = rules.data[0].compartmentId; + const eventsToCheck = [ + { displayName: 'Create', value: 'com.oraclecloud.identitycontrolplane.createpolicy' }, + { displayName: 'Update', value: 'com.oraclecloud.identitycontrolplane.updatepolicy' }, + { displayName: 'Delete', value: 'com.oraclecloud.identitycontrolplane.deletepolicy' } + ]; + + helpers.checkEventRules(rules.data, eventsToCheck, 'IAM Policy', compartment, region, results); + + } + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/identity/iamPolicyChanges.spec.js b/plugins/oracle/identity/iamPolicyChanges.spec.js new file mode 100644 index 0000000000..aa186b3211 --- /dev/null +++ b/plugins/oracle/identity/iamPolicyChanges.spec.js @@ -0,0 +1,165 @@ +var expect = require('chai').expect; +var plugin = require('./iamPolicyChanges'); + +const rules = [ + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.identitycontrolplane.createpolicy","com.oraclecloud.identitycontrolplane.updatepolicy","com.oraclecloud.identitycontrolplane.deletepolicy"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.identitycontrolplane.createpolicy"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.iad.abuwcljsa53hgf43hbifj3qmhewwgttyedhcngvbb3yyqqzgegtc4dpz2zca', + displayName: 'rule 2', + description: null, + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.objectstorage.createbucket"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-04T01:06:54.834Z' + } + +]; + + +const createCache = (err, rules) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + rules: { + list: { + 'us-ashburn-1': { + err: err, + data: rules + } + } + }, + } +}; + +describe('iamPolicyChanges', function () { + describe('run', function () { + it('should give unknown result if unable to query for rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['err'], + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no rules found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No rules found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no IAM Policy rules are configured', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No event rules are configured for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[2]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if Event rules are missing for some IAM Policy changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('Event rules are missing for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[1]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if event rules are configured for all IAM Policy changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('Event rules are configured for all') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[0]] + ); + + plugin.run(cache, {}, callback); + }) + + + }); +}); \ No newline at end of file diff --git a/plugins/oracle/identity/identityProviderChanges.js b/plugins/oracle/identity/identityProviderChanges.js new file mode 100644 index 0000000000..107c544f1d --- /dev/null +++ b/plugins/oracle/identity/identityProviderChanges.js @@ -0,0 +1,51 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Identity Provider Changes', + category: 'Identity', + domain: 'Management and Governance', + description: 'Ensure an event rule is configured for Identity Provider changes.', + more_info: 'Monitoring Identity Provider changes like create, update and delete will help in identifying changes to the security posture.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', + recommended_action: 'Configure an event rule for Identity Provider changes like create, update and delete.', + apis: ['rules:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.rules, function(region, rcb) { + if (helpers.checkRegionSubscription(cache, source, results, region)) { + var rules = helpers.addSource(cache, source, + ['rules', 'list', region]); + + if (!rules) return rcb(); + + if (rules.err || !rules.data) { + helpers.addResult(results, 3, + 'Unable to query for rules: ' + helpers.addError(rules), region); + return rcb(); + } + if (!rules.data.length) { + helpers.addResult(results, 2, 'No rules found', region); + return rcb(); + } + + const compartment = rules.data[0].compartmentId; + const eventsToCheck = [ + { displayName: 'Create', value: 'com.oraclecloud.identitycontrolplane.createidentityprovider' }, + { displayName: 'Update', value: 'com.oraclecloud.identitycontrolplane.updateidentityprovider' }, + { displayName: 'Delete', value: 'com.oraclecloud.identitycontrolplane.deleteidentityprovider' } + ]; + + helpers.checkEventRules(rules.data, eventsToCheck, 'Identity Provider', compartment, region, results); + + } + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/identity/identityProviderChanges.spec.js b/plugins/oracle/identity/identityProviderChanges.spec.js new file mode 100644 index 0000000000..e48eab970a --- /dev/null +++ b/plugins/oracle/identity/identityProviderChanges.spec.js @@ -0,0 +1,165 @@ +var expect = require('chai').expect; +var plugin = require('./identityProviderChanges'); + +const rules = [ + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.identitycontrolplane.createidentityprovider","com.oraclecloud.identitycontrolplane.updateidentityprovider","com.oraclecloud.identitycontrolplane.deleteidentityprovider"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.identitycontrolplane.deleteidentityprovider"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.iad.abuwcljsa53hgf43hbifj3qmhewwgttyedhcngvbb3yyqqzgegtc4dpz2zca', + displayName: 'rule 2', + description: null, + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.objectstorage.createbucket"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-04T01:06:54.834Z' + } + +]; + + +const createCache = (err, rules) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + rules: { + list: { + 'us-ashburn-1': { + err: err, + data: rules + } + } + }, + } +}; + +describe('identityProviderChanges', function () { + describe('run', function () { + it('should give unknown result if unable to query for rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['err'], + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no rules found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No rules found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no identity provider rules are configured', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No event rules are configured for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[2]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if Event rules are missing for some identity provider changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('Event rules are missing for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[1]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if event rules are configured for all identity provider changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('Event rules are configured for all') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[0]] + ); + + plugin.run(cache, {}, callback); + }) + + + }); +}); \ No newline at end of file diff --git a/plugins/oracle/identity/idpGroupMappingChanges.js b/plugins/oracle/identity/idpGroupMappingChanges.js new file mode 100644 index 0000000000..231024cbe2 --- /dev/null +++ b/plugins/oracle/identity/idpGroupMappingChanges.js @@ -0,0 +1,51 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Idp Group Mapping Changes', + category: 'Identity', + domain: 'Management and Governance', + description: 'Ensure an event rule is configured for Idp Group Mapping changes.', + more_info: 'Monitoring changes to Identity Provider Group Mappings like create, update and delete will help in identifying changes to the security posture.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', + recommended_action: 'Configure an event rule for Idp Group Mapping changes like create, update and delete.', + apis: ['rules:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.rules, function(region, rcb) { + if (helpers.checkRegionSubscription(cache, source, results, region)) { + var rules = helpers.addSource(cache, source, + ['rules', 'list', region]); + + if (!rules) return rcb(); + + if (rules.err || !rules.data) { + helpers.addResult(results, 3, + 'Unable to query for rules: ' + helpers.addError(rules), region); + return rcb(); + } + if (!rules.data.length) { + helpers.addResult(results, 2, 'No rules found', region); + return rcb(); + } + + const compartment = rules.data[0].compartmentId; + const eventsToCheck = [ + { displayName: 'Create', value: 'com.oraclecloud.identitycontrolplane.createidpgroupmapping' }, + { displayName: 'Update', value: 'com.oraclecloud.identitycontrolplane.updateidpgroupmapping' }, + { displayName: 'Delete', value: 'com.oraclecloud.identitycontrolplane.deleteidpgroupmapping' } + ]; + + helpers.checkEventRules(rules.data, eventsToCheck, 'Idp Group Mapping', compartment, region, results); + + } + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/identity/idpGroupMappingChanges.spec.js b/plugins/oracle/identity/idpGroupMappingChanges.spec.js new file mode 100644 index 0000000000..25a8ee64d8 --- /dev/null +++ b/plugins/oracle/identity/idpGroupMappingChanges.spec.js @@ -0,0 +1,165 @@ +var expect = require('chai').expect; +var plugin = require('./idpGroupMappingChanges'); + +const rules = [ + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.identitycontrolplane.createidpgroupmapping","com.oraclecloud.identitycontrolplane.updateidpgroupmapping","com.oraclecloud.identitycontrolplane.deleteidpgroupmapping"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.identitycontrolplane.createidpgroupmapping"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.iad.abuwcljsa53hgf43hbifj3qmhewwgttyedhcngvbb3yyqqzgegtc4dpz2zca', + displayName: 'rule 2', + description: null, + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.objectstorage.createbucket"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-04T01:06:54.834Z' + } + +]; + + +const createCache = (err, rules) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + rules: { + list: { + 'us-ashburn-1': { + err: err, + data: rules + } + } + }, + } +}; + +describe('idpGroupMappingChanges', function () { + describe('run', function () { + it('should give unknown result if unable to query for rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['err'], + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no rules found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No rules found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no idp group mapping rules are configured', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No event rules are configured for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[2]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if Event rules are missing for some idp group mapping changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('Event rules are missing for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[1]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if event rules are configured for all idp group mapping changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('Event rules are configured for all') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[0]] + ); + + plugin.run(cache, {}, callback); + }) + + + }); +}); \ No newline at end of file diff --git a/plugins/oracle/identity/userChanges.js b/plugins/oracle/identity/userChanges.js new file mode 100644 index 0000000000..1c56a7e553 --- /dev/null +++ b/plugins/oracle/identity/userChanges.js @@ -0,0 +1,53 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'User Changes', + category: 'Identity', + domain: 'Management and Governance', + description: 'Ensure an event rule is configured for User changes.', + more_info: 'Monitoring changes to users and their states and capabilities will help in identifying changes to the security posture.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', + recommended_action: 'Configure an event rule for changes to users and their states and capabilities.', + apis: ['rules:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.rules, function(region, rcb) { + if (helpers.checkRegionSubscription(cache, source, results, region)) { + var rules = helpers.addSource(cache, source, + ['rules', 'list', region]); + + if (!rules) return rcb(); + + if (rules.err || !rules.data) { + helpers.addResult(results, 3, + 'Unable to query for rules: ' + helpers.addError(rules), region); + return rcb(); + } + if (!rules.data.length) { + helpers.addResult(results, 2, 'No rules found', region); + return rcb(); + } + + const compartment = rules.data[0].compartmentId; + const eventsToCheck = [ + { displayName: 'Create', value: 'com.oraclecloud.identitycontrolplane.createuser' }, + { displayName: 'Update', value: 'com.oraclecloud.identitycontrolplane.updateuser' }, + { displayName: 'Delete', value: 'com.oraclecloud.identitycontrolplane.deleteuser' }, + { displayName: 'Update User State', value: 'com.oraclecloud.identitycontrolplane.updateuserstate' }, + { displayName: 'Update User Capabilities', value: 'com.oraclecloud.identitycontrolplane.updateusercapabilities' } + ]; + + helpers.checkEventRules(rules.data, eventsToCheck, 'User', compartment, region, results); + + } + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/identity/userChanges.spec.js b/plugins/oracle/identity/userChanges.spec.js new file mode 100644 index 0000000000..f47f69e3ef --- /dev/null +++ b/plugins/oracle/identity/userChanges.spec.js @@ -0,0 +1,165 @@ +var expect = require('chai').expect; +var plugin = require('./userChanges'); + +const rules = [ + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.identitycontrolplane.createuser","com.oraclecloud.identitycontrolplane.updateuser","com.oraclecloud.identitycontrolplane.deleteuser", "com.oraclecloud.identitycontrolplane.updateuserstate", "com.oraclecloud.identitycontrolplane.updateusercapabilities"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.identitycontrolplane.createuser","com.oraclecloud.identitycontrolplane.updateuser","com.oraclecloud.identitycontrolplane.deleteuser"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.iad.abuwcljsa53hgf43hbifj3qmhewwgttyedhcngvbb3yyqqzgegtc4dpz2zca', + displayName: 'rule 2', + description: null, + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.objectstorage.createbucket"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-04T01:06:54.834Z' + } + +]; + + +const createCache = (err, rules) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + rules: { + list: { + 'us-ashburn-1': { + err: err, + data: rules + } + } + }, + } +}; + +describe('userChanges', function () { + describe('run', function () { + it('should give unknown result if unable to query for rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['err'], + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no rules found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No rules found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no user rules are configured', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No event rules are configured for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[2]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if Event rules are missing for some user changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('Event rules are missing for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[1]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if event rules are configured for all user changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('Event rules are configured for all') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[0]] + ); + + plugin.run(cache, {}, callback); + }) + + + }); +}); \ No newline at end of file diff --git a/plugins/oracle/networking/networkGatewayChanges.js b/plugins/oracle/networking/networkGatewayChanges.js new file mode 100644 index 0000000000..90bc32c683 --- /dev/null +++ b/plugins/oracle/networking/networkGatewayChanges.js @@ -0,0 +1,74 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Network Gateway Changes', + category: 'Networking', + domain: 'Management and Governance', + description: 'Ensure an event rule is configured for network gateway changes.', + more_info: 'Monitoring changes to Network Gateways like create, update and delete will help in identifying changes to the security posture.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', + recommended_action: 'Configure an event rule for network gateway changes like create, update and delete.', + apis: ['rules:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.rules, function(region, rcb) { + if (helpers.checkRegionSubscription(cache, source, results, region)) { + var rules = helpers.addSource(cache, source, + ['rules', 'list', region]); + + if (!rules) return rcb(); + + if (rules.err || !rules.data) { + helpers.addResult(results, 3, + 'Unable to query for rules: ' + helpers.addError(rules), region); + return rcb(); + } + if (!rules.data.length) { + helpers.addResult(results, 2, 'No rules found', region); + return rcb(); + } + + const compartment = rules.data[0].compartmentId; + const eventsToCheck = [ + { displayName: 'Create DRG', value: 'com.oraclecloud.virtualnetwork.createdrg' }, + { displayName: 'Update DRG', value: 'com.oraclecloud.virtualnetwork.updatedrg' }, + { displayName: 'Delete DRG', value: 'com.oraclecloud.virtualnetwork.deletedrg' }, + { displayName: 'Create DRG Attachment', value: 'com.oraclecloud.virtualnetwork.createdrgattachment' }, + { displayName: 'Update DRG Attachment', value: 'com.oraclecloud.virtualnetwork.updatedrgattachment' }, + { displayName: 'Delete DRG Attachment', value: 'com.oraclecloud.virtualnetwork.deletedrgattachment' }, + { displayName: 'Create Internet Gateway', value: 'com.oraclecloud.virtualnetwork.createinternetgateway' }, + { displayName: 'Update Internet Gateway', value: 'com.oraclecloud.virtualnetwork.updateinternetgateway' }, + { displayName: 'Delete Internet Gateway', value: 'com.oraclecloud.virtualnetwork.deleteinternetgateway' }, + { displayName: 'Change Internet Gateway Compartment', value: 'com.oraclecloud.virtualnetwork.changeinternetgatewaycompartment' }, + { displayName: 'Create Local Peering Gateway', value: 'com.oraclecloud.virtualnetwork.createlocalpeeringgateway' }, + { displayName: 'Update Local Peering Gateway', value: 'com.oraclecloud.virtualnetwork.updatelocalpeeringgateway' }, + { displayName: 'Delete Local Peering Gateway - Begin', value: 'com.oraclecloud.virtualnetwork.deletelocalpeeringgateway.begin' }, + { displayName: 'Delete Local Peering Gateway - End', value: 'com.oraclecloud.virtualnetwork.deletelocalpeeringgateway.end' }, + { displayName: 'Change Local Peering Gateway Compartment', value: 'com.oraclecloud.virtualnetwork.changelocalpeeringgatewaycompartment' }, + { displayName: 'Create NAT Gateway', value: 'com.oraclecloud.natgateway.createnatgateway' }, + { displayName: 'Update NAT Gateway', value: 'com.oraclecloud.natgateway.updatenatgateway' }, + { displayName: 'Delete NAT Gateway', value: 'com.oraclecloud.natgateway.deletenatgateway' }, + { displayName: 'Change NAT Gateway Compartment', value: 'com.oraclecloud.natgateway.changenatgatewaycompartment' }, + { displayName: 'Attach Service Id', value: 'com.oraclecloud.servicegateway.attachserviceid' }, + { displayName: 'Detach Service Id', value: 'com.oraclecloud.servicegateway.detachserviceid' }, + { displayName: 'Create Service Gateway', value: 'com.oraclecloud.servicegateway.createservicegateway' }, + { displayName: 'Update Service Gateway', value: 'com.oraclecloud.servicegateway.updateservicegateway' }, + { displayName: 'Delete Service Gateway - Begin', value: 'com.oraclecloud.servicegateway.deleteservicegateway.begin' }, + { displayName: 'Delete Service Gateway - End', value: 'com.oraclecloud.servicegateway.deleteservicegateway.end' }, + { displayName: 'Change Service Gateway Compartment', value: 'com.oraclecloud.servicegateway.changeservicegatewaycompartment' }, + ]; + + helpers.checkEventRules(rules.data, eventsToCheck, 'Network Gateway', compartment, region, results); + + } + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/networking/networkGatewayChanges.spec.js b/plugins/oracle/networking/networkGatewayChanges.spec.js new file mode 100644 index 0000000000..c68c1a36fc --- /dev/null +++ b/plugins/oracle/networking/networkGatewayChanges.spec.js @@ -0,0 +1,171 @@ +var expect = require('chai').expect; +var plugin = require('./networkGatewayChanges'); + +const rules = [ + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: `{"eventType":["com.oraclecloud.virtualnetwork.createdrg","com.oraclecloud.virtualnetwork.updatedrg","com.oraclecloud.virtualnetwork.deletedrg", + "com.oraclecloud.virtualnetwork.createdrgattachment", "com.oraclecloud.virtualnetwork.updatedrgattachment", "com.oraclecloud.virtualnetwork.deletedrgattachment", + "com.oraclecloud.virtualnetwork.createinternetgateway", "com.oraclecloud.virtualnetwork.updateinternetgateway", "com.oraclecloud.virtualnetwork.deleteinternetgateway", "com.oraclecloud.virtualnetwork.changeinternetgatewaycompartment", + "com.oraclecloud.virtualnetwork.createlocalpeeringgateway", "com.oraclecloud.virtualnetwork.updatelocalpeeringgateway", "com.oraclecloud.virtualnetwork.deletelocalpeeringgateway.begin", "com.oraclecloud.virtualnetwork.deletelocalpeeringgateway.end", "com.oraclecloud.virtualnetwork.changelocalpeeringgatewaycompartment", + "com.oraclecloud.natgateway.createnatgateway", "com.oraclecloud.natgateway.updatenatgateway", "com.oraclecloud.natgateway.deletenatgateway", "com.oraclecloud.natgateway.changenatgatewaycompartment", + "com.oraclecloud.servicegateway.attachserviceid", "com.oraclecloud.servicegateway.detachserviceid", "com.oraclecloud.servicegateway.createservicegateway", "com.oraclecloud.servicegateway.updateservicegateway", "com.oraclecloud.servicegateway.deleteservicegateway.begin", "com.oraclecloud.servicegateway.deleteservicegateway.end", "com.oraclecloud.servicegateway.changeservicegatewaycompartment" + ],"data":{}}`, + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":[ "com.oraclecloud.virtualnetwork.createinternetgateway", "com.oraclecloud.virtualnetwork.updateinternetgateway", "com.oraclecloud.virtualnetwork.createinternetgateway"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.iad.abuwcljsa53hgf43hbifj3qmhewwgttyedhcngvbb3yyqqzgegtc4dpz2zca', + displayName: 'rule 2', + description: null, + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.objectstorage.createbucket"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-04T01:06:54.834Z' + } + +]; + + +const createCache = (err, rules) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + rules: { + list: { + 'us-ashburn-1': { + err: err, + data: rules + } + } + }, + } +}; + +describe('networkGatewayChanges', function () { + describe('run', function () { + it('should give unknown result if unable to query for rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['err'], + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no rules found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No rules found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no network gateway rules are configured', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No event rules are configured for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[2]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if Event rules are missing for some network gateway changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('Event rules are missing for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[1]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if event rules are configured for all network gateway changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('Event rules are configured for all') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[0]] + ); + + plugin.run(cache, {}, callback); + }) + + + }); +}); \ No newline at end of file diff --git a/plugins/oracle/networking/routeTableChanges.js b/plugins/oracle/networking/routeTableChanges.js new file mode 100644 index 0000000000..045d981490 --- /dev/null +++ b/plugins/oracle/networking/routeTableChanges.js @@ -0,0 +1,52 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Route Table Changes', + category: 'Networking', + domain: 'Management and Governance', + description: 'Ensure an event rule is configured for route table changes.', + more_info: 'Monitoring changes to route tables like create, update and delete will help in identifying changes to the traffic flows.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', + recommended_action: 'Configure an event rule for route table changes like create, update and delete.', + apis: ['rules:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.rules, function(region, rcb) { + if (helpers.checkRegionSubscription(cache, source, results, region)) { + var rules = helpers.addSource(cache, source, + ['rules', 'list', region]); + + if (!rules) return rcb(); + + if (rules.err || !rules.data) { + helpers.addResult(results, 3, + 'Unable to query for rules: ' + helpers.addError(rules), region); + return rcb(); + } + if (!rules.data.length) { + helpers.addResult(results, 2, 'No rules found', region); + return rcb(); + } + + const compartment = rules.data[0].compartmentId; + const eventsToCheck = [ + { displayName: 'Create', value: 'com.oraclecloud.virtualnetwork.createroutetable' }, + { displayName: 'Update', value: 'com.oraclecloud.virtualnetwork.updateroutetable' }, + { displayName: 'Delete', value: 'com.oraclecloud.virtualnetwork.deleteroutetable' }, + { displayName: 'Change Compartment', value: 'com.oraclecloud.virtualnetwork.changeroutetablecompartment'} + ]; + + helpers.checkEventRules(rules.data, eventsToCheck, 'Route Table', compartment, region, results); + + } + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/networking/routeTableChanges.spec.js b/plugins/oracle/networking/routeTableChanges.spec.js new file mode 100644 index 0000000000..da24820fd3 --- /dev/null +++ b/plugins/oracle/networking/routeTableChanges.spec.js @@ -0,0 +1,165 @@ +var expect = require('chai').expect; +var plugin = require('./routeTableChanges'); + +const rules = [ + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.virtualnetwork.createroutetable","com.oraclecloud.virtualnetwork.updateroutetable","com.oraclecloud.virtualnetwork.deleteroutetable", "com.oraclecloud.virtualnetwork.changeroutetablecompartment"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.virtualnetwork.createroutetable","com.oraclecloud.virtualnetwork.updateroutetable","com.oraclecloud.virtualnetwork.deleteroutetable"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.iad.abuwcljsa53hgf43hbifj3qmhewwgttyedhcngvbb3yyqqzgegtc4dpz2zca', + displayName: 'rule 2', + description: null, + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.objectstorage.createbucket"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-04T01:06:54.834Z' + } + +]; + + +const createCache = (err, rules) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + rules: { + list: { + 'us-ashburn-1': { + err: err, + data: rules + } + } + }, + } +}; + +describe('routeTableChanges', function () { + describe('run', function () { + it('should give unknown result if unable to query for rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['err'], + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no rules found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No rules found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no route table rules are configured', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No event rules are configured for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[2]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if Event rules are missing for some route table changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('Event rules are missing for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[1]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if event rules are configured for all route table changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('Event rules are configured for all') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[0]] + ); + + plugin.run(cache, {}, callback); + }) + + + }); +}); \ No newline at end of file diff --git a/plugins/oracle/networking/securityGroupChanges.js b/plugins/oracle/networking/securityGroupChanges.js new file mode 100644 index 0000000000..24ba58837f --- /dev/null +++ b/plugins/oracle/networking/securityGroupChanges.js @@ -0,0 +1,52 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Security Group Changes', + category: 'Networking', + domain: 'Management and Governance', + description: 'Ensure an event rule is configured for security group changes.', + more_info: 'Monitoring changes to security groups like create, update and delete will help in identifying changes to the security controls.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', + recommended_action: 'Configure an event rule for security group changes like create, update and delete.', + apis: ['rules:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.rules, function(region, rcb) { + if (helpers.checkRegionSubscription(cache, source, results, region)) { + var rules = helpers.addSource(cache, source, + ['rules', 'list', region]); + + if (!rules) return rcb(); + + if (rules.err || !rules.data) { + helpers.addResult(results, 3, + 'Unable to query for rules: ' + helpers.addError(rules), region); + return rcb(); + } + if (!rules.data.length) { + helpers.addResult(results, 2, 'No rules found', region); + return rcb(); + } + + const compartment = rules.data[0].compartmentId; + const eventsToCheck = [ + { displayName: 'Create', value: 'com.oraclecloud.virtualnetwork.createnetworksecuritygroup' }, + { displayName: 'Update', value: 'com.oraclecloud.virtualnetwork.updatenetworksecuritygroup' }, + { displayName: 'Delete', value: 'com.oraclecloud.virtualnetwork.deletenetworksecuritygroup' }, + { displayName: 'Change Compartment', value: 'com.oraclecloud.virtualnetwork.changenetworksecuritygroupcompartment'} + ]; + + helpers.checkEventRules(rules.data, eventsToCheck, 'Security Group', compartment, region, results); + + } + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/networking/securityGroupChanges.spec.js b/plugins/oracle/networking/securityGroupChanges.spec.js new file mode 100644 index 0000000000..75c23120ae --- /dev/null +++ b/plugins/oracle/networking/securityGroupChanges.spec.js @@ -0,0 +1,165 @@ +var expect = require('chai').expect; +var plugin = require('./securityGroupChanges'); + +const rules = [ + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.virtualnetwork.createnetworksecuritygroup","com.oraclecloud.virtualnetwork.updatenetworksecuritygroup","com.oraclecloud.virtualnetwork.deletenetworksecuritygroup", "com.oraclecloud.virtualnetwork.changenetworksecuritygroupcompartment"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.virtualnetwork.createnetworksecuritygroup","com.oraclecloud.virtualnetwork.updatenetworksecuritygroup","com.oraclecloud.virtualnetwork.deletenetworksecuritygroup"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.iad.abuwcljsa53hgf43hbifj3qmhewwgttyedhcngvbb3yyqqzgegtc4dpz2zca', + displayName: 'rule 2', + description: null, + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.objectstorage.createbucket"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-04T01:06:54.834Z' + } + +]; + + +const createCache = (err, rules) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + rules: { + list: { + 'us-ashburn-1': { + err: err, + data: rules + } + } + }, + } +}; + +describe('securityGroupChanges', function () { + describe('run', function () { + it('should give unknown result if unable to query for rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['err'], + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no rules found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No rules found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no security group rules are configured', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No event rules are configured for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[2]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if Event rules are missing for some security group changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('Event rules are missing for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[1]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if event rules are configured for all security group changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('Event rules are configured for all') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[0]] + ); + + plugin.run(cache, {}, callback); + }) + + + }); +}); \ No newline at end of file diff --git a/plugins/oracle/networking/securityListChanges.js b/plugins/oracle/networking/securityListChanges.js new file mode 100644 index 0000000000..e8d7a80e2f --- /dev/null +++ b/plugins/oracle/networking/securityListChanges.js @@ -0,0 +1,52 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Security List Changes', + category: 'Networking', + domain: 'Management and Governance', + description: 'Ensure an event rule is configured for security list changes.', + more_info: 'Monitoring changes to security lists like create, update and delete will help in identifying changes to the security controls.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', + recommended_action: 'Configure an event rule for security list changes like create, update and delete.', + apis: ['rules:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.rules, function(region, rcb) { + if (helpers.checkRegionSubscription(cache, source, results, region)) { + var rules = helpers.addSource(cache, source, + ['rules', 'list', region]); + + if (!rules) return rcb(); + + if (rules.err || !rules.data) { + helpers.addResult(results, 3, + 'Unable to query for rules: ' + helpers.addError(rules), region); + return rcb(); + } + if (!rules.data.length) { + helpers.addResult(results, 2, 'No rules found', region); + return rcb(); + } + + const compartment = rules.data[0].compartmentId; + const eventsToCheck = [ + { displayName: 'Create', value: 'com.oraclecloud.virtualnetwork.createsecuritylist' }, + { displayName: 'Update', value: 'com.oraclecloud.virtualnetwork.updatesecuritylist' }, + { displayName: 'Delete', value: 'com.oraclecloud.virtualnetwork.deletesecuritylist' }, + { displayName: 'Change Compartment', value: 'com.oraclecloud.virtualnetwork.changesecuritylistcompartment'} + ]; + + helpers.checkEventRules(rules.data, eventsToCheck, 'Security List', compartment, region, results); + + } + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/networking/securityListChanges.spec.js b/plugins/oracle/networking/securityListChanges.spec.js new file mode 100644 index 0000000000..dfd417a0c4 --- /dev/null +++ b/plugins/oracle/networking/securityListChanges.spec.js @@ -0,0 +1,165 @@ +var expect = require('chai').expect; +var plugin = require('./securityListChanges'); + +const rules = [ + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.virtualnetwork.createsecuritylist","com.oraclecloud.virtualnetwork.updatesecuritylist","com.oraclecloud.virtualnetwork.deletesecuritylist", "com.oraclecloud.virtualnetwork.changesecuritylistcompartment"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.virtualnetwork.createsecuritylist","com.oraclecloud.virtualnetwork.updatesecuritylist","com.oraclecloud.virtualnetwork.deletesecuritylist"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.iad.abuwcljsa53hgf43hbifj3qmhewwgttyedhcngvbb3yyqqzgegtc4dpz2zca', + displayName: 'rule 2', + description: null, + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.objectstorage.createbucket"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-04T01:06:54.834Z' + } + +]; + + +const createCache = (err, rules) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + rules: { + list: { + 'us-ashburn-1': { + err: err, + data: rules + } + } + }, + } +}; + +describe('securityListChanges', function () { + describe('run', function () { + it('should give unknown result if unable to query for rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['err'], + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no rules found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No rules found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no security list rules are configured', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No event rules are configured for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[2]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if Event rules are missing for some security list changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('Event rules are missing for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[1]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if event rules are configured for all security list changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('Event rules are configured for all') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[0]] + ); + + plugin.run(cache, {}, callback); + }) + + + }); +}); \ No newline at end of file diff --git a/plugins/oracle/networking/vcnChanges.js b/plugins/oracle/networking/vcnChanges.js new file mode 100644 index 0000000000..79d6febb7d --- /dev/null +++ b/plugins/oracle/networking/vcnChanges.js @@ -0,0 +1,51 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'VCN Changes', + category: 'Networking', + domain: 'Management and Governance', + description: 'Ensure an event rule is configured for VCN changes.', + more_info: 'Monitoring changes to VCNs will help in identifying changes to the security posture.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', + recommended_action: 'Configure an event rule for changes to VCNs like create, update and delete.', + apis: ['rules:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.rules, function(region, rcb) { + if (helpers.checkRegionSubscription(cache, source, results, region)) { + var rules = helpers.addSource(cache, source, + ['rules', 'list', region]); + + if (!rules) return rcb(); + + if (rules.err || !rules.data) { + helpers.addResult(results, 3, + 'Unable to query for rules: ' + helpers.addError(rules), region); + return rcb(); + } + if (!rules.data.length) { + helpers.addResult(results, 2, 'No rules found', region); + return rcb(); + } + + const compartment = rules.data[0].compartmentId; + const eventsToCheck = [ + { displayName: 'Create', value: 'com.oraclecloud.virtualnetwork.createvcn' }, + { displayName: 'Update', value: 'com.oraclecloud.virtualnetwork.updatevcn' }, + { displayName: 'Delete', value: 'com.oraclecloud.virtualnetwork.deletevcn' }, + ]; + + helpers.checkEventRules(rules.data, eventsToCheck, 'VCN', compartment, region, results); + + } + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/networking/vcnChanges.spec.js b/plugins/oracle/networking/vcnChanges.spec.js new file mode 100644 index 0000000000..a51463a449 --- /dev/null +++ b/plugins/oracle/networking/vcnChanges.spec.js @@ -0,0 +1,165 @@ +var expect = require('chai').expect; +var plugin = require('./vcnChanges'); + +const rules = [ + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.virtualnetwork.createvcn","com.oraclecloud.virtualnetwork.updatevcn","com.oraclecloud.virtualnetwork.deletevcn", "com.oraclecloud.virtualnetwork.updatevcnstate", "com.oraclecloud.virtualnetwork.updatevcncapabilities"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.rule1', + displayName: 'Rule 1', + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.virtualnetwork.createvcn","com.oraclecloud.virtualnetwork.updatevcn"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-03T23:57:52.769Z', + }, + { + id: 'ocid1.eventrule.oc1.iad.abuwcljsa53hgf43hbifj3qmhewwgttyedhcngvbb3yyqqzgegtc4dpz2zca', + displayName: 'rule 2', + description: null, + lifecycleState: 'ACTIVE', + condition: '{"eventType":["com.oraclecloud.objectstorage.createbucket"],"data":{}}', + compartmentId: 'ocid1.tenancy.oc1.111111111', + isEnabled: true, + timeCreated: '2022-07-04T01:06:54.834Z' + } + +]; + + +const createCache = (err, rules) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + rules: { + list: { + 'us-ashburn-1': { + err: err, + data: rules + } + } + }, + } +}; + +describe('vcnChanges', function () { + describe('run', function () { + it('should give unknown result if unable to query for rules', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for rules') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['err'], + null + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no rules found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No rules found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if no vcn rules are configured', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('No event rules are configured for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[2]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if Event rules are missing for some vcn changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('Event rules are missing for') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[1]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if event rules are configured for all vcn changes', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('Event rules are configured for all') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [rules[0]] + ); + + plugin.run(cache, {}, callback); + }) + + + }); +}); \ No newline at end of file From 35902894bd666ec146bace360aa039fad9081ad5 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Wed, 13 Jul 2022 17:31:24 +0500 Subject: [PATCH 321/350] Syncing with SAAS 13_07 --- helpers/aws/api_multipart.js | 10 +++++----- plugins/aws/elb/crosszoneLoadBalancing.js | 3 ++- plugins/aws/elb/elbLoggingEnabled.js | 3 ++- plugins/aws/elbv2/elbv2HttpsOnly.js | 2 +- plugins/aws/elbv2/elbv2LoggingEnabled.js | 3 ++- plugins/aws/elbv2/elbv2NoInstances.js | 2 +- 6 files changed, 13 insertions(+), 10 deletions(-) diff --git a/helpers/aws/api_multipart.js b/helpers/aws/api_multipart.js index 32f656d0c4..4019a12ff6 100644 --- a/helpers/aws/api_multipart.js +++ b/helpers/aws/api_multipart.js @@ -2057,10 +2057,11 @@ var postcalls = [ }, { IAM: { - getPolicyVersion: { + getPolicy: { reliesOnService: 'iam', reliesOnCall: 'listPolicies', - override: true, + filterKey: 'PolicyArn', + filterValue: 'Arn', rateLimit: 500 } }, @@ -2101,11 +2102,10 @@ var postcalls = [ }, { IAM: { - getPolicy: { + getPolicyVersion: { reliesOnService: 'iam', reliesOnCall: 'listPolicies', - filterKey: 'PolicyArn', - filterValue: 'Arn', + override: true, rateLimit: 500 }, getRole: { diff --git a/plugins/aws/elb/crosszoneLoadBalancing.js b/plugins/aws/elb/crosszoneLoadBalancing.js index 0b8de6284a..296f746e6d 100644 --- a/plugins/aws/elb/crosszoneLoadBalancing.js +++ b/plugins/aws/elb/crosszoneLoadBalancing.js @@ -43,7 +43,8 @@ module.exports = { var describeLoadBalancerAttributes = helpers.addSource(cache, source, ['elb', 'describeLoadBalancerAttributes', region, lb.DNSName]); - if (!describeLoadBalancerAttributes.data || + if (!describeLoadBalancerAttributes || + !describeLoadBalancerAttributes.data || describeLoadBalancerAttributes.err || !describeLoadBalancerAttributes.data || !describeLoadBalancerAttributes.data.LoadBalancerAttributes) { diff --git a/plugins/aws/elb/elbLoggingEnabled.js b/plugins/aws/elb/elbLoggingEnabled.js index b08c259c19..92176f32ba 100644 --- a/plugins/aws/elb/elbLoggingEnabled.js +++ b/plugins/aws/elb/elbLoggingEnabled.js @@ -57,7 +57,8 @@ module.exports = { var describeLoadBalancerAttributes = helpers.addSource(cache, source, ['elb', 'describeLoadBalancerAttributes', region, lb.DNSName]); - if ( describeLoadBalancerAttributes.data && + if (describeLoadBalancerAttributes && + describeLoadBalancerAttributes.data && describeLoadBalancerAttributes.data.LoadBalancerAttributes && describeLoadBalancerAttributes.data.LoadBalancerAttributes.AccessLog) { var accessLog = describeLoadBalancerAttributes.data.LoadBalancerAttributes.AccessLog; diff --git a/plugins/aws/elbv2/elbv2HttpsOnly.js b/plugins/aws/elbv2/elbv2HttpsOnly.js index a116425c7c..2f4895bf50 100644 --- a/plugins/aws/elbv2/elbv2HttpsOnly.js +++ b/plugins/aws/elbv2/elbv2HttpsOnly.js @@ -52,7 +52,7 @@ module.exports = { var non_https_listener = []; var noListeners = true; var elbArn = lb.LoadBalancerArn; - if (describeListeners.data && describeListeners.data.Listeners && describeListeners.data.Listeners.length) { + if (describeListeners && describeListeners.data && describeListeners.data.Listeners && describeListeners.data.Listeners.length) { noListeners = false; describeListeners.data.Listeners.forEach(function(listener){ // if it is not https add errors to results diff --git a/plugins/aws/elbv2/elbv2LoggingEnabled.js b/plugins/aws/elbv2/elbv2LoggingEnabled.js index e08cb3a4d4..e243a5bd46 100644 --- a/plugins/aws/elbv2/elbv2LoggingEnabled.js +++ b/plugins/aws/elbv2/elbv2LoggingEnabled.js @@ -50,7 +50,8 @@ module.exports = { var describeLoadBalancerAttributes = helpers.addSource(cache, source, ['elbv2', 'describeLoadBalancerAttributes', region, lb.DNSName]); - if ( describeLoadBalancerAttributes.data && + if (describeLoadBalancerAttributes && + describeLoadBalancerAttributes.data && describeLoadBalancerAttributes.data.Attributes && describeLoadBalancerAttributes.data.Attributes.length) { for (let attribute of describeLoadBalancerAttributes.data.Attributes) { diff --git a/plugins/aws/elbv2/elbv2NoInstances.js b/plugins/aws/elbv2/elbv2NoInstances.js index fd8df9ff0a..dcc3a79177 100644 --- a/plugins/aws/elbv2/elbv2NoInstances.js +++ b/plugins/aws/elbv2/elbv2NoInstances.js @@ -53,7 +53,7 @@ module.exports = { ['elbv2', 'describeTargetGroups', region, lb.DNSName]); var elbArn = lb.LoadBalancerArn; - if (describeTargetGroups.data && describeTargetGroups.data.TargetGroups && describeTargetGroups.data.TargetGroups.length){ + if (describeTargetGroups && describeTargetGroups.data && describeTargetGroups.data.TargetGroups && describeTargetGroups.data.TargetGroups.length){ helpers.addResult(results, 0, 'ELB has ' + describeTargetGroups.data.TargetGroups.length + ' target groups', region, elbArn); } else { From 8a56355fca76fdc2554c2e31f0ca105728d9c2b1 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Wed, 13 Jul 2022 19:29:31 +0500 Subject: [PATCH 322/350] Update collectors/google/collector.js --- collectors/google/collector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collectors/google/collector.js b/collectors/google/collector.js index 33b640fe22..40a4615bd2 100644 --- a/collectors/google/collector.js +++ b/collectors/google/collector.js @@ -478,7 +478,7 @@ var collect = function(GoogleConfig, settings, callback) { tertiaryCallCb(); }); }, function() { - if (collection && collection.projects && !collection.projects.get) { + if (collection && (!collection.projects || !collection.projects.get)) { collection.projects = { ...collection.projects, get: { From 230e328537cdd5db553ef691bbb2e8ef13d1f16a Mon Sep 17 00:00:00 2001 From: M-Akhtar Date: Wed, 13 Jul 2022 19:53:01 +0500 Subject: [PATCH 323/350] Added sql_tde_protector_encryption_key setting --- .../azure/sqlserver/tdeProtectorEncrypted.js | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/plugins/azure/sqlserver/tdeProtectorEncrypted.js b/plugins/azure/sqlserver/tdeProtectorEncrypted.js index b7faede55c..e5a0bd13d1 100644 --- a/plugins/azure/sqlserver/tdeProtectorEncrypted.js +++ b/plugins/azure/sqlserver/tdeProtectorEncrypted.js @@ -10,12 +10,24 @@ module.exports = { recommended_action: 'Ensure that a BYOK key is set for the Transparent Data Encryption of each SQL Server.', link: 'https://docs.microsoft.com/en-us/azure/sql-database/transparent-data-encryption-byok-azure-sql', apis: ['servers:listSql', 'encryptionProtectors:listByServer'], + settings: { + sql_tde_protector_encryption_key: { + name: 'SQL Server TDE Protector Encryption Key Type', + description: 'Desired encryption key for SQL Server transparent data encryption; default=service-managed key, cmk=customer-managed key', + regex: '(default|byok)', + default: 'byok' + } + }, run: function(cache, settings, callback) { const results = []; const source = {}; const locations = helpers.locations(settings.govcloud); + var config = { + sql_tde_protector_encryption_key: settings.sql_tde_protector_encryption_key || this.settings.sql_tde_protector_encryption_key.default + }; + async.each(locations.servers, function(location, rcb) { var servers = helpers.addSource(cache, source, @@ -46,16 +58,21 @@ module.exports = { helpers.addResult(results, 0, 'No SQL Server Encryption Protectors found for server', location, server.id); } else { encryptionProtectors.data.forEach(encryptionProtector => { - if ((encryptionProtector.kind && - encryptionProtector.kind.toLowerCase() != 'azurekeyvault') || - (encryptionProtector.serverKeyType && - encryptionProtector.serverKeyType.toLowerCase() != 'azurekeyvault') || - !encryptionProtector.uri) { - helpers.addResult(results, 2, - 'SQL Server TDE protector is not encrypted with BYOK', location, encryptionProtector.id); + if (config.sql_tde_protector_encryption_key == 'byok') { + if ((encryptionProtector.kind && + encryptionProtector.kind.toLowerCase() != 'azurekeyvault') || + (encryptionProtector.serverKeyType && + encryptionProtector.serverKeyType.toLowerCase() != 'azurekeyvault') || + !encryptionProtector.uri) { + helpers.addResult(results, 2, + 'SQL Server TDE protector is not encrypted with BYOK', location, encryptionProtector.id); + } else { + helpers.addResult(results, 0, + 'SQL Server TDE protector is encrypted with BYOK', location, encryptionProtector.id); + } } else { helpers.addResult(results, 0, - 'SQL Server TDE protector is encrypted with BYOK', location, encryptionProtector.id); + 'SQL Server TDE protector is encrypted with service-managed key', location, encryptionProtector.id); } }); } From 35aeb2a94fa3a9a5385452eb9df8bca5fcefe8b6 Mon Sep 17 00:00:00 2001 From: M-Akhtar Date: Wed, 13 Jul 2022 20:17:36 +0500 Subject: [PATCH 324/350] Modified open port plugins to show separate results --- helpers/aws/functions.js | 21 ++++++++++++--------- plugins/aws/ec2/openAllPortsProtocols.js | 12 ++++-------- plugins/aws/ec2/openCustomPorts.js | 2 +- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/helpers/aws/functions.js b/helpers/aws/functions.js index 0cd849e3b9..28c69d31f5 100644 --- a/helpers/aws/functions.js +++ b/helpers/aws/functions.js @@ -64,7 +64,6 @@ function addResult(results, status, message, region, resource, custom){ } function findOpenPorts(groups, ports, service, region, results, cache, config, callback) { - var found = false; var usedGroup = false; if (config.ec2_skip_unused_groups) { var usedGroups = getUsedSecurityGroups(cache, results, region); @@ -95,7 +94,6 @@ function findOpenPorts(groups, ports, service, region, results, cache, config, c if (permission.FromPort <= i && permission.ToPort >= i) { string = `some of ${permission.IpProtocol.toUpperCase()}:${port}`; openV4Ports.push(string); - found = true; break; } } @@ -104,7 +102,6 @@ function findOpenPorts(groups, ports, service, region, results, cache, config, c if (permission.FromPort <= port && permission.ToPort >= port) { string = `${permission.IpProtocol.toUpperCase()}:${port}`; if (openV4Ports.indexOf(string) === -1) openV4Ports.push(string); - found = true; } } } @@ -126,7 +123,6 @@ function findOpenPorts(groups, ports, service, region, results, cache, config, c if (permission.FromPort <= i && permission.ToPort >= i) { string = `some of ${permission.IpProtocol.toUpperCase()}:${portV6}`; openV6Ports.push(string); - found = true; break; } } @@ -135,7 +131,6 @@ function findOpenPorts(groups, ports, service, region, results, cache, config, c if (permission.FromPort <= portV6 && permission.ToPort >= portV6) { var stringV6 = `${permission.IpProtocol.toUpperCase()}:${portV6}`; if (openV6Ports.indexOf(stringV6) === -1) openV6Ports.push(stringV6); - found = true; } } } @@ -165,11 +160,19 @@ function findOpenPorts(groups, ports, service, region, results, cache, config, c addResult(results, 2, resultsString, region, resource); } - } - } + } else { + let strings = []; + + for (const key in ports) { + strings.push(`${key.toUpperCase()}:${ports[key]}`); + } - if (!found && !usedGroup) { - addResult(results, 0, 'No public open ports found', region); + if (strings.length){ + addResult(results, 0, + `Security group: ${groups[g].GroupId} (${groups[g].GroupName}) does not have ${strings.join(', ')} open to 0.0.0.0/0 or ::0`, + region, resource); + } + } } return; diff --git a/plugins/aws/ec2/openAllPortsProtocols.js b/plugins/aws/ec2/openAllPortsProtocols.js index 984d000e9a..7ded2e4692 100644 --- a/plugins/aws/ec2/openAllPortsProtocols.js +++ b/plugins/aws/ec2/openAllPortsProtocols.js @@ -56,7 +56,6 @@ module.exports = { return rcb(); } - var found = false; var groups = describeSecurityGroups.data; var usedGroup = false; if (config.ec2_skip_unused_groups) { @@ -79,13 +78,11 @@ module.exports = { if (!permission.FromPort && (!permission.ToPort || permission.ToPort === 65535)) { var string = 'all ports open to 0.0.0.0/0'; if (strings.indexOf(string) === -1) strings.push(string); - found = true; } if (permission.IpProtocol === '-1') { var stringO = 'all protocols open to 0.0.0.0/0'; if (strings.indexOf(stringO) === -1) strings.push(stringO); - found = true; } } } @@ -97,7 +94,6 @@ module.exports = { if (!permission.FromPort && (!permission.ToPort || permission.ToPort === 65535)) { var stringV6 = 'all ports open to ::/0'; if (strings.indexOf(stringV6) === -1) strings.push(stringV6); - found = true; } if (permission.IpProtocol === '-1') { @@ -121,13 +117,13 @@ module.exports = { ') has ' + strings.join(' and '), region, resource); } + } else { + helpers.addResult(results, 0, + `Security group: ${groups[g].GroupId} (${groups[g].GroupName}) does not have all ports or protocols open to the public`, + region, resource); } } - if (!found && !usedGroup) { - helpers.addResult(results, 0, 'No public open ports found', region); - } - rcb(); }, function(){ callback(null, results, source); diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js index f936f4bdef..3e90c20b05 100644 --- a/plugins/aws/ec2/openCustomPorts.js +++ b/plugins/aws/ec2/openCustomPorts.js @@ -15,7 +15,7 @@ module.exports = { name: 'Restricted Open Ports', description: 'Comma separated list of ports/port-ranges that should be restricted and not publicly open. Example: tcp:80,tcp:443,tcp:80-443', regex: '[a-zA-Z0-9,:]', - default: '' + default: 'tcp:22,udp:15,udp:20' }, ec2_skip_unused_groups: { name: 'EC2 Skip Unused Groups', From 1ced28b2f426e25d6391b1fdedcb6fbb3b8828f8 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Wed, 13 Jul 2022 20:21:56 +0500 Subject: [PATCH 325/350] Update plugins/aws/ec2/openCustomPorts.js --- plugins/aws/ec2/openCustomPorts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js index 3e90c20b05..f936f4bdef 100644 --- a/plugins/aws/ec2/openCustomPorts.js +++ b/plugins/aws/ec2/openCustomPorts.js @@ -15,7 +15,7 @@ module.exports = { name: 'Restricted Open Ports', description: 'Comma separated list of ports/port-ranges that should be restricted and not publicly open. Example: tcp:80,tcp:443,tcp:80-443', regex: '[a-zA-Z0-9,:]', - default: 'tcp:22,udp:15,udp:20' + default: '' }, ec2_skip_unused_groups: { name: 'EC2 Skip Unused Groups', From 04dce4ebeb93b373321b6ff33d744b12e4e020a4 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Wed, 13 Jul 2022 20:27:49 +0500 Subject: [PATCH 326/350] Modified open port plugins to show separate results --- helpers/aws/functions.js | 2 -- plugins/aws/ec2/openAllPortsProtocols.js | 2 -- 2 files changed, 4 deletions(-) diff --git a/helpers/aws/functions.js b/helpers/aws/functions.js index 28c69d31f5..34971affe1 100644 --- a/helpers/aws/functions.js +++ b/helpers/aws/functions.js @@ -64,7 +64,6 @@ function addResult(results, status, message, region, resource, custom){ } function findOpenPorts(groups, ports, service, region, results, cache, config, callback) { - var usedGroup = false; if (config.ec2_skip_unused_groups) { var usedGroups = getUsedSecurityGroups(cache, results, region); if (usedGroups && usedGroups.length && usedGroups[0] === 'Error') return callback(); @@ -155,7 +154,6 @@ function findOpenPorts(groups, ports, service, region, results, cache, config, c if (config.ec2_skip_unused_groups && groups[g].GroupId && !usedGroups.includes(groups[g].GroupId)) { addResult(results, 1, `Security Group: ${groups[g].GroupId} is not in use`, region, resource); - usedGroup = true; } else { addResult(results, 2, resultsString, region, resource); diff --git a/plugins/aws/ec2/openAllPortsProtocols.js b/plugins/aws/ec2/openAllPortsProtocols.js index 7ded2e4692..09a4d4c7a0 100644 --- a/plugins/aws/ec2/openAllPortsProtocols.js +++ b/plugins/aws/ec2/openAllPortsProtocols.js @@ -57,7 +57,6 @@ module.exports = { } var groups = describeSecurityGroups.data; - var usedGroup = false; if (config.ec2_skip_unused_groups) { var usedGroups = helpers.getUsedSecurityGroups(cache, results, region, rcb); } @@ -109,7 +108,6 @@ module.exports = { if (config.ec2_skip_unused_groups && groups[g].GroupId && !usedGroups.includes(groups[g].GroupId)) { helpers.addResult(results, 1, `Security Group: ${groups[g].GroupId} is not in use`, region, resource); - usedGroup = true; } else { helpers.addResult(results, 2, 'Security group: ' + groups[g].GroupId + From 6bb5448940b98ca16f194a4197727e4a2d837e29 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Wed, 13 Jul 2022 20:32:31 +0500 Subject: [PATCH 327/350] Modified open port plugins to show separate results --- plugins/aws/ec2/openAllPortsProtocols.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/aws/ec2/openAllPortsProtocols.js b/plugins/aws/ec2/openAllPortsProtocols.js index 09a4d4c7a0..438423f38c 100644 --- a/plugins/aws/ec2/openAllPortsProtocols.js +++ b/plugins/aws/ec2/openAllPortsProtocols.js @@ -98,7 +98,6 @@ module.exports = { if (permission.IpProtocol === '-1') { var stringP = 'all protocols open to ::/0'; if (strings.indexOf(stringP) === -1) strings.push(stringP); - found = true; } } } From e57b06ce035c9bd4a02577161eb7346070607a87 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Wed, 13 Jul 2022 23:32:39 +0500 Subject: [PATCH 328/350] modified open port plugins to produce 1 result per plugin --- helpers/azure/functions.js | 28 +++++++++++-------- .../openAllPorts.spec.js | 2 +- .../networksecuritygroups/openCIFS.spec.js | 2 +- .../networksecuritygroups/openDNS.spec.js | 2 +- .../networksecuritygroups/openDocker.spec.js | 2 +- .../networksecuritygroups/openFTP.spec.js | 2 +- .../openHadoopNameNode.spec.js | 2 +- .../openHadoopNameNodeWebUI.spec.js | 2 +- .../networksecuritygroups/openKibana.spec.js | 2 +- .../networksecuritygroups/openMySQL.spec.js | 2 +- .../networksecuritygroups/openNetBIOS.spec.js | 2 +- .../networksecuritygroups/openOracle.spec.js | 2 +- .../openOracleAutoDataWarehouse.spec.js | 2 +- .../openPostgreSQL.spec.js | 2 +- .../networksecuritygroups/openRDP.spec.js | 2 +- .../networksecuritygroups/openRPC.spec.js | 2 +- .../networksecuritygroups/openSMBoTCP.spec.js | 2 +- .../networksecuritygroups/openSMTP.spec.js | 2 +- .../openSQLServer.spec.js | 2 +- .../networksecuritygroups/openSSH.spec.js | 2 +- .../networksecuritygroups/openSalt.spec.js | 2 +- .../networksecuritygroups/openTelnet.spec.js | 2 +- .../openVNCClient.spec.js | 2 +- .../openVNCServer.spec.js | 2 +- 24 files changed, 40 insertions(+), 34 deletions(-) diff --git a/helpers/azure/functions.js b/helpers/azure/functions.js index 340e3b675d..57da0ce7eb 100644 --- a/helpers/azure/functions.js +++ b/helpers/azure/functions.js @@ -55,7 +55,6 @@ function addResult(results, status, message, region, resource, custom) { } function findOpenPorts(ngs, protocols, service, location, results) { - let found = false; var openPrefix = ['*', '0.0.0.0', '0.0.0.0/0', '', '/0', '::/0', 'internet']; for (let sGroups of ngs) { @@ -80,6 +79,7 @@ function findOpenPorts(ngs, protocols, service, location, results) { break; } } + if (sourceFound) { for (let protocol in protocols) { let ports = protocols[protocol]; @@ -92,6 +92,7 @@ function findOpenPorts(ngs, protocols, service, location, results) { typeof securityRule.properties['protocol'] == 'string' && (securityRule.properties['protocol'].toUpperCase() === protocol || securityRule.properties['protocol'].toUpperCase() === '*')) { if (securityRule.properties['destinationPortRange']) { + if (securityRule.properties['destinationPortRange'].toString().indexOf("-") > -1) { let portRange = securityRule.properties['destinationPortRange'].split("-"); let startPort = portRange[0]; @@ -101,20 +102,19 @@ function findOpenPorts(ngs, protocols, service, location, results) { ` port ` + ports + ` open to ` + sourceFilter; strings.push(string); if (strings.indexOf(string) === -1) strings.push(string); - found = true; } - } else if (parseInt(securityRule.properties['destinationPortRange']) === port ) { + } else if (parseInt(securityRule.properties['destinationPortRange']) === port || + securityRule.properties['destinationPortRange'] === port || + securityRule.properties['destinationPortRange'] === '*') { var string = `Security Rule "` + securityRule['name'] + `": ` + (protocol === '*' ? `All protocols` : protocol.toUpperCase()) + (ports === '*' ? ` and all ports` : ` port ` + ports) + ` open to ` + sourceFilter; if (strings.indexOf(string) === -1) strings.push(string); - found = true; } } else if (securityRule.properties['destinationPortRanges']) { if (securityRule.properties['destinationPortRanges'].indexOf(port.toString()) > -1) { var string = `Security Rule "` + securityRule['name'] + `": ` + (protocol === '*' ? `All protocols` : protocol.toUpperCase()) + ` port ` + ports + ` open to ` + sourceFilter; if (strings.indexOf(string) === -1) strings.push(string); - found = true; } else { for (let portRange of securityRule.properties['destinationPortRanges']){ if (portRange.toString().indexOf("-") > -1) { @@ -126,7 +126,6 @@ function findOpenPorts(ngs, protocols, service, location, results) { ` port ` + ports + ` open to ` + sourceFilter; strings.push(string); if (strings.indexOf(string) === -1) strings.push(string); - found = true; break; } } @@ -143,11 +142,18 @@ function findOpenPorts(ngs, protocols, service, location, results) { 'Security group:(' + sGroups.name + ') has ' + service + ': ' + strings.join(' and '), location, resource); - } - } + } else { + let strings = []; - if (!found) { - addResult(results, 0, 'No public open ports found', location); + for (const key in protocols) { + strings.push(`${key.toUpperCase()}:${protocols[key]}`); + } + if (strings.length){ + addResult(results, 0, + `Security group:( ${sGroups.name}) does not have ${strings.join(', ')} open *`, + location, resource); + } + } } return; @@ -689,4 +695,4 @@ module.exports = { processCall: processCall, remediateOpenPorts: remediateOpenPorts, remediateOpenPortsHelper: remediateOpenPortsHelper -}; \ No newline at end of file +}; diff --git a/plugins/azure/networksecuritygroups/openAllPorts.spec.js b/plugins/azure/networksecuritygroups/openAllPorts.spec.js index 342a81b6e4..6dea9b76b8 100644 --- a/plugins/azure/networksecuritygroups/openAllPorts.spec.js +++ b/plugins/azure/networksecuritygroups/openAllPorts.spec.js @@ -147,7 +147,7 @@ describe('openAllPorts', function() { openAllPorts.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openCIFS.spec.js b/plugins/azure/networksecuritygroups/openCIFS.spec.js index 54133a29aa..fbe949f4db 100644 --- a/plugins/azure/networksecuritygroups/openCIFS.spec.js +++ b/plugins/azure/networksecuritygroups/openCIFS.spec.js @@ -147,7 +147,7 @@ describe('openCIFS', function() { openCIFS.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openDNS.spec.js b/plugins/azure/networksecuritygroups/openDNS.spec.js index f52c2bbbb6..1d024ef378 100644 --- a/plugins/azure/networksecuritygroups/openDNS.spec.js +++ b/plugins/azure/networksecuritygroups/openDNS.spec.js @@ -148,7 +148,7 @@ describe('openDNS', function() { openDNS.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openDocker.spec.js b/plugins/azure/networksecuritygroups/openDocker.spec.js index 9554915318..0c397f8367 100644 --- a/plugins/azure/networksecuritygroups/openDocker.spec.js +++ b/plugins/azure/networksecuritygroups/openDocker.spec.js @@ -162,7 +162,7 @@ describe('openDocker', function() { openDocker.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openFTP.spec.js b/plugins/azure/networksecuritygroups/openFTP.spec.js index 554c446c44..a264383e70 100644 --- a/plugins/azure/networksecuritygroups/openFTP.spec.js +++ b/plugins/azure/networksecuritygroups/openFTP.spec.js @@ -146,7 +146,7 @@ describe('openFTP', function() { openFTP.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openHadoopNameNode.spec.js b/plugins/azure/networksecuritygroups/openHadoopNameNode.spec.js index 3a2529e464..a308fa34d8 100644 --- a/plugins/azure/networksecuritygroups/openHadoopNameNode.spec.js +++ b/plugins/azure/networksecuritygroups/openHadoopNameNode.spec.js @@ -153,7 +153,7 @@ describe('openHadoopNameNode', function() { openHadoopNameNode.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openHadoopNameNodeWebUI.spec.js b/plugins/azure/networksecuritygroups/openHadoopNameNodeWebUI.spec.js index f18b0e9d2e..98acdd1754 100644 --- a/plugins/azure/networksecuritygroups/openHadoopNameNodeWebUI.spec.js +++ b/plugins/azure/networksecuritygroups/openHadoopNameNodeWebUI.spec.js @@ -146,7 +146,7 @@ describe('openHadoopNameNodeWebUI', function() { openHadoopNameNodeWebUI.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openKibana.spec.js b/plugins/azure/networksecuritygroups/openKibana.spec.js index 819d24f1b1..57a30c80fa 100644 --- a/plugins/azure/networksecuritygroups/openKibana.spec.js +++ b/plugins/azure/networksecuritygroups/openKibana.spec.js @@ -145,7 +145,7 @@ describe('openKibana', function() { openKibana.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openMySQL.spec.js b/plugins/azure/networksecuritygroups/openMySQL.spec.js index 182ca013bc..b753b34e0e 100644 --- a/plugins/azure/networksecuritygroups/openMySQL.spec.js +++ b/plugins/azure/networksecuritygroups/openMySQL.spec.js @@ -146,7 +146,7 @@ describe('openMySQL', function() { openMySQL.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openNetBIOS.spec.js b/plugins/azure/networksecuritygroups/openNetBIOS.spec.js index cd4e2ee392..3f01b20dd7 100644 --- a/plugins/azure/networksecuritygroups/openNetBIOS.spec.js +++ b/plugins/azure/networksecuritygroups/openNetBIOS.spec.js @@ -146,7 +146,7 @@ describe('openNetBIOS', function() { openNetBIOS.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openOracle.spec.js b/plugins/azure/networksecuritygroups/openOracle.spec.js index 2b1a55133c..0097e1a570 100644 --- a/plugins/azure/networksecuritygroups/openOracle.spec.js +++ b/plugins/azure/networksecuritygroups/openOracle.spec.js @@ -145,7 +145,7 @@ describe('openOracle', function() { openOracle.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openOracleAutoDataWarehouse.spec.js b/plugins/azure/networksecuritygroups/openOracleAutoDataWarehouse.spec.js index 2fc0752cad..adc91c6541 100644 --- a/plugins/azure/networksecuritygroups/openOracleAutoDataWarehouse.spec.js +++ b/plugins/azure/networksecuritygroups/openOracleAutoDataWarehouse.spec.js @@ -145,7 +145,7 @@ describe('openOracleAutoDataWarehouse', function() { openOracleAutoDataWarehouse.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openPostgreSQL.spec.js b/plugins/azure/networksecuritygroups/openPostgreSQL.spec.js index aaaccc5b6c..411314a8db 100644 --- a/plugins/azure/networksecuritygroups/openPostgreSQL.spec.js +++ b/plugins/azure/networksecuritygroups/openPostgreSQL.spec.js @@ -145,7 +145,7 @@ describe('openPostgreSQL', function() { openPostgreSQL.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openRDP.spec.js b/plugins/azure/networksecuritygroups/openRDP.spec.js index 65c9522a71..6c6d57eac6 100644 --- a/plugins/azure/networksecuritygroups/openRDP.spec.js +++ b/plugins/azure/networksecuritygroups/openRDP.spec.js @@ -145,7 +145,7 @@ describe('openRDP', function() { openRDP.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openRPC.spec.js b/plugins/azure/networksecuritygroups/openRPC.spec.js index de81fbe552..86a267b8fa 100644 --- a/plugins/azure/networksecuritygroups/openRPC.spec.js +++ b/plugins/azure/networksecuritygroups/openRPC.spec.js @@ -145,7 +145,7 @@ describe('openRPC', function() { openRPC.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openSMBoTCP.spec.js b/plugins/azure/networksecuritygroups/openSMBoTCP.spec.js index 274ea8866b..8c7c1fd329 100644 --- a/plugins/azure/networksecuritygroups/openSMBoTCP.spec.js +++ b/plugins/azure/networksecuritygroups/openSMBoTCP.spec.js @@ -145,7 +145,7 @@ describe('openSMBoTCP', function() { openSMBoTCP.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openSMTP.spec.js b/plugins/azure/networksecuritygroups/openSMTP.spec.js index 914423a8d5..a03a8efd40 100644 --- a/plugins/azure/networksecuritygroups/openSMTP.spec.js +++ b/plugins/azure/networksecuritygroups/openSMTP.spec.js @@ -145,7 +145,7 @@ describe('openSMTP', function() { openSMTP.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openSQLServer.spec.js b/plugins/azure/networksecuritygroups/openSQLServer.spec.js index 1d3aecbe5e..1761e8ef65 100644 --- a/plugins/azure/networksecuritygroups/openSQLServer.spec.js +++ b/plugins/azure/networksecuritygroups/openSQLServer.spec.js @@ -146,7 +146,7 @@ describe('openSQLServer', function() { openSQLServer.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openSSH.spec.js b/plugins/azure/networksecuritygroups/openSSH.spec.js index f4bd8ecc35..a6214a1b7a 100644 --- a/plugins/azure/networksecuritygroups/openSSH.spec.js +++ b/plugins/azure/networksecuritygroups/openSSH.spec.js @@ -145,7 +145,7 @@ describe('openSSH', function() { openSSH.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openSalt.spec.js b/plugins/azure/networksecuritygroups/openSalt.spec.js index 4b191998cb..8f3eea407c 100644 --- a/plugins/azure/networksecuritygroups/openSalt.spec.js +++ b/plugins/azure/networksecuritygroups/openSalt.spec.js @@ -146,7 +146,7 @@ describe('openSalt', function() { openSalt.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openTelnet.spec.js b/plugins/azure/networksecuritygroups/openTelnet.spec.js index 1e9259996b..d7a02f3905 100644 --- a/plugins/azure/networksecuritygroups/openTelnet.spec.js +++ b/plugins/azure/networksecuritygroups/openTelnet.spec.js @@ -145,7 +145,7 @@ describe('openTelnet', function() { openTelnet.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openVNCClient.spec.js b/plugins/azure/networksecuritygroups/openVNCClient.spec.js index 59686d5947..2da05e4cc4 100644 --- a/plugins/azure/networksecuritygroups/openVNCClient.spec.js +++ b/plugins/azure/networksecuritygroups/openVNCClient.spec.js @@ -145,7 +145,7 @@ describe('openVNCClient', function() { openVNCClient.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); diff --git a/plugins/azure/networksecuritygroups/openVNCServer.spec.js b/plugins/azure/networksecuritygroups/openVNCServer.spec.js index cdec216423..3fc2053487 100644 --- a/plugins/azure/networksecuritygroups/openVNCServer.spec.js +++ b/plugins/azure/networksecuritygroups/openVNCServer.spec.js @@ -145,7 +145,7 @@ describe('openVNCServer', function() { openVNCServer.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('No public open ports found'); + expect(results[0].message).to.include('does not have'); expect(results[0].region).to.equal('eastus'); done(); }); From ddd6e4e97e3696e6cd5231944ff8dabe8b9a0070 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 14 Jul 2022 00:00:57 +0500 Subject: [PATCH 329/350] added setting in s3 bucket website enabled to whitelist empty buckets --- helpers/aws/api.js | 6 ++++ helpers/aws/api_multipart.js | 6 ++++ plugins/aws/s3/bucketWebsiteEnabled.js | 31 ++++++++++++++++++- plugins/aws/s3/bucketWebsiteEnabled.spec.js | 34 +++++++++++++++++++-- 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/helpers/aws/api.js b/helpers/aws/api.js index 2638e484a7..92e244cf69 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -1458,6 +1458,12 @@ var postcalls = [ filterKey: 'Bucket', filterValue: 'Name' }, + listObjects: { + reliesOnService: 's3', + reliesOnCall: 'listBuckets', + filterKey: 'Bucket', + filterValue: 'Name' + }, sendIntegration: { enabled: true } diff --git a/helpers/aws/api_multipart.js b/helpers/aws/api_multipart.js index 4019a12ff6..73d5b92de6 100644 --- a/helpers/aws/api_multipart.js +++ b/helpers/aws/api_multipart.js @@ -1432,6 +1432,12 @@ var postcalls = [ filterKey: 'Bucket', filterValue: 'Name' }, + listObjects: { + reliesOnService: 's3', + reliesOnCall: 'listBuckets', + filterKey: 'Bucket', + filterValue: 'Name' + }, sendIntegration: { enabled: true } diff --git a/plugins/aws/s3/bucketWebsiteEnabled.js b/plugins/aws/s3/bucketWebsiteEnabled.js index 115826a966..96e3c2e178 100644 --- a/plugins/aws/s3/bucketWebsiteEnabled.js +++ b/plugins/aws/s3/bucketWebsiteEnabled.js @@ -8,13 +8,25 @@ module.exports = { more_info: 'S3 buckets should not be configured with static website hosting with public objects. Instead, a CloudFront distribution should be configured with an origin access identity.', recommended_action: 'Disable S3 bucket static website hosting in favor or CloudFront distributions.', link: 'https://aws.amazon.com/premiumsupport/knowledge-center/cloudfront-https-requests-s3/', - apis: ['S3:listBuckets', 'S3:getBucketWebsite', 'S3:getBucketLocation'], + apis: ['S3:listBuckets', 'S3:getBucketWebsite', 'S3:getBucketLocation', 'S3:listObjects'], + settings: { + s3_website_whitelist_empty_buckets: { + name: 'S3 Website Whitelist Empty Buckets', + description: 'When set to true, whitelist empty buckets without checking bucket website configutation', + regex: '^(true|false)$', + default: 'false' + } + }, run: function(cache, settings, callback) { var results = []; var source = {}; var region = helpers.defaultRegion(settings); + var config = { + s3_website_whitelist_empty_buckets: settings.s3_website_whitelist_empty_buckets || this.settings.s3_website_whitelist_empty_buckets.default, + }; + var ignoreEmptyBuckets = (config.s3_website_whitelist_empty_buckets == 'true'); var listBuckets = helpers.addSource(cache, source, ['s3', 'listBuckets', region]); @@ -35,6 +47,23 @@ module.exports = { listBuckets.data.forEach(function(bucket){ var bucketLocation = helpers.getS3BucketLocation(cache, region, bucket.Name); + if (ignoreEmptyBuckets){ + var listObjects = helpers.addSource(cache, source, + ['s3', 'listObjects', region, bucket.Name]); + + if (!listObjects || listObjects.err || !listObjects.data) { + helpers.addResult(results, 3, + 'Unable to list S3 bucket objects: ' + helpers.addError(listObjects), bucketLocation, 'arn:aws:s3:::' + bucket.Name); + return; + } + + if (!listObjects.data.Contents || !listObjects.data.Contents.length){ + helpers.addResult(results, 0, + 'Bucket : ' + bucket.Name + ' is empty', bucketLocation, 'arn:aws:s3:::' + bucket.Name); + return; + } + } + var getBucketWebsite = helpers.addSource(cache, source, ['s3', 'getBucketWebsite', region, bucket.Name]); diff --git a/plugins/aws/s3/bucketWebsiteEnabled.spec.js b/plugins/aws/s3/bucketWebsiteEnabled.spec.js index 364ac6f211..c751ceb04e 100644 --- a/plugins/aws/s3/bucketWebsiteEnabled.spec.js +++ b/plugins/aws/s3/bucketWebsiteEnabled.spec.js @@ -2,9 +2,9 @@ var assert = require('assert'); var expect = require('chai').expect; var s3 = require('./bucketWebsiteEnabled'); -const createCache = (bucketErr, website) => { +const createCache = (bucketErr, website, emptyBucket) => { var bucketObj = {}; - + var bucketContents = []; if (bucketErr) { bucketObj = { "err": { @@ -17,6 +17,15 @@ const createCache = (bucketErr, website) => { }; } + if (!emptyBucket) { + bucketContents.push({ + ETag: "\"70ee1738b6b21e2c8a43f3a5ab0eee71\"", + Key: "example1.jpg", + Size: 11, + StorageClass: "STANDARD" + }) + } + return { "s3": { "listBuckets": { @@ -41,6 +50,13 @@ const createCache = (bucketErr, website) => { } } } + }, + "listObjects": { + "us-east-1": { + "bucket1": { + "data": bucketContents + } + } } } }; @@ -91,5 +107,19 @@ describe('bucketWebsiteEnabled', function () { s3.run(cache, {}, callback); }) + + it('should give passing result if S3 bucket is empty and whitelist s3 bucket setting is enabled', 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('is empty') + expect(results[0].region).to.equal('us-east-1'); + done() + }; + + const cache = createCache(false, null, false); + + s3.run(cache, { s3_website_whitelist_empty_buckets: 'true' }, callback); + }) }) }); \ No newline at end of file From d35bb3ddb6d112a3550bb137ae9d474bbbec2071 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Thu, 14 Jul 2022 00:16:14 +0500 Subject: [PATCH 330/350] Removed get project call from openAllPorts --- plugins/google/vpcnetwork/openAllPorts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/google/vpcnetwork/openAllPorts.js b/plugins/google/vpcnetwork/openAllPorts.js index ab5838ec22..b8015e7425 100644 --- a/plugins/google/vpcnetwork/openAllPorts.js +++ b/plugins/google/vpcnetwork/openAllPorts.js @@ -9,7 +9,7 @@ module.exports = { more_info: 'While some ports such as HTTP and HTTPS are required to be open to the public to function properly, services should be restricted to known IP addresses.', link: 'https://cloud.google.com/vpc/docs/using-firewalls', recommended_action: 'Restrict ports to known IP addresses.', - apis: ['firewalls:list', 'projects:get'], + apis: ['firewalls:list'], compliance: { hipaa: 'HIPAA requires strict access controls to networks and services ' + 'processing sensitive data. Firewalls are the built-in ' + From cc046e6d99154020bd37895b48fac8d439b122eb Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Fri, 15 Jul 2022 08:44:52 +0500 Subject: [PATCH 331/350] OCI - Key Rotation Plugin --- collectors/oracle/collector.js | 20 ++ exports.js | 3 + helpers/oracle/regions.js | 1 + other_modules/oci/index.js | 10 +- other_modules/oci/services.json | 21 ++ plugins/oracle/vaults/keyRotation.js | 88 ++++++++ plugins/oracle/vaults/keyRotation.spec.js | 246 ++++++++++++++++++++++ 7 files changed, 386 insertions(+), 3 deletions(-) create mode 100644 plugins/oracle/vaults/keyRotation.js create mode 100644 plugins/oracle/vaults/keyRotation.spec.js diff --git a/collectors/oracle/collector.js b/collectors/oracle/collector.js index 4c3a0df0d3..f6583b5f5d 100644 --- a/collectors/oracle/collector.js +++ b/collectors/oracle/collector.js @@ -464,6 +464,26 @@ var finalcalls = { restVersion: '', } }, + keys: { + get: { + api: 'kms', + reliesOnService: ['keys'], + reliesOnCall: ['list'], + filterKey: ['compartmentId', 'id'], + filterValue: ['compartmentId', 'id'], + restVersion: '/20180608' + } + }, + keyVersions: { + list: { + api: 'kms', + reliesOnService: ['keys'], + reliesOnCall: ['list'], + filterKey: ['compartmentId', 'id'], + filterValue: ['compartmentId', 'id'], + restVersion: '/20180608' + } + }, exprt: { get: { api: 'fileStorage', diff --git a/exports.js b/exports.js index c7d33a4f9f..b9e8e7e8c9 100644 --- a/exports.js +++ b/exports.js @@ -910,6 +910,9 @@ module.exports = { 'okePrivateEndpoint' : require(__dirname + '/plugins/oracle/oke/okePrivateEndpoint.js'), 'okeSecretsEncrypted' : require(__dirname + '/plugins/oracle/oke/okeSecretsEncrypted.js'), 'okeSecurityGroups' : require(__dirname + '/plugins/oracle/oke/okeSecurityGroups.js'), + + 'keyRotation' : require(__dirname + '/plugins/oracle/vaults/keyRotation.js'), + }, google: { 'excessiveFirewallRules' : require(__dirname + '/plugins/google/vpcnetwork/excessiveFirewallRules.js'), diff --git a/helpers/oracle/regions.js b/helpers/oracle/regions.js index 4e10c3b37b..ed90e2eaf8 100644 --- a/helpers/oracle/regions.js +++ b/helpers/oracle/regions.js @@ -83,5 +83,6 @@ module.exports = { customerSecretKey: ['default'], vault: regions, keys: regions, + keyVersions: regions, cluster: regions }; \ No newline at end of file diff --git a/other_modules/oci/index.js b/other_modules/oci/index.js index 6a174bc668..c05a2a133b 100644 --- a/other_modules/oci/index.js +++ b/other_modules/oci/index.js @@ -7,11 +7,15 @@ module.exports = function(api, service, key, OracleConfig, parameters, callback) !services[api][service][key]) return callback({code: 'Invalid API'}); var localService = services[api][service][key]; - + //replacing endpoint with managementRndpoint value from vault for keys api if (api === 'kms' && localService.path === 'keys') { - localService.endpoint = parameters.managementEndpoint.replace('https://', ''); - delete parameters['managementEndpoint']; + if (!localService.secondaryPath && key === 'list') { + localService.endpoint = parameters.managementEndpoint.replace('https://', ''); + delete parameters['managementEndpoint']; + } else if (key === 'get' || (localService.secondaryPath && localService.secondaryPath === 'keyVersions')) { + localService.endpoint = localService.endpoint.replace(/^[^\s-]*(?=-)/, parameters.id.split('.')[4]); + } } var suffix = ''; diff --git a/other_modules/oci/services.json b/other_modules/oci/services.json index f578bb7c6d..f3bff494a2 100644 --- a/other_modules/oci/services.json +++ b/other_modules/oci/services.json @@ -473,6 +473,27 @@ "method": "GET", "path": "keys", "endpoint": "{{managementEndpoint}}" + }, + "get": { + "allowedQueryStrings": [ + "compartmentId", "page", "limit" + ], + "encodedGet": "id", + "method": "GET", + "path": "keys", + "endpoint": "-management.kms.{{region}}.oraclecloud.com" + } + }, + "keyVersions": { + "list": { + "allowedQueryStrings": [ + "compartmentId", "page", "limit" + ], + "encodedGet": "id", + "method": "GET", + "path": "keys", + "secondaryPath": "keyVersions", + "endpoint": "-management.kms.{{region}}.oraclecloud.com" } } }, diff --git a/plugins/oracle/vaults/keyRotation.js b/plugins/oracle/vaults/keyRotation.js new file mode 100644 index 0000000000..c4e784dd16 --- /dev/null +++ b/plugins/oracle/vaults/keyRotation.js @@ -0,0 +1,88 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Key Rotation', + category: 'Vaults', + domain: 'Management and Governance', + description: 'Ensure that your OCI Vault Keys are periodically rotated.', + more_info: 'Rotating keys periodically limits the data encrypted under one key version. Key rotation thereby reduces the risk in case a key is ever compromised.', + link: 'https://docs.oracle.com/en-us/iaas/Content/KeyManagement/Tasks/managingkeys.htm', + recommended_action: 'Ensure that all your cryptographic keys are regenerated (rotated) after a specific period.', + apis: ['vault:list', 'keys:list', 'keys:get', 'keyVersions:list'], + settings: { + key_rotation_interval: { + name: 'Key Rotation Interval', + description: 'Return a failing result when keys exceed this number of days without being rotated', + regex: '^[1-9]{1}[0-9]{0,3}$', + default: '365' + } + }, + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + var keyRotationInterval = parseInt(settings.key_rotation_interval || this.settings.key_rotation_interval.default); + + async.each(regions.keys, function(region, rcb){ + + if (helpers.checkRegionSubscription(cache, source, results, region)) { + + var keys = helpers.addSource(cache, source, + ['keys', 'get', region]); + + if (!keys) return rcb(); + + if (keys.err || !keys.data) { + helpers.addResult(results, 3, + 'Unable to query for cryptographic keys: ' + helpers.addError(keys), region); + return rcb(); + } + + if (!keys.data.length) { + helpers.addResult(results, 0, 'No cryptographic keys found', region); + return rcb(); + } + + var keyVersions = helpers.addSource(cache, source, + ['keyVersions', 'list', region]); + + if (!keyVersions) return rcb(); + + if (keyVersions.err || !keyVersions.data) { + helpers.addResult(results, 3, + 'Unable to query for cryptographic key versions: ' + helpers.addError(keyVersions), region); + return rcb(); + } + + if (!keyVersions.data.length) { + helpers.addResult(results, 0, 'No key versions found', region); + return rcb(); + } + + keys.data.forEach(key => { + const currentKeyVersion = keyVersions.data.find(version => version.id === key.currentKeyVersion); + + let timeCreated = currentKeyVersion ? currentKeyVersion.timeCreated : key.timeCreated; + var diffInDays = helpers.daysBetween(timeCreated, new Date()); + + if (diffInDays > keyRotationInterval) { + helpers.addResult(results, 2, + `Cryptographic Key was last rotated ${diffInDays} days ago which is greater than ${keyRotationInterval}`, region, key.id); + } else { + helpers.addResult(results, 0, + `Cryptographic Key was last rotated ${diffInDays} days ago which is equal to or less than ${keyRotationInterval}`, region, key.id); + } + }); + + + } + rcb(); + }, function(){ + // Global checking goes here + callback(null, results, source); + }); + } +}; diff --git a/plugins/oracle/vaults/keyRotation.spec.js b/plugins/oracle/vaults/keyRotation.spec.js new file mode 100644 index 0000000000..6d3f8ec035 --- /dev/null +++ b/plugins/oracle/vaults/keyRotation.spec.js @@ -0,0 +1,246 @@ +var expect = require('chai').expect; +var plugin = require('./keyRotation'); + +var passDate = new Date(); +passDate.setMonth(passDate.getMonth() - 1); +var failDate = new Date(); +failDate.setYear(failDate.getYear() - 1); + +const keys = [ + { + "compartmentId": "ocid1.tenancy.oc1..aaaa111111", + "currentKeyVersion": "ocid1.keyversion.oc1.iad.bbbbbbbb.version1", + "definedTags": {}, + "displayName": "key1", + "freeformTags": {}, + "id": "ocid1.key.oc1.iad.bbbbbbbb.key1", + "protectionMode": "HSM", + "lifecycleState": "ENABLED", + "timeCreated": failDate, + }, + { + "compartmentId": "ocid1.tenancy.oc1..aaaa111111", + "currentKeyVersion": "ocid1.keyversion.oc1.iad.bbbbbbb.version2", + "definedTags": {}, + "displayName": "key-1", + "freeformTags": {}, + "id": "ocid1.key.oc1.iad.bbbbbbb.key2", + "protectionMode": "SOFTWARE", + "lifecycleState": "ENABLED", + "timeCreated": failDate + } +]; + +const keyVersions = [ + { + "compartmentId": 'ocid1.tenancy.oc1..aaaa111111', + "id": 'ocid1.keyversion.oc1.iad.bbbbbbb.awemmjwzfoaaa.abuwcljrc4nsujs33cxy6o7bf5hcjtq5fce7cqk56o3bcxh4pwkobfbkhpba', + "keyId": 'ocid1.key.oc1.iad.bbbbbbb.key2', + "lifecycleState": 'ENABLED', + "origin": 'INTERNAL', + "timeCreated": failDate, + "timeOfDeletion": null, + "vaultId": 'ocid1.vault.oc1.iad.bbbbbbb.vault1', + "keys": 'ocid1.key.oc1.iad.bbbbbbb.key2' + }, + { + "compartmentId": 'ocid1.tenancy.oc1..aaaa111111', + "id": 'ocid1.keyversion.oc1.iad.bbbbbbb.version2', + "keyId": 'ocid1.key.oc1.iad.bbbbbbb.key2', + "lifecycleState": 'ENABLED', + "origin": 'INTERNAL', + "timeCreated": passDate, + "timeOfDeletion": null, + "vaultId": 'ocid1.vault.oc1.iad.bbbbbbb.vault1', + "keys": 'ocid1.key.oc1.iad.bbbbbbb.key2' + }, + { + "compartmentId": 'ocid1.tenancy.oc1..aaaa111111', + "id": 'ocid1.keyversion.oc1.iad.bbbbbbb.awemmjwzfoaaa.abuwcljrc4nsujs33cxy6o7bf5hcjtq5fce7cqk56o3bcxh4pwkobfbkhpba', + "keyId": 'ocid1.key.oc1.iad.bbbbbbbb.key1', + "lifecycleState": 'ENABLED', + "origin": 'INTERNAL', + "timeCreated": failDate, + "timeOfDeletion": null, + "vaultId": 'ocid1.vault.oc1.iad.bbbbbbb.vault1', + "keys": 'ocid1.key.oc1.iad.bbbbbbb.key2' + } +] + +const createCache = (err, data, versionErr, versionData) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + keys: { + get: { + 'us-ashburn-1': { + err: err, + data: data + } + } + }, + keyVersions: { + list: { + 'us-ashburn-1': { + err: versionErr, + data: versionData + } + } + }, + vault: { + list: { + 'us-ashburn-1': { + data: [ + { + "compartmentId": "compartment-1", + "displayName": "vault-1", + "freeformTags": {}, + "id": "vault-1", + "lifecycleState": "ACTIVE", + }, + ] + } + } + } + } +}; + +describe('keyRotation', function () { + describe('run', function () { + it('should give unknown result if unable to query for cryptographic keys', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for cryptographic keys') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['error'], + undefined + + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if no cryptographic keys', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No cryptographic keys found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give unknown result if unable to query for cryptographic key versions', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for cryptographic key versions') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + keys, + ['error'], + undefined + + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if no key versions found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No key versions found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + keys, + null, + [] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give failing result if cryptographic key has not been rotated within set days limit', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('which is greater than') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [keys[0]], + null, + keyVersions + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if cryptographic key has been rotated within set days limit', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('which is equal to or less than') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [keys[1]], + null, + keyVersions + ); + + plugin.run(cache, {}, callback); + }); + }); +}); \ No newline at end of file From 904c7df3cc5380e2f6ecb691d2c3988f53770ed7 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Fri, 15 Jul 2022 06:38:01 +0500 Subject: [PATCH 332/350] OCI - Flow Logs Enabled Plugin --- collectors/oracle/collector.js | 18 ++ exports.js | 1 + helpers/oracle/regions.js | 2 + other_modules/oci/services.json | 21 ++ plugins/oracle/networking/flowLogsEnabled.js | 65 ++++++ .../oracle/networking/flowLogsEnabled.spec.js | 185 ++++++++++++++++++ 6 files changed, 292 insertions(+) create mode 100644 plugins/oracle/networking/flowLogsEnabled.js create mode 100644 plugins/oracle/networking/flowLogsEnabled.spec.js diff --git a/collectors/oracle/collector.js b/collectors/oracle/collector.js index 4c3a0df0d3..b69e02dd60 100644 --- a/collectors/oracle/collector.js +++ b/collectors/oracle/collector.js @@ -44,6 +44,14 @@ var calls = { filterValue: ['compartmentId'], } }, + logGroup: { + list: { + api: 'logging', + restVersion: '/20200531', + filterKey: ['compartmentId'], + filterValue: ['compartmentId'] + } + }, publicIp: { list: { api: 'core', @@ -439,6 +447,16 @@ var postcalls = { restVersion: '/20180608' } }, + log: { + list: { + api: 'logging', + reliesOnService: ['logGroup'], + reliesOnCall: ['list'], + filterKey: ['compartmentId', 'id'], + filterValue: ['compartmentId', 'id'], + restVersion: '/20200531' + } + }, cluster: { get: { api: 'oke', diff --git a/exports.js b/exports.js index c7d33a4f9f..30e68eab36 100644 --- a/exports.js +++ b/exports.js @@ -869,6 +869,7 @@ module.exports = { 'openKibana' : require(__dirname + '/plugins/oracle/networking/openKibana.js'), 'openSalt' : require(__dirname + '/plugins/oracle/networking/openSalt.js'), 'openSMTP' : require(__dirname + '/plugins/oracle/networking/openSMTP.js'), + 'flowLogsEnabled' : require(__dirname + '/plugins/oracle/networking/flowLogsEnabled.js'), 'statelessSecurityRules' : require(__dirname + '/plugins/oracle/networking/statelessSecurityRules.js'), 'defaultSecurityList' : require(__dirname + '/plugins/oracle/networking/defaultSecurityList.js'), diff --git a/helpers/oracle/regions.js b/helpers/oracle/regions.js index 4e10c3b37b..d08f0e7af9 100644 --- a/helpers/oracle/regions.js +++ b/helpers/oracle/regions.js @@ -56,6 +56,8 @@ module.exports = { policy: regions, defaultTags: ['default'], subnet: regions, + logGroup: regions, + log: regions, dbHome: regions, database: regions, instance: regions, diff --git a/other_modules/oci/services.json b/other_modules/oci/services.json index f578bb7c6d..bee269dda4 100644 --- a/other_modules/oci/services.json +++ b/other_modules/oci/services.json @@ -490,6 +490,27 @@ } } }, + "logging": { + "logGroup": { + "list": { + "allowedQueryStrings": [ + "compartmentId", "displayname", "limit", "page", "sortBy", "sortOrder", "lifecycleState" + ], + "method": "GET", + "path": "logGroups", + "endpoint": "logging.{{region}}.oci.oraclecloud.com" + } + }, + "log": { + "list": { + "encodedGet": "id", + "method": "GET", + "path": "logGroups", + "secondaryPath": "logs", + "endpoint": "logging.{{region}}.oci.oraclecloud.com" + } + } + }, "objectStore": { "bucket": { "list": { diff --git a/plugins/oracle/networking/flowLogsEnabled.js b/plugins/oracle/networking/flowLogsEnabled.js new file mode 100644 index 0000000000..2951bbbafb --- /dev/null +++ b/plugins/oracle/networking/flowLogsEnabled.js @@ -0,0 +1,65 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Flow Logs Enabled', + category: 'Networking', + domain: 'Management and Governance', + description: 'Ensures VCN flow logs are enabled for traffic logging.', + more_info: 'VCN flow logs allow you to monitor traffic flowing within your virtual network and can help in detecting anomalous traffic.', + link: 'https://docs.oracle.com/en-us/iaas/Content/Network/Concepts/vcn_flow_logs.htm', + recommended_action: 'Enable VCN flow logs for each VCN subnet.', + apis: ['vcn:list', 'subnet:list', 'logGroup:list', 'log:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.subnet, function(region, rcb){ + + if (helpers.checkRegionSubscription(cache, source, results, region)) { + + var subnets = helpers.addSource(cache, source, + ['subnet', 'list', region]); + + if (!subnets) return rcb(); + + if (subnets.err || !subnets.data) { + helpers.addResult(results, 3, + 'Unable to query for subnets: ' + helpers.addError(subnets), region); + return rcb(); + } + + if (!subnets.data.length) { + helpers.addResult(results, 0, 'No subnets found', region); + return rcb(); + } + + var logs = helpers.addSource(cache, source, + ['log', 'list', region]); + + subnets.data.forEach(subnet => { + let subnetFlowLog = null; + + if (logs && !logs.err && logs.data && logs.data.length) { + subnetFlowLog = logs.data.find(log => log.isEnabled && log.configuration + && Object.keys(log.configuration).length && log.configuration.source + && Object.keys(log.configuration.source).length && log.configuration.source.service === 'flowlogs' + && log.configuration.source.resource === subnet.id); + } + + if (subnetFlowLog) { + helpers.addResult(results, 0, 'The subnet has flow logs enabled', region, subnet.id); + } else { + helpers.addResult(results, 2, 'The subnet does not have flow logs enabled', region, subnet.id); + } + }); + } + rcb(); + }, function(){ + // Global checking goes here + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/networking/flowLogsEnabled.spec.js b/plugins/oracle/networking/flowLogsEnabled.spec.js new file mode 100644 index 0000000000..956f6882d4 --- /dev/null +++ b/plugins/oracle/networking/flowLogsEnabled.spec.js @@ -0,0 +1,185 @@ +var expect = require('chai').expect; +var plugin = require('./flowLogsEnabled'); + +const logs = [ + { + "id": "ocid1.log.oc1.log11111111", + "logGroupId": "ocid1.loggroup.oc1.loggroup11111", + "displayName": "subnet_log", + "isEnabled": true, + "lifecycleState": "ACTIVE", + "logType": "SERVICE", + "configuration": { + "compartmentId": "ocid1.tenancy.oc1.1111111111111", + "source": { + "sourceType": "OCISERVICE", + "service": "flowlogs", + "resource": "ocid1.subnet.oc1.iad.subnet1", + "category": "all", + "parameters": {} + }, + "archiving": { + "isEnabled": false + } + }, + "freeformTags": {}, + "timeCreated": "2022-07-15T00:25:53.258Z", + "timeLastModified": "2022-07-15T00:25:53.258Z", + "retentionDuration": 30, + "compartmentId": "ocid1.tenancy.oc1.1111111111111", + "logGroups": "ocid1.loggroup.oc1.loggroup11111" + } +] + +const createCache = (err, data) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + subnet: { + list: { + 'us-ashburn-1': { + err: err, + data: data + } + } + }, + log: { + list: { + 'us-ashburn-1': { + err: null, + data: logs + } + } + } + } +}; + +describe('flowLogsEnabled', function () { + describe('run', function () { + it('should give unknown result if a subnet error occurs or no data is present', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for subnets') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['error'], + null, + ); + + plugin.run(cache, {}, callback); + }) + it('should give passing result if no subnets are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No subnets found') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [], + ); + + plugin.run(cache, {}, callback); + }) + it('should give failing result if the subnet does not have flow logs enabled', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('The subnet does not have flow logs enabled') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [ + + { + "cidrBlock": "10.0.1.0/24", + "compartmentId": "ocid1.tenancy.oc1.1111111111111", + "definedTags": {}, + "displayName": "subnet1", + "freeformTags": {}, + "id": "ocid1.subnet.oc1.iad.subnet2", + "lifecycleState": "AVAILABLE", + "securityListIds": [ + "ocid1.securitylist.oc1.iad.list11111" + ], + "timeCreated": "2019-02-28T18:19:38.677Z", + "vcnId": "ocid1.vcn.oc1.iad.vcn111111", + "virtualRouterIp": "10.0.1.1", + "virtualRouterMac": "00:00:17:33:E4:A0" + } + ] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if the subnet has flow logs enabled', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('The subnet has flow logs enabled') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [ + { + "cidrBlock": "10.0.1.0/24", + "compartmentId": "ocid1.tenancy.oc1.1111111111111", + "definedTags": {}, + "displayName": "subnet1", + "freeformTags": {}, + "id": "ocid1.subnet.oc1.iad.subnet1", + "lifecycleState": "AVAILABLE", + "securityListIds": [ + "ocid1.securitylist.oc1.iad.list11111" + ], + "timeCreated": "2019-02-28T18:19:38.677Z", + "vcnId": "ocid1.vcn.oc1.iad.vcn111111", + "virtualRouterIp": "10.0.1.1", + "virtualRouterMac": "00:00:17:33:E4:A0" + } + ] + ); + + plugin.run(cache, {}, callback); + }) + }) +}) \ No newline at end of file From c1883ed5d1bd88d88d85877084aaec3c9adcb0ab Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Sun, 17 Jul 2022 20:08:45 +0500 Subject: [PATCH 333/350] OCI - Cloud Guard Enabled Plugin --- collectors/oracle/collector.js | 9 ++ exports.js | 3 + helpers/oracle/regions.js | 3 +- other_modules/oci/services.json | 10 ++ .../oracle/cloudguard/cloudguardEnabled.js | 40 +++++++ .../cloudguard/cloudguardEnabled.spec.js | 104 ++++++++++++++++++ 6 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 plugins/oracle/cloudguard/cloudguardEnabled.js create mode 100644 plugins/oracle/cloudguard/cloudguardEnabled.spec.js diff --git a/collectors/oracle/collector.js b/collectors/oracle/collector.js index 4c3a0df0d3..7c62170ab3 100644 --- a/collectors/oracle/collector.js +++ b/collectors/oracle/collector.js @@ -99,6 +99,14 @@ var calls = { filterConfig: [true] } }, + cloudguardConfiguration: { + get: { + api: 'cloudguard', + filterKey: ['compartmentId'], + filterValue: ['compartmentId'], + restVersion: '/20200131', + } + }, group: { list: { api: 'iam', @@ -379,6 +387,7 @@ var postcalls = { limit: 900 } }, + waasPolicy: { get: { api: 'waas', diff --git a/exports.js b/exports.js index c7d33a4f9f..c7881cdc06 100644 --- a/exports.js +++ b/exports.js @@ -910,6 +910,9 @@ module.exports = { 'okePrivateEndpoint' : require(__dirname + '/plugins/oracle/oke/okePrivateEndpoint.js'), 'okeSecretsEncrypted' : require(__dirname + '/plugins/oracle/oke/okeSecretsEncrypted.js'), 'okeSecurityGroups' : require(__dirname + '/plugins/oracle/oke/okeSecurityGroups.js'), + + 'cloudguardEnabled' : require(__dirname + '/plugins/oracle/cloudguard/cloudguardEnabled.js'), + }, google: { 'excessiveFirewallRules' : require(__dirname + '/plugins/google/vpcnetwork/excessiveFirewallRules.js'), diff --git a/helpers/oracle/regions.js b/helpers/oracle/regions.js index 4e10c3b37b..7c09824701 100644 --- a/helpers/oracle/regions.js +++ b/helpers/oracle/regions.js @@ -83,5 +83,6 @@ module.exports = { customerSecretKey: ['default'], vault: regions, keys: regions, - cluster: regions + cluster: regions, + cloudguardConfiguration: ['default'] }; \ No newline at end of file diff --git a/other_modules/oci/services.json b/other_modules/oci/services.json index f578bb7c6d..7e27472fee 100644 --- a/other_modules/oci/services.json +++ b/other_modules/oci/services.json @@ -23,6 +23,16 @@ } } }, + "cloudguard": { + "cloudguardConfiguration": { + "get": { + "allowedQueryStrings": ["compartmentId"], + "method": "GET", + "path": "configuration", + "endpoint": "cloudguard-cp-api.{{region}}.oci.oraclecloud.com" + } + } + }, "oke": { "cluster": { "list": { diff --git a/plugins/oracle/cloudguard/cloudguardEnabled.js b/plugins/oracle/cloudguard/cloudguardEnabled.js new file mode 100644 index 0000000000..0ab883ecc4 --- /dev/null +++ b/plugins/oracle/cloudguard/cloudguardEnabled.js @@ -0,0 +1,40 @@ +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Cloud Guard Enabled', + category: 'Cloud Guard', + domain: 'Management and Governance', + description: 'Ensure Cloud Guard is enabled in the root compartment of the tenancy.', + more_info: 'Cloud Guard detects misconfigured resources and insecure activity within a tenancy and provides security administrators with the visibility to resolve these issues. Upon detection, Cloud Guard can suggest, assist, or take corrective actions to mitigate these issues.', + recommended_action: 'Cloud Guard should be enabled in the root compartment of your tenancy.', + link: 'https://docs.oracle.com/en-us/iaas/cloud-guard/using/index.htm', + apis: ['cloudguardConfiguration:get'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var region = helpers.objectFirstKey(cache['regionSubscription']['list']); + + if (helpers.checkRegionSubscription(cache, source, results, region)) { + + var config = helpers.addSource(cache, source, + ['cloudguardConfiguration', 'get', region]); + + if (!config) return callback(null, results, source); + + if (config.err) { + helpers.addResult(results, 3, + 'Unable to query for cloud guard configuration: ' + helpers.addError(config), region); + return callback(null, results, source); + } + if (config.data && Object.keys(config.data).length && config.data.status && config.data.status === 'ENABLED') { + helpers.addResult(results, 0, + 'Cloud Guard is enabled in the root compartment of the tenancy.', region); + } else { + helpers.addResult(results, 2, + 'Cloud Guard is not enabled in the root compartment of the tenancy.', region); + } + } + callback(null, results, source); + } +}; \ No newline at end of file diff --git a/plugins/oracle/cloudguard/cloudguardEnabled.spec.js b/plugins/oracle/cloudguard/cloudguardEnabled.spec.js new file mode 100644 index 0000000000..76d12bd2c6 --- /dev/null +++ b/plugins/oracle/cloudguard/cloudguardEnabled.spec.js @@ -0,0 +1,104 @@ +var expect = require('chai').expect; +var plugin = require('./cloudguardEnabled'); + +const createCache = (err, data) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + cloudguardConfiguration: { + get: { + 'us-ashburn-1': { + err: err, + data: data + } + } + } + } +}; + +describe('cloudguardEnabled', function () { + describe('run', function () { + it('should give unknown result if a configuration error is passed or no data is present', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for cloud guard configuration') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['error'], + null, + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result cloud guard is enabled in the root compartment of the tenancy', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('is enabled') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + { + reportingRegion: 'us-ashburn-1', + status: 'ENABLED', + selfManageResources: false + } + ); + + plugin.run(cache, {}, callback); + }) + it('should give failing result if cloud guard is not enabled in the root compartment of the tenancy', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('is not enabled') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + { + reportingRegion: 'us-ashburn-1', + status: 'DISABLED', + selfManageResources: false + } + ); + + plugin.run(cache, {}, callback); + }) + }) +}) \ No newline at end of file From dd541175bb3c9d636b5628c364947aa773c13e16 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Sat, 23 Jul 2022 19:08:22 +0500 Subject: [PATCH 334/350] Sync open source --- collectors/aws/collector_multipart.js | 4 +- helpers/aws/api_multipart.js | 124 ++++++++++-------- helpers/azure/functions.js | 26 ++-- package.json | 1 - .../alibaba/ack/networkPolicyEnabled.spec.js | 2 +- .../alibaba/apigateway/apiProtocol.spec.js | 1 - plugins/aws/iam/rolePolicyUnusedServices.js | 23 ++-- .../aws/lookout/modelDataEncrypted.spec.js | 1 - plugins/aws/msk/mskClusterPublicAccess.js | 2 +- .../timestreamDatabaseEncrypted.js | 4 +- .../logalerts/securityPolicyAlertsEnabled.js | 2 +- .../networksecuritygroups/openAllPorts.js | 2 +- plugins/azure/sqlserver/enableATP.js | 4 +- 13 files changed, 108 insertions(+), 88 deletions(-) diff --git a/collectors/aws/collector_multipart.js b/collectors/aws/collector_multipart.js index 95ba9a7d31..0aa6a9c822 100644 --- a/collectors/aws/collector_multipart.js +++ b/collectors/aws/collector_multipart.js @@ -27,9 +27,9 @@ var agent = new https.Agent({maxSockets: 100}); AWS.config.update({httpOptions: {agent: agent}}); var CALLS_CONFIG = { - TOTAL_PARTS: 13, + TOTAL_PARTS: 14, CALLS_PARTS: 4, - POSTCALLS_PARTS: 9 + POSTCALLS_PARTS: 10 }; var rateError = {message: 'rate', statusCode: 429}; diff --git a/helpers/aws/api_multipart.js b/helpers/aws/api_multipart.js index 73d5b92de6..03da22fd77 100644 --- a/helpers/aws/api_multipart.js +++ b/helpers/aws/api_multipart.js @@ -1166,18 +1166,6 @@ var postcalls = [ filterValue: 'Name' } }, - AutoScaling: { - describeNotificationConfigurations: { - reliesOnService: 'autoscaling', - reliesOnCall: 'describeAutoScalingGroups', - override: true - }, - describeLaunchConfigurations: { - reliesOnService: 'autoscaling', - reliesOnCall: 'describeAutoScalingGroups', - override: true - } - }, Backup: { getBackupVaultNotifications: { reliesOnService: 'backup', @@ -1450,17 +1438,6 @@ var postcalls = [ reliesOnCall: 'describeVpcs', override: true }, - describeSnapshotAttribute: { - reliesOnService: 'ec2', - reliesOnCall: 'describeSnapshots', - override: true - }, - describeVpcEndpointServicePermissions: { - reliesOnService: 'ec2', - reliesOnCall: 'describeVpcEndpointServices', - filterKey: 'ServiceId', - filterValue: 'ServiceId' - }, describeLaunchTemplateVersions: { reliesOnService: 'ec2', reliesOnCall: 'describeLaunchTemplates', @@ -1523,13 +1500,6 @@ var postcalls = [ override: true } }, - ElasticBeanstalk: { - describeConfigurationSettings: { - reliesOnService: 'elasticbeanstalk', - reliesOnCall: 'describeEnvironments', - override: true - } - }, ElasticTranscoder: { listJobsByPipeline: { reliesOnService: 'elastictranscoder', @@ -1544,11 +1514,6 @@ var postcalls = [ reliesOnCall: 'describeLoadBalancers', override: true }, - describeLoadBalancerAttributes: { - reliesOnService: 'elb', - reliesOnCall: 'describeLoadBalancers', - override: true - }, describeTags: { reliesOnService: 'elb', reliesOnCall: 'describeLoadBalancers', @@ -1562,21 +1527,6 @@ var postcalls = [ filterKey: 'TargetGroupArn', filterValue: 'TargetGroupArn' }, - describeLoadBalancerAttributes: { - reliesOnService: 'elbv2', - reliesOnCall: 'describeLoadBalancers', - override: true - }, - describeListeners: { - reliesOnService: 'elbv2', - reliesOnCall: 'describeLoadBalancers', - override: true - }, - describeTargetGroups: { - reliesOnService: 'elbv2', - reliesOnCall: 'describeLoadBalancers', - override: true - }, describeTargetGroupAttributes: { reliesOnService: 'elbv2', reliesOnCall: 'describeTargetGroups', @@ -1593,12 +1543,6 @@ var postcalls = [ reliesOnCall: 'listClusters', filterKey: 'ClusterId', filterValue: 'Id' - }, - listInstanceGroups: { - reliesOnService: 'emr', - reliesOnCall: 'listClusters', - filterKey: 'ClusterId', - filterValue: 'Id' } }, DLM: { @@ -1626,6 +1570,72 @@ var postcalls = [ } }, }, + { + EC2: { + describeSnapshotAttribute: { + reliesOnService: 'ec2', + reliesOnCall: 'describeSnapshots', + override: true + }, + describeVpcEndpointServicePermissions: { + reliesOnService: 'ec2', + reliesOnCall: 'describeVpcEndpointServices', + filterKey: 'ServiceId', + filterValue: 'ServiceId' + }, + }, + ElasticBeanstalk: { + describeConfigurationSettings: { + reliesOnService: 'elasticbeanstalk', + reliesOnCall: 'describeEnvironments', + override: true + } + }, + ELB: { + describeLoadBalancerAttributes: { + reliesOnService: 'elb', + reliesOnCall: 'describeLoadBalancers', + override: true + }, + }, + ELBv2: { + describeLoadBalancerAttributes: { + reliesOnService: 'elbv2', + reliesOnCall: 'describeLoadBalancers', + override: true + }, + describeListeners: { + reliesOnService: 'elbv2', + reliesOnCall: 'describeLoadBalancers', + override: true + }, + describeTargetGroups: { + reliesOnService: 'elbv2', + reliesOnCall: 'describeLoadBalancers', + override: true + }, + }, + EMR: { + listInstanceGroups: { + reliesOnService: 'emr', + reliesOnCall: 'listClusters', + filterKey: 'ClusterId', + filterValue: 'Id' + } + }, + AutoScaling: { + describeNotificationConfigurations: { + reliesOnService: 'autoscaling', + reliesOnCall: 'describeAutoScalingGroups', + override: true + }, + describeLaunchConfigurations: { + reliesOnService: 'autoscaling', + reliesOnCall: 'describeAutoScalingGroups', + override: true + } + }, + }, { CloudFormation: { describeStackEvents: { @@ -2157,7 +2167,7 @@ var postcalls = [ filterValue: 'DomainName' }, } - } + }, ]; module.exports = { diff --git a/helpers/azure/functions.js b/helpers/azure/functions.js index 57da0ce7eb..ea5c11c22a 100644 --- a/helpers/azure/functions.js +++ b/helpers/azure/functions.js @@ -54,7 +54,7 @@ function addResult(results, status, message, region, resource, custom) { }); } -function findOpenPorts(ngs, protocols, service, location, results) { +function findOpenPorts(ngs, protocols, service, location, results, checkAllPorts) { var openPrefix = ['*', '0.0.0.0', '0.0.0.0/0', '', '/0', '::/0', 'internet']; for (let sGroups of ngs) { @@ -103,12 +103,15 @@ function findOpenPorts(ngs, protocols, service, location, results) { strings.push(string); if (strings.indexOf(string) === -1) strings.push(string); } - } else if (parseInt(securityRule.properties['destinationPortRange']) === port || - securityRule.properties['destinationPortRange'] === port || - securityRule.properties['destinationPortRange'] === '*') { + } else if (parseInt(securityRule.properties['destinationPortRange']) === port) { var string = `Security Rule "` + securityRule['name'] + `": ` + (protocol === '*' ? `All protocols` : protocol.toUpperCase()) + (ports === '*' ? ` and all ports` : ` port ` + ports) + ` open to ` + sourceFilter; if (strings.indexOf(string) === -1) strings.push(string); + } else if (checkAllPorts && + openPrefix.includes(securityRule.properties['destinationPortRange'])) { + var openAllstring = `Security Rule "` + securityRule['name'] + `": ` + (protocol === '*' ? `All protocols` : protocol.toUpperCase()) + + (ports === '*' ? ` and all ports` : ` port ` + ports) + ` open to ` + sourceFilter; + if (strings.indexOf(openAllstring) === -1) strings.push(openAllstring); } } else if (securityRule.properties['destinationPortRanges']) { if (securityRule.properties['destinationPortRanges'].indexOf(port.toString()) > -1) { @@ -211,7 +214,7 @@ function checkPolicyAssignment(policyAssignments, param, text, results, location } } -function checkLogAlerts(activityLogAlerts, conditionResource, text, results, location) { +function checkLogAlerts(activityLogAlerts, conditionResource, text, results, location, parentConditionResource) { if (!activityLogAlerts) return; if (activityLogAlerts.err || !activityLogAlerts.data) { @@ -241,11 +244,18 @@ function checkLogAlerts(activityLogAlerts, conditionResource, text, results, loc if (!allConditions || !allConditions.allOf || !allConditions.allOf.length) continue; - var conditionOperation = allConditions.allOf.filter((d) => { - return (d.equals && d.equals.toLowerCase().indexOf(conditionResource) > -1); + return (d.equals && d.equals.toLowerCase().indexOf(conditionResource) > -1 || + (parentConditionResource && d.equals && d.equals.toLowerCase().indexOf(parentConditionResource) > -1)); }); + if (conditionOperation && conditionOperation.length) { + if (conditionResource.includes('microsoft.security') && allConditions.allOf.every(condition => condition.field && condition.field == 'category' && + condition.equals && condition.equals.toLowerCase() == 'security')) { + alertCreateUpdateEnabled = (!alertCreateUpdateEnabled && activityLogAlertResource.enabled ? true : alertCreateUpdateEnabled); + break; + } + allConditions.allOf.forEach(condition => { if (condition.field && (condition.field === 'resourceType') && (condition.equals && (condition.equals.toLowerCase() === conditionResource))) { alertCreateDeleteEnabled = (!alertCreateDeleteEnabled && activityLogAlertResource.enabled ? true : alertCreateDeleteEnabled); @@ -254,7 +264,7 @@ function checkLogAlerts(activityLogAlerts, conditionResource, text, results, loc } else if (condition.equals && condition.equals.toLowerCase().indexOf(conditionResource + '/delete') > -1) { alertDeleteEnabled = (!alertDeleteEnabled && activityLogAlertResource.enabled ? true : alertDeleteEnabled); } - }) + }); } } diff --git a/package.json b/package.json index ce5529b0e4..b76e257faa 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,6 @@ "azure-storage": "^2.10.3", "csv-write-stream": "^2.0.0", "fast-safe-stringify": "^2.0.6", - "googleapis": "^76.0.0", "minimatch": "^3.0.4", "ms-rest-azure": "^2.6.0", "tty-table": "^4.1.3" diff --git a/plugins/alibaba/ack/networkPolicyEnabled.spec.js b/plugins/alibaba/ack/networkPolicyEnabled.spec.js index 2a31410f79..3a56f07da7 100644 --- a/plugins/alibaba/ack/networkPolicyEnabled.spec.js +++ b/plugins/alibaba/ack/networkPolicyEnabled.spec.js @@ -4,7 +4,7 @@ var networkPolicyEnabled = require('./networkPolicyEnabled.js'); const describeClusters = [ { "name": "aqua-cluster2", - "cluster_id": "cc377f7509590489da921de83a1cad919", + "cluster_id": "cc377f7509590489da921de83a1cad918", "size": 2, "region_id": "us-west-1", "state": "initial", diff --git a/plugins/alibaba/apigateway/apiProtocol.spec.js b/plugins/alibaba/apigateway/apiProtocol.spec.js index 32781510ff..e06148c861 100644 --- a/plugins/alibaba/apigateway/apiProtocol.spec.js +++ b/plugins/alibaba/apigateway/apiProtocol.spec.js @@ -185,7 +185,6 @@ describe('apiProtocol', () => { it('should PASS if API has HTTPS protocol configured', done => { const cache = createCache([describeApis], describeApi[0]); apiProtocol.run(cache, {}, (err, results) => { - console.log(results); expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); expect(results[0].message).to.include('API has HTTPS protocol configured'); diff --git a/plugins/aws/iam/rolePolicyUnusedServices.js b/plugins/aws/iam/rolePolicyUnusedServices.js index bd9d2b76e6..4dec0097cd 100644 --- a/plugins/aws/iam/rolePolicyUnusedServices.js +++ b/plugins/aws/iam/rolePolicyUnusedServices.js @@ -193,15 +193,17 @@ module.exports = { allResources = allResources.reduce((result, resource) => { let arr = resource.resourceType.split(':'); - let service = arr[2].toLowerCase(); - let subService = arr[4].toLowerCase(); - result[service] = result[service] || []; + if (arr.length && arr.length > 5) { + let service = arr[2].toLowerCase(); + let subService = arr[4].toLowerCase(); + result[service] = result[service] || []; - if (resource.count > 0 && (allServices[service] && allServices[service].includes(subService))) { - result[service].push(subService); - } + if (resource.count > 0 && (allServices[service] && allServices[service].includes(subService))) { + result[service].push(subService); + } - return result; + return result; + } }, {}); var listRoles = helpers.addSource(cache, source, @@ -301,8 +303,8 @@ module.exports = { for (let statement of statements) { if (statement.Action && statement.Action.length) { for (let action of statement.Action) { - let service = action.split(':')[0].toLowerCase(); - let resourceAction = action.split(':')[1].toLowerCase(); + let service = action.split(':')[0] ? action.split(':')[0].toLowerCase() : ''; + let resourceAction = action.split(':')[1] ? action.split(':')[1].toLowerCase() : ''; if (allServices[service]) { for (let supportedResource of allServices[service]) { @@ -339,7 +341,8 @@ module.exports = { if (!statements) break; for (let statement of statements) { - if ((statement.Action && statement.Action.length === 1 && statement.Action[0] === '*') && (statement.Resource && statement.Resource.length === 1 && statement.Resource[0] === '*')) { + if ((statement.Action && statement.Action.length && statement.Action[0] === '*') || + (statement.Resource && statement.Resource.length && statement.Resource[0] === '*')) { continue; } diff --git a/plugins/aws/lookout/modelDataEncrypted.spec.js b/plugins/aws/lookout/modelDataEncrypted.spec.js index c1bd822b8c..86ae41a5e5 100644 --- a/plugins/aws/lookout/modelDataEncrypted.spec.js +++ b/plugins/aws/lookout/modelDataEncrypted.spec.js @@ -173,7 +173,6 @@ describe('modelDataEncrypted', function () { it('should PASS if LookoutVision model data is encrypted with desired level', function (done) { const cache = createCache([listProjects[0]], [listModels[1]], describeModel[1], listKeys, describeKey[0]); modelDataEncrypted.run(cache, { model_data_desired_encryption_level: 'awscmk' }, (err, results) => { - console.log(results); expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); expect(results[0].region).to.equal('us-east-1'); diff --git a/plugins/aws/msk/mskClusterPublicAccess.js b/plugins/aws/msk/mskClusterPublicAccess.js index 5336dad6b1..ac5301b4ac 100644 --- a/plugins/aws/msk/mskClusterPublicAccess.js +++ b/plugins/aws/msk/mskClusterPublicAccess.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Compute', severity: 'Medium', description: 'Ensure that public access feature within the cluster is disabled for your Amazon MSK clusters.', - more_info: 'Amazon MSK gives you the option to turn on public access to the brokers of MSK clusters running Apache Kafka 2.6.0 or later versions. For security reasons, you can'/'t turn on public access while creating an MSK cluster. However, you can update an existing cluster to make it publicly accessible.', + more_info: 'Amazon MSK gives you the option to turn on public access to the brokers of MSK clusters running Apache Kafka 2.6.0 or later versions. For security reasons, you cannot turn on public access while creating an MSK cluster. However, you can update an existing cluster to make it publicly accessible.', link: 'https://docs.aws.amazon.com/msk/latest/developerguide/public-access.html', recommended_action: 'Check for public access feature within the cluster for all MSK clusters', apis: ['Kafka:listClusters'], diff --git a/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js b/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js index 2e7bfe3535..339d2b1187 100644 --- a/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js +++ b/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js @@ -2,14 +2,14 @@ var async = require('async'); var helpers = require('../../../helpers/aws'); module.exports = { - title: ' Timestream Database Encrypted', + title: 'Timestream Database Encrypted', category: 'Timestream', domain: 'Databases', description: 'Ensure that AWS Timestream databases are encrypted with KMS Customer Master Keys (CMKs) instead of AWS managed-keys.', more_info: 'Timestream encryption at rest provides enhanced security by encrypting all your data at rest using encryption keys. ' + 'This functionality helps reduce the operational burden and complexity involved in protecting sensitive data. ' + 'With encryption at rest using customer-managed keys, you can build security-sensitive applications that meet strict encryption compliance and regulatory requirements. ', - recommended_action: 'Modify Trimestream database encryption configuration to use desired encryption key', + recommended_action: 'Modify Timestream database encryption configuration to use desired encryption key', link: 'https://docs.aws.amazon.com/timestream/latest/developerguide/EncryptionAtRest.html', apis: ['TimestreamWrite:listDatabases', 'KMS:describeKey', 'KMS:listKeys'], settings: { diff --git a/plugins/azure/logalerts/securityPolicyAlertsEnabled.js b/plugins/azure/logalerts/securityPolicyAlertsEnabled.js index e24e3203a2..19e3784b2b 100644 --- a/plugins/azure/logalerts/securityPolicyAlertsEnabled.js +++ b/plugins/azure/logalerts/securityPolicyAlertsEnabled.js @@ -25,7 +25,7 @@ module.exports = { var activityLogAlerts = helpers.addSource(cache, source, ['activityLogAlerts', 'listBySubscriptionId', location]); - helpers.checkLogAlerts(activityLogAlerts, conditionResource, text, results, location); + helpers.checkLogAlerts(activityLogAlerts, conditionResource, text, results, location, 'security'); rcb(); }, function() { diff --git a/plugins/azure/networksecuritygroups/openAllPorts.js b/plugins/azure/networksecuritygroups/openAllPorts.js index a53556db8e..db03e93d54 100644 --- a/plugins/azure/networksecuritygroups/openAllPorts.js +++ b/plugins/azure/networksecuritygroups/openAllPorts.js @@ -51,7 +51,7 @@ module.exports = { let service = 'All Ports'; - helpers.findOpenPorts(networkSecurityGroups.data, ports, service, location, results); + helpers.findOpenPorts(networkSecurityGroups.data, ports, service, location, results, true); rcb(); }, function() { diff --git a/plugins/azure/sqlserver/enableATP.js b/plugins/azure/sqlserver/enableATP.js index a660401bd6..612779cf02 100644 --- a/plugins/azure/sqlserver/enableATP.js +++ b/plugins/azure/sqlserver/enableATP.js @@ -2,11 +2,11 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); module.exports = { - title: 'Advanced Threat Protection Enabled', + title: 'SQL Server Advanced Threat Protection Enabled', category: 'SQL Server', domain: 'Databases', description: 'Ensures that Advanced Threat Protection is enabled on SQL Servers.', - more_info: 'Azure Defender for SQL is a unified package for advanced SQL security capabilities. Azure Defender is available for Azure SQL Database, Azure SQL Managed Instance, and Azure Synapse Analytics. It includes functionality for discovering and classifying sensitive data, surfacing and mitigating potential database vulnerabilities, and detecting anomalous activities that could indicate a threat to your database. It provides a single go-to location for enabling and managing these capabilities.', + more_info: 'Azure Defender for SQL is a unified package for advanced SQL security capabilities.', recommended_action: 'Ensure that ThreatDetectionState is set to Enabled', link: 'https://docs.microsoft.com/en-us/azure/azure-sql/database/azure-defender-for-sql', apis: ['servers:listSql', 'advancedThreatProtectionSettings:listByServer'], From fd2455c63e2c8d933d5ec953a5ccd66f26e4d94f Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Sat, 23 Jul 2022 19:15:15 +0500 Subject: [PATCH 335/350] added google-auth-library --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index b76e257faa..0e44d67cb8 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "azure-storage": "^2.10.3", "csv-write-stream": "^2.0.0", "fast-safe-stringify": "^2.0.6", + "google-auth-library": "^8.1.1", "minimatch": "^3.0.4", "ms-rest-azure": "^2.6.0", "tty-table": "^4.1.3" From ca70d2803e5a416e28e1c2f88af7981bb9be8086 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Thu, 28 Jul 2022 20:45:38 +0500 Subject: [PATCH 336/350] Apply suggestions from code review --- plugins/oracle/vaults/keyRotation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oracle/vaults/keyRotation.js b/plugins/oracle/vaults/keyRotation.js index c4e784dd16..f3d5aaaac5 100644 --- a/plugins/oracle/vaults/keyRotation.js +++ b/plugins/oracle/vaults/keyRotation.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/oracle'); module.exports = { title: 'Key Rotation', category: 'Vaults', - domain: 'Management and Governance', + domain: 'Application Integration', description: 'Ensure that your OCI Vault Keys are periodically rotated.', more_info: 'Rotating keys periodically limits the data encrypted under one key version. Key rotation thereby reduces the risk in case a key is ever compromised.', link: 'https://docs.oracle.com/en-us/iaas/Content/KeyManagement/Tasks/managingkeys.htm', From 28099fc1f60cff009eba5a61d2f222fe3472ecc5 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Thu, 28 Jul 2022 20:57:52 +0500 Subject: [PATCH 337/350] Apply suggestions from code review --- plugins/oracle/identity/iamGroupChanges.js | 2 +- plugins/oracle/identity/iamPolicyChanges.js | 2 +- plugins/oracle/identity/identityProviderChanges.js | 2 +- plugins/oracle/identity/idpGroupMappingChanges.js | 2 +- plugins/oracle/networking/securityListChanges.js | 2 +- plugins/oracle/networking/vcnChanges.js | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/oracle/identity/iamGroupChanges.js b/plugins/oracle/identity/iamGroupChanges.js index e62c9d1f72..08cf147ba5 100644 --- a/plugins/oracle/identity/iamGroupChanges.js +++ b/plugins/oracle/identity/iamGroupChanges.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/oracle'); module.exports = { title: 'IAM Group Changes', category: 'Identity', - domain: 'Management and Governance', + domain: 'Identity and Access Management', description: 'Ensure an event rule is configured for IAM Group changes.', more_info: 'Monitoring changes to IAM groups like create, update and delete will help in identifying changes to satisfy least privilege principle.', link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', diff --git a/plugins/oracle/identity/iamPolicyChanges.js b/plugins/oracle/identity/iamPolicyChanges.js index 7a24555edc..99c085959a 100644 --- a/plugins/oracle/identity/iamPolicyChanges.js +++ b/plugins/oracle/identity/iamPolicyChanges.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/oracle'); module.exports = { title: 'IAM Policy Changes', category: 'Identity', - domain: 'Management and Governance', + domain: 'Identity and Access Management', description: 'Ensure an event rule is configured for IAM Policy changes.', more_info: 'Monitoring changes to IAM policies like create, update and delete will help in identifying changes to the security posture.', link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', diff --git a/plugins/oracle/identity/identityProviderChanges.js b/plugins/oracle/identity/identityProviderChanges.js index 107c544f1d..623c7c019a 100644 --- a/plugins/oracle/identity/identityProviderChanges.js +++ b/plugins/oracle/identity/identityProviderChanges.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/oracle'); module.exports = { title: 'Identity Provider Changes', category: 'Identity', - domain: 'Management and Governance', + domain: 'Identity and Access Management', description: 'Ensure an event rule is configured for Identity Provider changes.', more_info: 'Monitoring Identity Provider changes like create, update and delete will help in identifying changes to the security posture.', link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', diff --git a/plugins/oracle/identity/idpGroupMappingChanges.js b/plugins/oracle/identity/idpGroupMappingChanges.js index 231024cbe2..cb041b7465 100644 --- a/plugins/oracle/identity/idpGroupMappingChanges.js +++ b/plugins/oracle/identity/idpGroupMappingChanges.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/oracle'); module.exports = { title: 'Idp Group Mapping Changes', category: 'Identity', - domain: 'Management and Governance', + domain: 'Identity and Access Management', description: 'Ensure an event rule is configured for Idp Group Mapping changes.', more_info: 'Monitoring changes to Identity Provider Group Mappings like create, update and delete will help in identifying changes to the security posture.', link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', diff --git a/plugins/oracle/networking/securityListChanges.js b/plugins/oracle/networking/securityListChanges.js index e8d7a80e2f..aeb1fa1b70 100644 --- a/plugins/oracle/networking/securityListChanges.js +++ b/plugins/oracle/networking/securityListChanges.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/oracle'); module.exports = { title: 'Security List Changes', category: 'Networking', - domain: 'Management and Governance', + domain: 'Network Access Control', description: 'Ensure an event rule is configured for security list changes.', more_info: 'Monitoring changes to security lists like create, update and delete will help in identifying changes to the security controls.', link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', diff --git a/plugins/oracle/networking/vcnChanges.js b/plugins/oracle/networking/vcnChanges.js index 79d6febb7d..cb8b6db229 100644 --- a/plugins/oracle/networking/vcnChanges.js +++ b/plugins/oracle/networking/vcnChanges.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/oracle'); module.exports = { title: 'VCN Changes', category: 'Networking', - domain: 'Management and Governance', + domain: 'Network Access Control', description: 'Ensure an event rule is configured for VCN changes.', more_info: 'Monitoring changes to VCNs will help in identifying changes to the security posture.', link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', From 2d64b25da357634a9a593a8a53b718886b05dc46 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Thu, 28 Jul 2022 20:58:24 +0500 Subject: [PATCH 338/350] Update plugins/oracle/identity/userChanges.js --- plugins/oracle/identity/userChanges.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oracle/identity/userChanges.js b/plugins/oracle/identity/userChanges.js index 1c56a7e553..4c38df7891 100644 --- a/plugins/oracle/identity/userChanges.js +++ b/plugins/oracle/identity/userChanges.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/oracle'); module.exports = { title: 'User Changes', category: 'Identity', - domain: 'Management and Governance', + domain: 'Identity and Access Management', description: 'Ensure an event rule is configured for User changes.', more_info: 'Monitoring changes to users and their states and capabilities will help in identifying changes to the security posture.', link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', From 623e0dc73905eef8504e75a6d87de5885f6f27a3 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Thu, 28 Jul 2022 20:58:57 +0500 Subject: [PATCH 339/350] Apply suggestions from code review --- plugins/oracle/networking/networkGatewayChanges.js | 2 +- plugins/oracle/networking/routeTableChanges.js | 2 +- plugins/oracle/networking/securityGroupChanges.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/oracle/networking/networkGatewayChanges.js b/plugins/oracle/networking/networkGatewayChanges.js index 90bc32c683..d79b90e82a 100644 --- a/plugins/oracle/networking/networkGatewayChanges.js +++ b/plugins/oracle/networking/networkGatewayChanges.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/oracle'); module.exports = { title: 'Network Gateway Changes', category: 'Networking', - domain: 'Management and Governance', + domain: 'Network Access Control', description: 'Ensure an event rule is configured for network gateway changes.', more_info: 'Monitoring changes to Network Gateways like create, update and delete will help in identifying changes to the security posture.', link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', diff --git a/plugins/oracle/networking/routeTableChanges.js b/plugins/oracle/networking/routeTableChanges.js index 045d981490..172540c7b4 100644 --- a/plugins/oracle/networking/routeTableChanges.js +++ b/plugins/oracle/networking/routeTableChanges.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/oracle'); module.exports = { title: 'Route Table Changes', category: 'Networking', - domain: 'Management and Governance', + domain: 'Network Access Control', description: 'Ensure an event rule is configured for route table changes.', more_info: 'Monitoring changes to route tables like create, update and delete will help in identifying changes to the traffic flows.', link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', diff --git a/plugins/oracle/networking/securityGroupChanges.js b/plugins/oracle/networking/securityGroupChanges.js index 24ba58837f..85796ccbc6 100644 --- a/plugins/oracle/networking/securityGroupChanges.js +++ b/plugins/oracle/networking/securityGroupChanges.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/oracle'); module.exports = { title: 'Security Group Changes', category: 'Networking', - domain: 'Management and Governance', + domain: 'Network Access Control', description: 'Ensure an event rule is configured for security group changes.', more_info: 'Monitoring changes to security groups like create, update and delete will help in identifying changes to the security controls.', link: 'https://docs.oracle.com/en-us/iaas/Content/Events/Task/managingrules.htm', From 3185c5dfd52c7f807373f86000c76db4921cdf34 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Thu, 28 Jul 2022 22:06:16 +0500 Subject: [PATCH 340/350] updated remediation min version --- plugins/google/cloudfunctions/httpTriggerRequireHttps.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/google/cloudfunctions/httpTriggerRequireHttps.js b/plugins/google/cloudfunctions/httpTriggerRequireHttps.js index 7208b403ce..57ee6129d4 100644 --- a/plugins/google/cloudfunctions/httpTriggerRequireHttps.js +++ b/plugins/google/cloudfunctions/httpTriggerRequireHttps.js @@ -10,7 +10,7 @@ module.exports = { link: 'https://cloud.google.com/functions/docs/writing/http', recommended_action: 'Ensure that your Google Cloud functions always require HTTPS.', apis: ['functions:list', 'projects:get'], - remediation_min_version: '202202132132', + remediation_min_version: '202207282132', remediation_description: 'All Google Cloud Functions will be configured to require HTTPS for HTTP invocations.', apis_remediate: ['functions:list', 'projects:get'], actions: {remediate:['CloudFunctionsService.UpdateFunction'], rollback:['CloudFunctionsService.UpdateFunction']}, From 374f28c8eb226f6b137a67b86dab095a83b466a4 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Thu, 28 Jul 2022 22:07:46 +0500 Subject: [PATCH 341/350] updated remediation min version --- plugins/google/storage/bucketUniformAccess.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/google/storage/bucketUniformAccess.js b/plugins/google/storage/bucketUniformAccess.js index a923f8f3bd..cc5a996ccf 100644 --- a/plugins/google/storage/bucketUniformAccess.js +++ b/plugins/google/storage/bucketUniformAccess.js @@ -10,7 +10,7 @@ module.exports = { link: 'https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use', recommended_action: 'Make sure that storage buckets have uniform level access enabled', apis: ['buckets:list'], - remediation_min_version: '202202071836', + remediation_min_version: '202207281836', remediation_description: 'Unfiorm Level Access will be enabled on all storage buckets', apis_remediate: ['buckets:list'], actions: {remediate:['storage.buckets.update'], rollback:['storage.buckets.update']}, From e7045ddf4a970f87e244f57a1590a0a4c5df2453 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Thu, 28 Jul 2022 22:09:16 +0500 Subject: [PATCH 342/350] updated remediation min version --- plugins/google/storage/bucketVersioning.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/google/storage/bucketVersioning.js b/plugins/google/storage/bucketVersioning.js index ab17dccb77..a764c0e38b 100644 --- a/plugins/google/storage/bucketVersioning.js +++ b/plugins/google/storage/bucketVersioning.js @@ -10,7 +10,7 @@ module.exports = { link: 'https://cloud.google.com/storage/docs/using-object-versioning', recommended_action: 'Bucket Versioning can only be enabled by using the Command Line Interface, use this command to enable Versioning: gsutil versioning set on gs://[BUCKET_NAME]', apis: ['buckets:list'], - remediation_min_version: '202201291836', + remediation_min_version: '202207281836', remediation_description: 'Bucket versioning will be enabled on storage buckets', apis_remediate: ['buckets:list'], actions: {remediate:['storage.buckets.update'], rollback:['storage.buckets.update']}, From 75e359fcdc1d4e92cc7e8859f18009c2f58daf77 Mon Sep 17 00:00:00 2001 From: mehakseedat63 Date: Thu, 28 Jul 2022 22:14:16 +0500 Subject: [PATCH 343/350] updated remediation min version --- plugins/google/cloudresourcemanager/detailedAuditLoggingMode.js | 2 +- .../google/cloudresourcemanager/disableAutomaticIAMGrants.js | 2 +- plugins/google/cloudresourcemanager/disableDefaultEncryption.js | 2 +- plugins/google/cloudresourcemanager/disableGuestAttributes.js | 2 +- .../cloudresourcemanager/disableIdentityClusterCreation.js | 2 +- plugins/google/cloudresourcemanager/disableKeyCreation.js | 2 +- plugins/google/cloudresourcemanager/disableKeyUpload.js | 2 +- plugins/google/cloudresourcemanager/disableSerialPortAccess.js | 2 +- plugins/google/cloudresourcemanager/requireOsLogin.js | 2 +- .../google/cloudresourcemanager/restrictAuthorizedNetworks.js | 2 +- .../google/cloudresourcemanager/skipDefaultNetworkCreation.js | 2 +- plugins/google/cloudresourcemanager/uniformBucketLevelAccess.js | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/plugins/google/cloudresourcemanager/detailedAuditLoggingMode.js b/plugins/google/cloudresourcemanager/detailedAuditLoggingMode.js index 784d4da169..d3eec289cc 100644 --- a/plugins/google/cloudresourcemanager/detailedAuditLoggingMode.js +++ b/plugins/google/cloudresourcemanager/detailedAuditLoggingMode.js @@ -9,7 +9,7 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Detailed Audit Logging Mode" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], - remediation_min_version: '202202140432', + remediation_min_version: '202207280432', remediation_description: 'The "Detailed Audit Logging Mode" constraint will be enforced at the organization level.', apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, diff --git a/plugins/google/cloudresourcemanager/disableAutomaticIAMGrants.js b/plugins/google/cloudresourcemanager/disableAutomaticIAMGrants.js index 7270b6909a..c9c77102b7 100644 --- a/plugins/google/cloudresourcemanager/disableAutomaticIAMGrants.js +++ b/plugins/google/cloudresourcemanager/disableAutomaticIAMGrants.js @@ -9,7 +9,7 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Disable Automatic IAM Grants for Default Service Accounts" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], - remediation_min_version: '202202140432', + remediation_min_version: '202207280432', remediation_description: 'The "Disable Automatic IAM Grants for Default Service Accounts" constraint will be enforced at the organization level.', apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, diff --git a/plugins/google/cloudresourcemanager/disableDefaultEncryption.js b/plugins/google/cloudresourcemanager/disableDefaultEncryption.js index 1924ec5793..517facb354 100644 --- a/plugins/google/cloudresourcemanager/disableDefaultEncryption.js +++ b/plugins/google/cloudresourcemanager/disableDefaultEncryption.js @@ -9,7 +9,7 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Restrict Default Google-Managed Encryption for Cloud SQL Instances" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], - remediation_min_version: '202202140432', + remediation_min_version: '202207280432', remediation_description: 'The "Restrict Default Google-Managed Encryption for Cloud SQL Instances" constraint will be enforced at the organization level.', apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, diff --git a/plugins/google/cloudresourcemanager/disableGuestAttributes.js b/plugins/google/cloudresourcemanager/disableGuestAttributes.js index 935ca3d040..f52510ed5b 100644 --- a/plugins/google/cloudresourcemanager/disableGuestAttributes.js +++ b/plugins/google/cloudresourcemanager/disableGuestAttributes.js @@ -9,7 +9,7 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Disable Guest Attributes of Compute Engine Metadata" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], - remediation_min_version: '202202200432', + remediation_min_version: '202207280432', remediation_description: 'The "Disable Guest Attributes of Compute Engine Metadata" constraint will be enforced at the organization level.', apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, diff --git a/plugins/google/cloudresourcemanager/disableIdentityClusterCreation.js b/plugins/google/cloudresourcemanager/disableIdentityClusterCreation.js index ae1e987c62..26cef30c62 100644 --- a/plugins/google/cloudresourcemanager/disableIdentityClusterCreation.js +++ b/plugins/google/cloudresourcemanager/disableIdentityClusterCreation.js @@ -9,7 +9,7 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Disable Workload Identity Cluster Creation" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], - remediation_min_version: '202202200432', + remediation_min_version: '202207280432', remediation_description: 'The "Disable Workload Identity Cluster Creation" constraint will be enforced at the organization level.', apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, diff --git a/plugins/google/cloudresourcemanager/disableKeyCreation.js b/plugins/google/cloudresourcemanager/disableKeyCreation.js index d895aa4e63..41d5bb62cc 100644 --- a/plugins/google/cloudresourcemanager/disableKeyCreation.js +++ b/plugins/google/cloudresourcemanager/disableKeyCreation.js @@ -9,7 +9,7 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Disable Service Account Key Creation" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], - remediation_min_version: '202202200432', + remediation_min_version: '202207280432', remediation_description: 'The "Disable Service Account Key Creation" constraint will be enforced at the organization level.', apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, diff --git a/plugins/google/cloudresourcemanager/disableKeyUpload.js b/plugins/google/cloudresourcemanager/disableKeyUpload.js index 99c610ef6f..9f469b6fc4 100644 --- a/plugins/google/cloudresourcemanager/disableKeyUpload.js +++ b/plugins/google/cloudresourcemanager/disableKeyUpload.js @@ -9,7 +9,7 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Disable Service Account Key Upload" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], - remediation_min_version: '202202200432', + remediation_min_version: '202207280432', remediation_description: 'The "Disable Service Account Key Upload" constraint will be enforced at the organization level.', apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, diff --git a/plugins/google/cloudresourcemanager/disableSerialPortAccess.js b/plugins/google/cloudresourcemanager/disableSerialPortAccess.js index b9cc4b77ab..db8cc27141 100644 --- a/plugins/google/cloudresourcemanager/disableSerialPortAccess.js +++ b/plugins/google/cloudresourcemanager/disableSerialPortAccess.js @@ -9,7 +9,7 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Disable VM serial port access" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], - remediation_min_version: '202202140432', + remediation_min_version: '202207280432', remediation_description: 'The "Disable VM serial port access" constraint will be enforced at the organization level.', apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, diff --git a/plugins/google/cloudresourcemanager/requireOsLogin.js b/plugins/google/cloudresourcemanager/requireOsLogin.js index a68ef3c303..e3a1efd2cd 100644 --- a/plugins/google/cloudresourcemanager/requireOsLogin.js +++ b/plugins/google/cloudresourcemanager/requireOsLogin.js @@ -9,7 +9,7 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Require OS Login" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], - remediation_min_version: '202202140432', + remediation_min_version: '202207280432', remediation_description: 'The "Require OS Login" constraint will be enforced at the organization level.', apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, diff --git a/plugins/google/cloudresourcemanager/restrictAuthorizedNetworks.js b/plugins/google/cloudresourcemanager/restrictAuthorizedNetworks.js index b947f57d61..a81ed4b5fb 100644 --- a/plugins/google/cloudresourcemanager/restrictAuthorizedNetworks.js +++ b/plugins/google/cloudresourcemanager/restrictAuthorizedNetworks.js @@ -9,7 +9,7 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Restrict Authorized Networks on Cloud SQL instances" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], - remediation_min_version: '202202140432', + remediation_min_version: '202207280432', remediation_description: 'The "Restrict Authorized Networks on Cloud SQL instances" constraint will be enforced at the organization level.', apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, diff --git a/plugins/google/cloudresourcemanager/skipDefaultNetworkCreation.js b/plugins/google/cloudresourcemanager/skipDefaultNetworkCreation.js index 31bc2e297d..f92fe98a70 100644 --- a/plugins/google/cloudresourcemanager/skipDefaultNetworkCreation.js +++ b/plugins/google/cloudresourcemanager/skipDefaultNetworkCreation.js @@ -10,7 +10,7 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Skip Default Network Creation" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], - remediation_min_version: '202202140432', + remediation_min_version: '202207280432', remediation_description: 'The "Skip Default Network Creation" constraint will be enforced at the organization level.', apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, diff --git a/plugins/google/cloudresourcemanager/uniformBucketLevelAccess.js b/plugins/google/cloudresourcemanager/uniformBucketLevelAccess.js index 475208e8d7..b3d4ec233f 100644 --- a/plugins/google/cloudresourcemanager/uniformBucketLevelAccess.js +++ b/plugins/google/cloudresourcemanager/uniformBucketLevelAccess.js @@ -9,7 +9,7 @@ module.exports = { link: 'https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints', recommended_action: 'Ensure that "Enforce uniform bucket-level access" constraint is enforced at the organization level.', apis: ['organizations:list', 'organizations:listOrgPolicies'], - remediation_min_version: '202202140432', + remediation_min_version: '202207280432', remediation_description: 'The "Enforce uniform bucket-level access" constraint will be enforced at the organization level.', apis_remediate: ['organizations:list', 'organizations:listOrgPolicies'], actions: {remediate:['SetOrgPolicy'], rollback:['SetOrgPolicy']}, From c8fc684cbbb32b0e94ba038009dfd370f5fbf9ac Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 29 Jul 2022 14:59:49 +0500 Subject: [PATCH 344/350] Syncing with SAAS --- collectors/aws/collector_multipart.js | 4 +- helpers/aws/api_multipart.js | 124 ++++---- helpers/azure/functions.js | 26 +- package.json | 1 - .../alibaba/ack/networkPolicyEnabled.spec.js | 2 +- .../alibaba/apigateway/apiProtocol.spec.js | 1 - plugins/aws/ecr/ecrRepositoryPolicy.js | 4 +- plugins/aws/iam/rolePolicyUnusedServices.js | 299 +++++++++--------- .../aws/lookout/modelDataEncrypted.spec.js | 1 - plugins/aws/msk/mskClusterPublicAccess.js | 2 +- .../timestreamDatabaseEncrypted.js | 4 +- .../logalerts/securityPolicyAlertsEnabled.js | 2 +- .../networksecuritygroups/openAllPorts.js | 2 +- plugins/azure/sqlserver/enableATP.js | 4 +- 14 files changed, 250 insertions(+), 226 deletions(-) diff --git a/collectors/aws/collector_multipart.js b/collectors/aws/collector_multipart.js index 95ba9a7d31..0aa6a9c822 100644 --- a/collectors/aws/collector_multipart.js +++ b/collectors/aws/collector_multipart.js @@ -27,9 +27,9 @@ var agent = new https.Agent({maxSockets: 100}); AWS.config.update({httpOptions: {agent: agent}}); var CALLS_CONFIG = { - TOTAL_PARTS: 13, + TOTAL_PARTS: 14, CALLS_PARTS: 4, - POSTCALLS_PARTS: 9 + POSTCALLS_PARTS: 10 }; var rateError = {message: 'rate', statusCode: 429}; diff --git a/helpers/aws/api_multipart.js b/helpers/aws/api_multipart.js index 73d5b92de6..03da22fd77 100644 --- a/helpers/aws/api_multipart.js +++ b/helpers/aws/api_multipart.js @@ -1166,18 +1166,6 @@ var postcalls = [ filterValue: 'Name' } }, - AutoScaling: { - describeNotificationConfigurations: { - reliesOnService: 'autoscaling', - reliesOnCall: 'describeAutoScalingGroups', - override: true - }, - describeLaunchConfigurations: { - reliesOnService: 'autoscaling', - reliesOnCall: 'describeAutoScalingGroups', - override: true - } - }, Backup: { getBackupVaultNotifications: { reliesOnService: 'backup', @@ -1450,17 +1438,6 @@ var postcalls = [ reliesOnCall: 'describeVpcs', override: true }, - describeSnapshotAttribute: { - reliesOnService: 'ec2', - reliesOnCall: 'describeSnapshots', - override: true - }, - describeVpcEndpointServicePermissions: { - reliesOnService: 'ec2', - reliesOnCall: 'describeVpcEndpointServices', - filterKey: 'ServiceId', - filterValue: 'ServiceId' - }, describeLaunchTemplateVersions: { reliesOnService: 'ec2', reliesOnCall: 'describeLaunchTemplates', @@ -1523,13 +1500,6 @@ var postcalls = [ override: true } }, - ElasticBeanstalk: { - describeConfigurationSettings: { - reliesOnService: 'elasticbeanstalk', - reliesOnCall: 'describeEnvironments', - override: true - } - }, ElasticTranscoder: { listJobsByPipeline: { reliesOnService: 'elastictranscoder', @@ -1544,11 +1514,6 @@ var postcalls = [ reliesOnCall: 'describeLoadBalancers', override: true }, - describeLoadBalancerAttributes: { - reliesOnService: 'elb', - reliesOnCall: 'describeLoadBalancers', - override: true - }, describeTags: { reliesOnService: 'elb', reliesOnCall: 'describeLoadBalancers', @@ -1562,21 +1527,6 @@ var postcalls = [ filterKey: 'TargetGroupArn', filterValue: 'TargetGroupArn' }, - describeLoadBalancerAttributes: { - reliesOnService: 'elbv2', - reliesOnCall: 'describeLoadBalancers', - override: true - }, - describeListeners: { - reliesOnService: 'elbv2', - reliesOnCall: 'describeLoadBalancers', - override: true - }, - describeTargetGroups: { - reliesOnService: 'elbv2', - reliesOnCall: 'describeLoadBalancers', - override: true - }, describeTargetGroupAttributes: { reliesOnService: 'elbv2', reliesOnCall: 'describeTargetGroups', @@ -1593,12 +1543,6 @@ var postcalls = [ reliesOnCall: 'listClusters', filterKey: 'ClusterId', filterValue: 'Id' - }, - listInstanceGroups: { - reliesOnService: 'emr', - reliesOnCall: 'listClusters', - filterKey: 'ClusterId', - filterValue: 'Id' } }, DLM: { @@ -1626,6 +1570,72 @@ var postcalls = [ } }, }, + { + EC2: { + describeSnapshotAttribute: { + reliesOnService: 'ec2', + reliesOnCall: 'describeSnapshots', + override: true + }, + describeVpcEndpointServicePermissions: { + reliesOnService: 'ec2', + reliesOnCall: 'describeVpcEndpointServices', + filterKey: 'ServiceId', + filterValue: 'ServiceId' + }, + }, + ElasticBeanstalk: { + describeConfigurationSettings: { + reliesOnService: 'elasticbeanstalk', + reliesOnCall: 'describeEnvironments', + override: true + } + }, + ELB: { + describeLoadBalancerAttributes: { + reliesOnService: 'elb', + reliesOnCall: 'describeLoadBalancers', + override: true + }, + }, + ELBv2: { + describeLoadBalancerAttributes: { + reliesOnService: 'elbv2', + reliesOnCall: 'describeLoadBalancers', + override: true + }, + describeListeners: { + reliesOnService: 'elbv2', + reliesOnCall: 'describeLoadBalancers', + override: true + }, + describeTargetGroups: { + reliesOnService: 'elbv2', + reliesOnCall: 'describeLoadBalancers', + override: true + }, + }, + EMR: { + listInstanceGroups: { + reliesOnService: 'emr', + reliesOnCall: 'listClusters', + filterKey: 'ClusterId', + filterValue: 'Id' + } + }, + AutoScaling: { + describeNotificationConfigurations: { + reliesOnService: 'autoscaling', + reliesOnCall: 'describeAutoScalingGroups', + override: true + }, + describeLaunchConfigurations: { + reliesOnService: 'autoscaling', + reliesOnCall: 'describeAutoScalingGroups', + override: true + } + }, + }, { CloudFormation: { describeStackEvents: { @@ -2157,7 +2167,7 @@ var postcalls = [ filterValue: 'DomainName' }, } - } + }, ]; module.exports = { diff --git a/helpers/azure/functions.js b/helpers/azure/functions.js index 57da0ce7eb..ea5c11c22a 100644 --- a/helpers/azure/functions.js +++ b/helpers/azure/functions.js @@ -54,7 +54,7 @@ function addResult(results, status, message, region, resource, custom) { }); } -function findOpenPorts(ngs, protocols, service, location, results) { +function findOpenPorts(ngs, protocols, service, location, results, checkAllPorts) { var openPrefix = ['*', '0.0.0.0', '0.0.0.0/0', '', '/0', '::/0', 'internet']; for (let sGroups of ngs) { @@ -103,12 +103,15 @@ function findOpenPorts(ngs, protocols, service, location, results) { strings.push(string); if (strings.indexOf(string) === -1) strings.push(string); } - } else if (parseInt(securityRule.properties['destinationPortRange']) === port || - securityRule.properties['destinationPortRange'] === port || - securityRule.properties['destinationPortRange'] === '*') { + } else if (parseInt(securityRule.properties['destinationPortRange']) === port) { var string = `Security Rule "` + securityRule['name'] + `": ` + (protocol === '*' ? `All protocols` : protocol.toUpperCase()) + (ports === '*' ? ` and all ports` : ` port ` + ports) + ` open to ` + sourceFilter; if (strings.indexOf(string) === -1) strings.push(string); + } else if (checkAllPorts && + openPrefix.includes(securityRule.properties['destinationPortRange'])) { + var openAllstring = `Security Rule "` + securityRule['name'] + `": ` + (protocol === '*' ? `All protocols` : protocol.toUpperCase()) + + (ports === '*' ? ` and all ports` : ` port ` + ports) + ` open to ` + sourceFilter; + if (strings.indexOf(openAllstring) === -1) strings.push(openAllstring); } } else if (securityRule.properties['destinationPortRanges']) { if (securityRule.properties['destinationPortRanges'].indexOf(port.toString()) > -1) { @@ -211,7 +214,7 @@ function checkPolicyAssignment(policyAssignments, param, text, results, location } } -function checkLogAlerts(activityLogAlerts, conditionResource, text, results, location) { +function checkLogAlerts(activityLogAlerts, conditionResource, text, results, location, parentConditionResource) { if (!activityLogAlerts) return; if (activityLogAlerts.err || !activityLogAlerts.data) { @@ -241,11 +244,18 @@ function checkLogAlerts(activityLogAlerts, conditionResource, text, results, loc if (!allConditions || !allConditions.allOf || !allConditions.allOf.length) continue; - var conditionOperation = allConditions.allOf.filter((d) => { - return (d.equals && d.equals.toLowerCase().indexOf(conditionResource) > -1); + return (d.equals && d.equals.toLowerCase().indexOf(conditionResource) > -1 || + (parentConditionResource && d.equals && d.equals.toLowerCase().indexOf(parentConditionResource) > -1)); }); + if (conditionOperation && conditionOperation.length) { + if (conditionResource.includes('microsoft.security') && allConditions.allOf.every(condition => condition.field && condition.field == 'category' && + condition.equals && condition.equals.toLowerCase() == 'security')) { + alertCreateUpdateEnabled = (!alertCreateUpdateEnabled && activityLogAlertResource.enabled ? true : alertCreateUpdateEnabled); + break; + } + allConditions.allOf.forEach(condition => { if (condition.field && (condition.field === 'resourceType') && (condition.equals && (condition.equals.toLowerCase() === conditionResource))) { alertCreateDeleteEnabled = (!alertCreateDeleteEnabled && activityLogAlertResource.enabled ? true : alertCreateDeleteEnabled); @@ -254,7 +264,7 @@ function checkLogAlerts(activityLogAlerts, conditionResource, text, results, loc } else if (condition.equals && condition.equals.toLowerCase().indexOf(conditionResource + '/delete') > -1) { alertDeleteEnabled = (!alertDeleteEnabled && activityLogAlertResource.enabled ? true : alertDeleteEnabled); } - }) + }); } } diff --git a/package.json b/package.json index ce5529b0e4..b76e257faa 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,6 @@ "azure-storage": "^2.10.3", "csv-write-stream": "^2.0.0", "fast-safe-stringify": "^2.0.6", - "googleapis": "^76.0.0", "minimatch": "^3.0.4", "ms-rest-azure": "^2.6.0", "tty-table": "^4.1.3" diff --git a/plugins/alibaba/ack/networkPolicyEnabled.spec.js b/plugins/alibaba/ack/networkPolicyEnabled.spec.js index 2a31410f79..3a56f07da7 100644 --- a/plugins/alibaba/ack/networkPolicyEnabled.spec.js +++ b/plugins/alibaba/ack/networkPolicyEnabled.spec.js @@ -4,7 +4,7 @@ var networkPolicyEnabled = require('./networkPolicyEnabled.js'); const describeClusters = [ { "name": "aqua-cluster2", - "cluster_id": "cc377f7509590489da921de83a1cad919", + "cluster_id": "cc377f7509590489da921de83a1cad918", "size": 2, "region_id": "us-west-1", "state": "initial", diff --git a/plugins/alibaba/apigateway/apiProtocol.spec.js b/plugins/alibaba/apigateway/apiProtocol.spec.js index 32781510ff..e06148c861 100644 --- a/plugins/alibaba/apigateway/apiProtocol.spec.js +++ b/plugins/alibaba/apigateway/apiProtocol.spec.js @@ -185,7 +185,6 @@ describe('apiProtocol', () => { it('should PASS if API has HTTPS protocol configured', done => { const cache = createCache([describeApis], describeApi[0]); apiProtocol.run(cache, {}, (err, results) => { - console.log(results); expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); expect(results[0].message).to.include('API has HTTPS protocol configured'); diff --git a/plugins/aws/ecr/ecrRepositoryPolicy.js b/plugins/aws/ecr/ecrRepositoryPolicy.js index 34fce38bb4..1851a22748 100644 --- a/plugins/aws/ecr/ecrRepositoryPolicy.js +++ b/plugins/aws/ecr/ecrRepositoryPolicy.js @@ -105,11 +105,11 @@ module.exports = { if (Array.isArray(srcAcct) && srcAcct.length == 1 && srcAcct[0] == registryId) continue; } - if (helpers.globalPrincipal(statement.Principal) && config.ecr_check_global_principal) { + if (statement.Principal && helpers.globalPrincipal(statement.Principal) && config.ecr_check_global_principal) { // Check for global access found.push('Repository allows global access for actions: ' + statement.Action.join(', ') + '.'); if (result < 2) result = 2; - } else if (helpers.crossAccountPrincipal(statement.Principal, registryId) && config.ecr_check_cross_account_principal) { + } else if (statement.Principal && helpers.crossAccountPrincipal(statement.Principal, registryId) && config.ecr_check_cross_account_principal) { // Check for cross-account access found.push('Repository allows cross-account access for actions: ' + statement.Action.join(', ') + '.'); if (result < 2) result = 2; diff --git a/plugins/aws/iam/rolePolicyUnusedServices.js b/plugins/aws/iam/rolePolicyUnusedServices.js index bd9d2b76e6..044c38f99a 100644 --- a/plugins/aws/iam/rolePolicyUnusedServices.js +++ b/plugins/aws/iam/rolePolicyUnusedServices.js @@ -139,6 +139,8 @@ module.exports = { elasticloadbalancingv2: ['loadbalancer'] }; + + async.each(regions.configservice, function(region, rcb) { var configRecorderStatus = helpers.addSource(cache, source, ['configservice', 'describeConfigurationRecorderStatus', region]); @@ -184,202 +186,207 @@ module.exports = { allResources.push(...discoveredResources.data); rcb(); - }); - - if (!allResources.length) { - helpers.addResult(results, 0, 'No Discovered Resources found.'); - return callback(null, results, source); - } - - allResources = allResources.reduce((result, resource) => { - let arr = resource.resourceType.split(':'); - let service = arr[2].toLowerCase(); - let subService = arr[4].toLowerCase(); - result[service] = result[service] || []; - - if (resource.count > 0 && (allServices[service] && allServices[service].includes(subService))) { - result[service].push(subService); + }, function() { + if (!allResources.length) { + helpers.addResult(results, 0, 'No Discovered Resources found.'); + return callback(null, results, source); } - return result; - }, {}); - - var listRoles = helpers.addSource(cache, source, - ['iam', 'listRoles', iamRegion]); - - if (!listRoles) return callback(null, results, source); - - if (listRoles.err || !listRoles.data) { - helpers.addResult(results, 3, - 'Unable to query for IAM roles: ' + helpers.addError(listRoles)); - return callback(null, results, source); - } - - if (!listRoles.data.length) { - helpers.addResult(results, 0, 'No IAM roles found'); - return callback(null, results, source); - } - - async.each(listRoles.data, function(role, cb){ - if (!role.RoleName) return cb(); + allResources = allResources.reduce((result, resource) => { + let arr = resource.resourceType.split(':'); + if (arr.length && arr.length >= 5) { + let service = arr[2].toLowerCase(); + let subService = arr[4].toLowerCase(); + result[service] = result[service] || []; - // Skip roles with user-defined paths - if (config.iam_role_policies_ignore_path && - config.iam_role_policies_ignore_path.length && - role.Path && - role.Path.indexOf(config.iam_role_policies_ignore_path) > -1) { - return cb(); - } + if (resource.count > 0 && (allServices[service] && allServices[service].includes(subService))) { + result[service].push(subService); + } - if (config.ignore_identity_federation_roles && - helpers.hasFederatedUserRole(helpers.normalizePolicyDocument(role.AssumeRolePolicyDocument))) { - helpers.addResult(results, 0, - 'Role is federated user role', - 'global', role.Arn, custom); - return cb(); - } + return result; + } + }, {}); - // Get managed policies attached to role - var listAttachedRolePolicies = helpers.addSource(cache, source, - ['iam', 'listAttachedRolePolicies', iamRegion, role.RoleName]); + if (!allResources) allResources = {}; - // Get inline policies attached to role - var listRolePolicies = helpers.addSource(cache, source, - ['iam', 'listRolePolicies', iamRegion, role.RoleName]); + var listRoles = helpers.addSource(cache, source, + ['iam', 'listRoles', iamRegion]); - var getRolePolicy = helpers.addSource(cache, source, - ['iam', 'getRolePolicy', iamRegion, role.RoleName]); + if (!listRoles) return callback(null, results, source); - if (!listAttachedRolePolicies || listAttachedRolePolicies.err) { + if (listRoles.err || !listRoles.data) { helpers.addResult(results, 3, - 'Unable to query for IAM attached policy for role: ' + role.RoleName + ': ' + helpers.addError(listAttachedRolePolicies), 'global', role.Arn); - return cb(); + 'Unable to query for IAM roles: ' + helpers.addError(listRoles)); + return callback(null, results, source); } - if (!listRolePolicies || listRolePolicies.err) { - helpers.addResult(results, 3, - 'Unable to query for IAM role policy for role: ' + role.RoleName + ': ' + helpers.addError(listRolePolicies), 'global', role.Arn); - return cb(); + if (!listRoles.data.length) { + helpers.addResult(results, 0, 'No IAM roles found'); + return callback(null, results, source); } - var policyFailures = []; - var roleFailures = []; + async.each(listRoles.data, function(role, cb){ + if (!role.RoleName) return cb(); - // See if role has admin managed policy - if (listAttachedRolePolicies.data && - listAttachedRolePolicies.data.AttachedPolicies) { + // Skip roles with user-defined paths + if (config.iam_role_policies_ignore_path && + config.iam_role_policies_ignore_path.length && + role.Path && + role.Path.indexOf(config.iam_role_policies_ignore_path) > -1) { + return cb(); + } - for (var policy of listAttachedRolePolicies.data.AttachedPolicies) { - if (policy.PolicyArn === managedAdminPolicy) { - roleFailures.push('Role has managed AdministratorAccess policy'); - break; - } + if (config.ignore_identity_federation_roles && + helpers.hasFederatedUserRole(helpers.normalizePolicyDocument(role.AssumeRolePolicyDocument))) { + helpers.addResult(results, 0, + 'Role is federated user role', + 'global', role.Arn, custom); + return cb(); + } - if (config.ignore_aws_managed_iam_policies && /^arn:aws:iam::aws:.*/.test(policy.PolicyArn)) continue; + // Get managed policies attached to role + var listAttachedRolePolicies = helpers.addSource(cache, source, + ['iam', 'listAttachedRolePolicies', iamRegion, role.RoleName]); - if (config.ignore_customer_managed_iam_policies && /^arn:aws:iam::[0-9]{12}:.*/.test(policy.PolicyArn)) continue; + // Get inline policies attached to role + var listRolePolicies = helpers.addSource(cache, source, + ['iam', 'listRolePolicies', iamRegion, role.RoleName]); - var getPolicy = helpers.addSource(cache, source, - ['iam', 'getPolicy', iamRegion, policy.PolicyArn]); + var getRolePolicy = helpers.addSource(cache, source, + ['iam', 'getRolePolicy', iamRegion, role.RoleName]); - if (getPolicy && - getPolicy.data && - getPolicy.data.Policy && - getPolicy.data.Policy.DefaultVersionId) { - var getPolicyVersion = helpers.addSource(cache, source, - ['iam', 'getPolicyVersion', iamRegion, policy.PolicyArn]); + if (!listAttachedRolePolicies || listAttachedRolePolicies.err) { + helpers.addResult(results, 3, + 'Unable to query for IAM attached policy for role: ' + role.RoleName + ': ' + helpers.addError(listAttachedRolePolicies), 'global', role.Arn); + return cb(); + } - if (getPolicyVersion && - getPolicyVersion.data && - getPolicyVersion.data.PolicyVersion && - getPolicyVersion.data.PolicyVersion.Document) { - let statements = helpers.normalizePolicyDocument( - getPolicyVersion.data.PolicyVersion.Document); + if (!listRolePolicies || listRolePolicies.err) { + helpers.addResult(results, 3, + 'Unable to query for IAM role policy for role: ' + role.RoleName + ': ' + helpers.addError(listRolePolicies), 'global', role.Arn); + return cb(); + } - if (!statements) break; + var policyFailures = []; + var roleFailures = []; - for (let statement of statements) { - if (statement.Action && statement.Action.length) { - for (let action of statement.Action) { - let service = action.split(':')[0].toLowerCase(); - let resourceAction = action.split(':')[1].toLowerCase(); + // See if role has admin managed policy + if (listAttachedRolePolicies.data && + listAttachedRolePolicies.data.AttachedPolicies) { - if (allServices[service]) { - for (let supportedResource of allServices[service]) { - if (resourceAction.includes(supportedResource)) { - if (!allResources[service] || !allResources[service].includes(supportedResource)) { - if (policyFailures.indexOf(action) === -1) policyFailures.push(action); + for (var policy of listAttachedRolePolicies.data.AttachedPolicies) { + if (policy.PolicyArn === managedAdminPolicy) { + roleFailures.push('Role has managed AdministratorAccess policy'); + break; + } + + if (config.ignore_aws_managed_iam_policies && /^arn:aws:iam::aws:.*/.test(policy.PolicyArn)) continue; + + if (config.ignore_customer_managed_iam_policies && /^arn:aws:iam::[0-9]{12}:.*/.test(policy.PolicyArn)) continue; + + var getPolicy = helpers.addSource(cache, source, + ['iam', 'getPolicy', iamRegion, policy.PolicyArn]); + + if (getPolicy && + getPolicy.data && + getPolicy.data.Policy && + getPolicy.data.Policy.DefaultVersionId) { + var getPolicyVersion = helpers.addSource(cache, source, + ['iam', 'getPolicyVersion', iamRegion, policy.PolicyArn]); + + if (getPolicyVersion && + getPolicyVersion.data && + getPolicyVersion.data.PolicyVersion && + getPolicyVersion.data.PolicyVersion.Document) { + let statements = helpers.normalizePolicyDocument( + getPolicyVersion.data.PolicyVersion.Document); + + if (!statements) break; + + for (let statement of statements) { + if (statement.Action && statement.Action.length) { + for (let action of statement.Action) { + let service = action.split(':')[0] ? action.split(':')[0].toLowerCase() : ''; + let resourceAction = action.split(':')[1] ? action.split(':')[1].toLowerCase() : ''; + + if (allServices[service]) { + for (let supportedResource of allServices[service]) { + if (resourceAction.includes(supportedResource)) { + if (!allResources[service] || !allResources[service].includes(supportedResource)) { + if (policyFailures.indexOf(action) === -1) policyFailures.push(action); + } } } } } } } - } - addRoleFailures(roleFailures, statements, 'managed', config.ignore_service_specific_wildcards); + addRoleFailures(roleFailures, statements, 'managed', config.ignore_service_specific_wildcards); + } } } } - } - if (listRolePolicies.data && - listRolePolicies.data.PolicyNames) { + if (listRolePolicies.data && + listRolePolicies.data.PolicyNames) { - for (var p in listRolePolicies.data.PolicyNames) { - var policyName = listRolePolicies.data.PolicyNames[p]; + for (var p in listRolePolicies.data.PolicyNames) { + var policyName = listRolePolicies.data.PolicyNames[p]; - if (getRolePolicy && - getRolePolicy[policyName] && - getRolePolicy[policyName].data && - getRolePolicy[policyName].data.PolicyDocument) { - var statements = helpers.normalizePolicyDocument( - getRolePolicy[policyName].data.PolicyDocument); + if (getRolePolicy && + getRolePolicy[policyName] && + getRolePolicy[policyName].data && + getRolePolicy[policyName].data.PolicyDocument) { + var statements = helpers.normalizePolicyDocument( + getRolePolicy[policyName].data.PolicyDocument); - if (!statements) break; + if (!statements) break; - for (let statement of statements) { - if ((statement.Action && statement.Action.length === 1 && statement.Action[0] === '*') && (statement.Resource && statement.Resource.length === 1 && statement.Resource[0] === '*')) { - continue; - } + for (let statement of statements) { + if ((statement.Action && statement.Action.length && statement.Action[0] === '*') || + (statement.Resource && statement.Resource.length && statement.Resource[0] === '*')) { + continue; + } - let service = statement.Resource[0].includes('arn') ? statement.Resource[0].split(':')[2].toLowerCase() : - statement.Action[0].split(':')[1].toLowerCase(); - if (statement.Action.length > 1 || statement.Action[0] !== '*') { - for (let action of statement.Action) { - let resourceAction = action.split(':')[1].toLowerCase(); - - if (allServices[service]) { - for (let supportedResource of allServices[service]) { - if (resourceAction.includes(supportedResource)) { - if (!allResources[service] || !allResources[service].includes(supportedResource)) { - if (policyFailures.indexOf(action) === -1) policyFailures.push(action); + let service = statement.Resource[0].includes('arn') ? statement.Resource[0].split(':')[2].toLowerCase() : + statement.Action[0].split(':')[1].toLowerCase(); + if (statement.Action.length > 1 || statement.Action[0] !== '*') { + for (let action of statement.Action) { + let resourceAction = action.split(':')[1].toLowerCase(); + + if (allServices[service]) { + for (let supportedResource of allServices[service]) { + if (resourceAction.includes(supportedResource)) { + if (!allResources[service] || !allResources[service].includes(supportedResource)) { + if (policyFailures.indexOf(action) === -1) policyFailures.push(action); + } } } } } } } - } - addRoleFailures(roleFailures, statements, 'inline', config.ignore_service_specific_wildcards); + addRoleFailures(roleFailures, statements, 'inline', config.ignore_service_specific_wildcards); + } } } - } - if (policyFailures.length || roleFailures.length) { - let failureMsg = policyFailures.length ? 'Role policies contain actions for resource types which are not in use: ' + - '[ ' + policyFailures.join(', ') + ' ]' + '\r\n' + roleFailures.join(', ') : roleFailures.join(', '); - helpers.addResult(results, 2, failureMsg, 'global', role.Arn, custom); - } else { - helpers.addResult(results, 0, - 'Role does not have overly-permissive policy', - 'global', role.Arn, custom); - } + if (policyFailures.length || roleFailures.length) { + let failureMsg = policyFailures.length ? 'Role policies contain actions for resource types which are not in use: ' + + '[ ' + policyFailures.join(', ') + ' ]' + '\r\n' + roleFailures.join(', ') : roleFailures.join(', '); + helpers.addResult(results, 2, failureMsg, 'global', role.Arn, custom); + } else { + helpers.addResult(results, 0, + 'Role does not have overly-permissive policy', + 'global', role.Arn, custom); + } - cb(); - }, function() { - callback(null, results, source); + cb(); + }, function() { + callback(null, results, source); + }); }); } }; diff --git a/plugins/aws/lookout/modelDataEncrypted.spec.js b/plugins/aws/lookout/modelDataEncrypted.spec.js index c1bd822b8c..86ae41a5e5 100644 --- a/plugins/aws/lookout/modelDataEncrypted.spec.js +++ b/plugins/aws/lookout/modelDataEncrypted.spec.js @@ -173,7 +173,6 @@ describe('modelDataEncrypted', function () { it('should PASS if LookoutVision model data is encrypted with desired level', function (done) { const cache = createCache([listProjects[0]], [listModels[1]], describeModel[1], listKeys, describeKey[0]); modelDataEncrypted.run(cache, { model_data_desired_encryption_level: 'awscmk' }, (err, results) => { - console.log(results); expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); expect(results[0].region).to.equal('us-east-1'); diff --git a/plugins/aws/msk/mskClusterPublicAccess.js b/plugins/aws/msk/mskClusterPublicAccess.js index 5336dad6b1..ac5301b4ac 100644 --- a/plugins/aws/msk/mskClusterPublicAccess.js +++ b/plugins/aws/msk/mskClusterPublicAccess.js @@ -7,7 +7,7 @@ module.exports = { domain: 'Compute', severity: 'Medium', description: 'Ensure that public access feature within the cluster is disabled for your Amazon MSK clusters.', - more_info: 'Amazon MSK gives you the option to turn on public access to the brokers of MSK clusters running Apache Kafka 2.6.0 or later versions. For security reasons, you can'/'t turn on public access while creating an MSK cluster. However, you can update an existing cluster to make it publicly accessible.', + more_info: 'Amazon MSK gives you the option to turn on public access to the brokers of MSK clusters running Apache Kafka 2.6.0 or later versions. For security reasons, you cannot turn on public access while creating an MSK cluster. However, you can update an existing cluster to make it publicly accessible.', link: 'https://docs.aws.amazon.com/msk/latest/developerguide/public-access.html', recommended_action: 'Check for public access feature within the cluster for all MSK clusters', apis: ['Kafka:listClusters'], diff --git a/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js b/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js index 2e7bfe3535..339d2b1187 100644 --- a/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js +++ b/plugins/aws/timestreamwrite/timestreamDatabaseEncrypted.js @@ -2,14 +2,14 @@ var async = require('async'); var helpers = require('../../../helpers/aws'); module.exports = { - title: ' Timestream Database Encrypted', + title: 'Timestream Database Encrypted', category: 'Timestream', domain: 'Databases', description: 'Ensure that AWS Timestream databases are encrypted with KMS Customer Master Keys (CMKs) instead of AWS managed-keys.', more_info: 'Timestream encryption at rest provides enhanced security by encrypting all your data at rest using encryption keys. ' + 'This functionality helps reduce the operational burden and complexity involved in protecting sensitive data. ' + 'With encryption at rest using customer-managed keys, you can build security-sensitive applications that meet strict encryption compliance and regulatory requirements. ', - recommended_action: 'Modify Trimestream database encryption configuration to use desired encryption key', + recommended_action: 'Modify Timestream database encryption configuration to use desired encryption key', link: 'https://docs.aws.amazon.com/timestream/latest/developerguide/EncryptionAtRest.html', apis: ['TimestreamWrite:listDatabases', 'KMS:describeKey', 'KMS:listKeys'], settings: { diff --git a/plugins/azure/logalerts/securityPolicyAlertsEnabled.js b/plugins/azure/logalerts/securityPolicyAlertsEnabled.js index e24e3203a2..19e3784b2b 100644 --- a/plugins/azure/logalerts/securityPolicyAlertsEnabled.js +++ b/plugins/azure/logalerts/securityPolicyAlertsEnabled.js @@ -25,7 +25,7 @@ module.exports = { var activityLogAlerts = helpers.addSource(cache, source, ['activityLogAlerts', 'listBySubscriptionId', location]); - helpers.checkLogAlerts(activityLogAlerts, conditionResource, text, results, location); + helpers.checkLogAlerts(activityLogAlerts, conditionResource, text, results, location, 'security'); rcb(); }, function() { diff --git a/plugins/azure/networksecuritygroups/openAllPorts.js b/plugins/azure/networksecuritygroups/openAllPorts.js index a53556db8e..db03e93d54 100644 --- a/plugins/azure/networksecuritygroups/openAllPorts.js +++ b/plugins/azure/networksecuritygroups/openAllPorts.js @@ -51,7 +51,7 @@ module.exports = { let service = 'All Ports'; - helpers.findOpenPorts(networkSecurityGroups.data, ports, service, location, results); + helpers.findOpenPorts(networkSecurityGroups.data, ports, service, location, results, true); rcb(); }, function() { diff --git a/plugins/azure/sqlserver/enableATP.js b/plugins/azure/sqlserver/enableATP.js index a660401bd6..612779cf02 100644 --- a/plugins/azure/sqlserver/enableATP.js +++ b/plugins/azure/sqlserver/enableATP.js @@ -2,11 +2,11 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); module.exports = { - title: 'Advanced Threat Protection Enabled', + title: 'SQL Server Advanced Threat Protection Enabled', category: 'SQL Server', domain: 'Databases', description: 'Ensures that Advanced Threat Protection is enabled on SQL Servers.', - more_info: 'Azure Defender for SQL is a unified package for advanced SQL security capabilities. Azure Defender is available for Azure SQL Database, Azure SQL Managed Instance, and Azure Synapse Analytics. It includes functionality for discovering and classifying sensitive data, surfacing and mitigating potential database vulnerabilities, and detecting anomalous activities that could indicate a threat to your database. It provides a single go-to location for enabling and managing these capabilities.', + more_info: 'Azure Defender for SQL is a unified package for advanced SQL security capabilities.', recommended_action: 'Ensure that ThreatDetectionState is set to Enabled', link: 'https://docs.microsoft.com/en-us/azure/azure-sql/database/azure-defender-for-sql', apis: ['servers:listSql', 'advancedThreatProtectionSettings:listByServer'], From 94d49d379c4d00a692d33cf087222c2b2998bbbe Mon Sep 17 00:00:00 2001 From: M-Akhtar Date: Fri, 29 Jul 2022 16:00:40 +0500 Subject: [PATCH 345/350] fix lint --- helpers/google/index.js | 85 ----------------------------------------- 1 file changed, 85 deletions(-) diff --git a/helpers/google/index.js b/helpers/google/index.js index c51fe93699..73454dbe3c 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -441,92 +441,7 @@ function remediatePlugin(config, method, body, baseUrl, resource, remediation_fi return callback(null, action); }); } -function makeRemediationCall(GoogleConfig, method, body, baseUrl, resource, callCb) { - authenticate(GoogleConfig).then(client => { - if (resource) { - baseUrl = baseUrl.replace(/\{resource\}/g, resource); - } - client.request({ - url: baseUrl, - method, - data: body - }, function(err, res) { - if (err) { - callCb(err); - } else if (res && res.data) { - callCb(null); - } - }); - }); -} - -function remediateOrgPolicy(config, constraintName, policyType, policyValue, resource, remediation_file, putCall, pluginName, callback) { - // url to update org policy - var baseUrl = 'https://cloudresourcemanager.googleapis.com/v1/{resource}:setOrgPolicy'; - var method = 'POST'; - - // create the params necessary for the remediation - var body; - if (policyType == 'booleanPolicy') { - body = { - policy: { - constraint: constraintName, - booleanPolicy: { - enforced: policyValue - } - } - }; - } - // logging - remediation_file['pre_remediate']['actions'][pluginName][resource] = { - constraintName: policyValue ? 'Disabled' : 'Enabled' - }; - - remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, callback); -} - -function remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, callback) { - makeRemediationCall(config, method, body, baseUrl, resource, function(err) { - if (err) { - remediation_file['remediate']['actions'][pluginName]['error'] = err; - return callback(err, null); - } - - let action = body; - return callback(null, action); - }); -} -function makeRemediationCall(GoogleConfig, method, body, baseUrl, resource, callCb) { - authenticate(GoogleConfig).then(client => { - if (resource) { - baseUrl = baseUrl.replace(/\{resource\}/g, resource); - } - client.request({ - url: baseUrl, - method, - data: body - }, function(err, res) { - if (err) { - callCb(err); - } else if (res && res.data) { - callCb(null); - } - }); - }); -} - -function remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, callback) { - makeRemediationCall(config, method, body, baseUrl, resource, function(err) { - if (err) { - remediation_file['remediate']['actions'][pluginName]['error'] = err; - return callback(err, null); - } - - let action = body; - return callback(null, action); - }); -} function makeRemediationCall(GoogleConfig, method, body, baseUrl, resource, callCb) { authenticate(GoogleConfig).then(client => { if (resource) { From 9aa206a60a9cabdd19c803e87158ab306eb7987a Mon Sep 17 00:00:00 2001 From: M-Akhtar Date: Fri, 29 Jul 2022 16:04:20 +0500 Subject: [PATCH 346/350] fix lint --- helpers/google/index.js | 55 ----------------------------------------- 1 file changed, 55 deletions(-) diff --git a/helpers/google/index.js b/helpers/google/index.js index fb39f0444f..73454dbe3c 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -441,62 +441,7 @@ function remediatePlugin(config, method, body, baseUrl, resource, remediation_fi return callback(null, action); }); } -function makeRemediationCall(GoogleConfig, method, body, baseUrl, resource, callCb) { - authenticate(GoogleConfig).then(client => { - if (resource) { - baseUrl = baseUrl.replace(/\{resource\}/g, resource); - } - client.request({ - url: baseUrl, - method, - data: body - }, function(err, res) { - if (err) { - callCb(err); - } else if (res && res.data) { - callCb(null); - } - }); - }); -} - -function remediateOrgPolicy(config, constraintName, policyType, policyValue, resource, remediation_file, putCall, pluginName, callback) { - - // url to update org policy - var baseUrl = 'https://cloudresourcemanager.googleapis.com/v1/{resource}:setOrgPolicy'; - var method = 'POST'; - // create the params necessary for the remediation - var body; - if (policyType == 'booleanPolicy') { - body = { - policy: { - constraint: constraintName, - booleanPolicy: { - enforced: policyValue - } - } - }; - } - // logging - remediation_file['pre_remediate']['actions'][pluginName][resource] = { - constraintName: policyValue ? 'Disabled' : 'Enabled' - }; - - remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, callback); -} - -function remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, callback) { - makeRemediationCall(config, method, body, baseUrl, resource, function(err) { - if (err) { - remediation_file['remediate']['actions'][pluginName]['error'] = err; - return callback(err, null); - } - - let action = body; - return callback(null, action); - }); -} function makeRemediationCall(GoogleConfig, method, body, baseUrl, resource, callCb) { authenticate(GoogleConfig).then(client => { if (resource) { From b8a0643092a1fd056e665740e655b03f8b900f54 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 29 Jul 2022 16:15:54 +0500 Subject: [PATCH 347/350] fix lint --- helpers/google/index.js | 55 ----------------------------------------- 1 file changed, 55 deletions(-) diff --git a/helpers/google/index.js b/helpers/google/index.js index fb39f0444f..73454dbe3c 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -441,62 +441,7 @@ function remediatePlugin(config, method, body, baseUrl, resource, remediation_fi return callback(null, action); }); } -function makeRemediationCall(GoogleConfig, method, body, baseUrl, resource, callCb) { - authenticate(GoogleConfig).then(client => { - if (resource) { - baseUrl = baseUrl.replace(/\{resource\}/g, resource); - } - client.request({ - url: baseUrl, - method, - data: body - }, function(err, res) { - if (err) { - callCb(err); - } else if (res && res.data) { - callCb(null); - } - }); - }); -} - -function remediateOrgPolicy(config, constraintName, policyType, policyValue, resource, remediation_file, putCall, pluginName, callback) { - - // url to update org policy - var baseUrl = 'https://cloudresourcemanager.googleapis.com/v1/{resource}:setOrgPolicy'; - var method = 'POST'; - // create the params necessary for the remediation - var body; - if (policyType == 'booleanPolicy') { - body = { - policy: { - constraint: constraintName, - booleanPolicy: { - enforced: policyValue - } - } - }; - } - // logging - remediation_file['pre_remediate']['actions'][pluginName][resource] = { - constraintName: policyValue ? 'Disabled' : 'Enabled' - }; - - remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, callback); -} - -function remediatePlugin(config, method, body, baseUrl, resource, remediation_file, putCall, pluginName, callback) { - makeRemediationCall(config, method, body, baseUrl, resource, function(err) { - if (err) { - remediation_file['remediate']['actions'][pluginName]['error'] = err; - return callback(err, null); - } - - let action = body; - return callback(null, action); - }); -} function makeRemediationCall(GoogleConfig, method, body, baseUrl, resource, callCb) { authenticate(GoogleConfig).then(client => { if (resource) { From d56f7c3a9c75ebef1e1d062efc14a66319ed7e7b Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 29 Jul 2022 16:43:02 +0500 Subject: [PATCH 348/350] Added 7061 --- exports.js | 1 + .../objectstore/bucketWriteLogsEnabled.js | 66 +++++++ .../bucketWriteLogsEnabled.spec.js | 169 ++++++++++++++++++ 3 files changed, 236 insertions(+) create mode 100644 plugins/oracle/objectstore/bucketWriteLogsEnabled.js create mode 100644 plugins/oracle/objectstore/bucketWriteLogsEnabled.spec.js diff --git a/exports.js b/exports.js index ce71431f01..ce714f5905 100644 --- a/exports.js +++ b/exports.js @@ -900,6 +900,7 @@ module.exports = { 'bucketCMKEncryption' : require(__dirname + '/plugins/oracle/objectstore/bucketCMKEncryption.js'), 'bucketVersioning' : require(__dirname + '/plugins/oracle/objectstore/bucketVersioning.js'), 'bucketObjectEvents' : require(__dirname + '/plugins/oracle/objectstore/bucketObjectEvents.js'), + 'bucketWriteLogsEnabled' : require(__dirname + '/plugins/oracle/objectstore/bucketWriteLogsEnabled.js'), 'nfsPublicAccess' : require(__dirname + '/plugins/oracle/filestorage/nfsPublicAccess.js'), 'nfsPolicyProtection' : require(__dirname + '/plugins/oracle/filestorage/nfsPolicyProtection.js'), diff --git a/plugins/oracle/objectstore/bucketWriteLogsEnabled.js b/plugins/oracle/objectstore/bucketWriteLogsEnabled.js new file mode 100644 index 0000000000..e8319d72b4 --- /dev/null +++ b/plugins/oracle/objectstore/bucketWriteLogsEnabled.js @@ -0,0 +1,66 @@ +var async = require('async'); +var helpers = require('../../../helpers/oracle'); + +module.exports = { + title: 'Bucket Write Logs Enabled', + category: 'Object Store', + domain: 'Management and Governance', + description: 'Ensures write level Object Storage logging is enabled for all buckets.', + more_info: 'Enabling write level logging for object store buckets will provide you more visibility into changes to objects in your buckets.', + link: 'https://docs.cloud.oracle.com/iaas/Content/Object/Tasks/managingbuckets.htm', + recommended_action: 'Enable write level logging for each object store.', + apis: ['namespace:get', 'bucket:list', 'logGroup:list', 'log:list'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings.govcloud); + + async.each(regions.bucket, function(region, rcb){ + + if (helpers.checkRegionSubscription(cache, source, results, region)) { + + var buckets = helpers.addSource(cache, source, + ['bucket', 'list', region]); + + if (!buckets) return rcb(); + + if (buckets.err || !buckets.data) { + helpers.addResult(results, 3, + 'Unable to query for object store buckets: ' + helpers.addError(buckets), region); + return rcb(); + } + + if (!buckets.data.length) { + helpers.addResult(results, 0, 'No object store buckets to check', region); + return rcb(); + } + + var logs = helpers.addSource(cache, source, + ['log', 'list', region]); + + buckets.data.forEach(bucket => { + let bucketLog = null; + + if (logs && !logs.err && logs.data && logs.data.length) { + bucketLog = logs.data.find(log => log.isEnabled && log.configuration + && Object.keys(log.configuration).length && log.configuration.source + && Object.keys(log.configuration.source).length && log.configuration.source.service === 'objectstorage' + && log.configuration.source.category === 'write' + && log.configuration.source.resource === bucket.name); + } + + if (bucketLog) { + helpers.addResult(results, 0, 'The bucket has write level logging enabled', region, bucket.name); + } else { + helpers.addResult(results, 2, 'The bucket does not have write level logging enabled', region, bucket.name); + } + }); + } + rcb(); + }, function(){ + // Global checking goes here + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/oracle/objectstore/bucketWriteLogsEnabled.spec.js b/plugins/oracle/objectstore/bucketWriteLogsEnabled.spec.js new file mode 100644 index 0000000000..010dfe3382 --- /dev/null +++ b/plugins/oracle/objectstore/bucketWriteLogsEnabled.spec.js @@ -0,0 +1,169 @@ +var expect = require('chai').expect; +var plugin = require('./bucketWriteLogsEnabled'); + +const buckets = [ + { + "namespace": 'idacicrnmktm', + "name": 'my-bucket', + "id": 'ocid1.bucket.oc1.iad.111111111111111122222222222222222233333333333333333', + "compartmentId": 'ocid1.tenancy.oc1..11111111111111111222222222222222222333333333333333', + "createdBy": 'ocid1.user.oc1..11111111111111112222222222222223333333333333333', + "timeCreated": '2021-04-28T13:26:51.917Z', + }, + { + "namespace": 'idacicrnmktm', + "name": 'my-bucket-1', + "id": 'ocid1.bucket.oc1.iad.111111111111111122222222222222222233333333333333333', + "compartmentId": 'ocid1.tenancy.oc1..11111111111111111222222222222222222333333333333333', + "createdBy": 'ocid1.user.oc1..11111111111111112222222222222223333333333333333', + "timeCreated": '2021-04-28T13:26:51.917Z', + } +]; + +const logs = [ + { + "id": "ocid1.log.oc1.log11111111", + "logGroupId": "ocid1.loggroup.oc1.loggroup11111", + "displayName": "bucket_log", + "isEnabled": true, + "lifecycleState": "ACTIVE", + "logType": "SERVICE", + "configuration": { + "compartmentId": "ocid1.tenancy.oc1.1111111111111", + "source": { + "sourceType": "OCISERVICE", + "service": "objectstorage", + "resource": "my-bucket-1", + "category": "write", + "parameters": {} + }, + "archiving": { + "isEnabled": false + } + }, + "freeformTags": {}, + "timeCreated": "2022-07-15T00:25:53.258Z", + "timeLastModified": "2022-07-15T00:25:53.258Z", + "retentionDuration": 30, + "compartmentId": "ocid1.tenancy.oc1.1111111111111", + "logGroups": "ocid1.loggroup.oc1.loggroup11111" + } +] + +const createCache = (err, data) => { + return { + regionSubscription: { + "list": { + "us-ashburn-1": { + "data": [ + { + "regionKey": "IAD", + "regionName": "us-ashburn-1", + "status": "READY", + "isHomeRegion": true + }, + { + "regionKey": "LHR", + "regionName": "uk-london-1", + "status": "READY", + "isHomeRegion": false + }, + { + "regionKey": "PHX", + "regionName": "us-phoenix-1", + "status": "READY", + "isHomeRegion": false + } + ] + } + } + }, + + bucket: { + list: { + 'us-ashburn-1': { + err: err, + data: data + } + } + }, + log: { + list: { + 'us-ashburn-1': { + err: null, + data: logs + } + } + } + } +}; + +describe('bucketWriteLogsEnabled', function () { + describe('run', function () { + it('should give unknown result if a bucket error occurs or no data is present', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(3) + expect(results[0].message).to.include('Unable to query for object store buckets') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + ['error'], + null, + ); + + plugin.run(cache, {}, callback); + }) + it('should give passing result if no buckets are found', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('No object store buckets to check') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [], + ); + + plugin.run(cache, {}, callback); + }) + it('should give failing result if the bucket does not have write level logs enabled', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(2) + expect(results[0].message).to.include('The bucket does not have write level logging enabled') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [buckets[0]] + ); + + plugin.run(cache, {}, callback); + }) + + it('should give passing result if the bucket has write level logs enabled', function (done) { + const callback = (err, results) => { + expect(results.length).to.be.above(0) + expect(results[0].status).to.equal(0) + expect(results[0].message).to.include('The bucket has write level logging enabled') + expect(results[0].region).to.equal('us-ashburn-1') + done() + }; + + const cache = createCache( + null, + [buckets[1]] + ); + + plugin.run(cache, {}, callback); + }) + }) +}) \ No newline at end of file From 2f89bab3c413121e3cecbb152cbf60e5794874b6 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 29 Jul 2022 16:49:32 +0500 Subject: [PATCH 349/350] Apply suggestions from code review --- helpers/oracle/regions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/oracle/regions.js b/helpers/oracle/regions.js index 18ae3e6ae1..3c38516852 100644 --- a/helpers/oracle/regions.js +++ b/helpers/oracle/regions.js @@ -87,6 +87,6 @@ module.exports = { vault: regions, keys: regions, cluster: regions, - cloudguardConfiguration: ['default'] + cloudguardConfiguration: ['default'], keyVersions: regions, }; \ No newline at end of file From 728cbce1c0b66902d9acb07b5ab0067769d05188 Mon Sep 17 00:00:00 2001 From: Sadeed Rehman <45767890+sadeed12345@users.noreply.github.com> Date: Fri, 29 Jul 2022 17:06:56 +0500 Subject: [PATCH 350/350] Removed linting issues --- helpers/aws/api.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/helpers/aws/api.js b/helpers/aws/api.js index 9a6e214a38..c47f7b68fd 100644 --- a/helpers/aws/api.js +++ b/helpers/aws/api.js @@ -664,6 +664,10 @@ var calls = { listComponents: { property: 'componentVersionList', paginate: 'nextToken' + }, + paginatelistImagePipelines: { + property: 'imagePipelineList', + paginate: 'nextToken' } }, IAM: { @@ -704,12 +708,6 @@ var calls = { override: true } }, - Imagebuilder: { - listImagePipelines: { - property: 'imagePipelineList', - paginate: 'nextToken' - } - }, IoTSiteWise: { describeDefaultEncryptionConfiguration: { }