diff --git a/collectors/aws/ses/getIdentityDkimAttributes.js b/collectors/aws/ses/getIdentityDkimAttributes.js index 587f5c6a11..e67f02564f 100644 --- a/collectors/aws/ses/getIdentityDkimAttributes.js +++ b/collectors/aws/ses/getIdentityDkimAttributes.js @@ -3,14 +3,46 @@ var helpers = require(__dirname + '/../../../helpers/aws'); module.exports = function(AWSConfig, collection, retries, callback) { var ses = new AWS.SES(AWSConfig); + collection.ses.getIdentityDkimAttributes[AWSConfig.region] = {}; - helpers.makeCustomCollectorCall(ses, 'getIdentityDkimAttributes', {Identities: collection.ses.listIdentities[AWSConfig.region].data}, retries, null, null, null, function(err, data) { - if (err) { - collection.ses.getIdentityDkimAttributes[AWSConfig.region].err = err; + var identities = collection.ses.listIdentities[AWSConfig.region].data; + var identityChunks = chunkArray(identities, 100); + var allDkimAttributes = []; + var processIdentityChunk = function(chunkIndex) { + if (chunkIndex >= identityChunks.length) { + allDkimAttributes = allDkimAttributes.flatMap(obj => Object.values(obj)); + collection.ses.getIdentityDkimAttributes[AWSConfig.region].data = { + DkimAttributes: allDkimAttributes + }; + callback(); + return; } - collection.ses.getIdentityDkimAttributes[AWSConfig.region].data = data; + var chunk = identityChunks[chunkIndex]; + var params = { + Identities: chunk, + }; - callback(); - }); -}; \ No newline at end of file + setTimeout(function() { + helpers.makeCustomCollectorCall(ses, 'getIdentityDkimAttributes', params, retries, null, null, null, function(err, data) { + if (err) { + collection.ses.getIdentityDkimAttributes[AWSConfig.region].err = err; + } else if (data && data.DkimAttributes) { + allDkimAttributes = allDkimAttributes.concat(data.DkimAttributes); + } + + processIdentityChunk(chunkIndex + 1); + }); + }, 1000); + }; + + processIdentityChunk(0); +}; + +function chunkArray(arr, chunkSize) { + var result = []; + for (var i = 0; i < arr.length; i += chunkSize) { + result.push(arr.slice(i, i + chunkSize)); + } + return result; +} diff --git a/collectors/azure/collector.js b/collectors/azure/collector.js index 4d1df48cae..ef1c30d0b2 100644 --- a/collectors/azure/collector.js +++ b/collectors/azure/collector.js @@ -44,7 +44,7 @@ function parseCollection(path, obj) { } } -var collect = function(AzureConfig, settings, callback) { +let collect = function(AzureConfig, settings, callback) { // Used to gather info only if (settings.gather) { return callback(null, calls, postcalls, tertiarycalls, specialcalls); @@ -92,10 +92,12 @@ var collect = function(AzureConfig, settings, callback) { }); }; - var processCall = function(obj, cb, localData) { - var localUrl = obj.nextUrl || obj.url.replace(/\{subscriptionId\}/g, AzureConfig.SubscriptionID); + let processCall = function(obj, cb, localData) { + let localUrl = obj.nextUrl || obj.url.replace(/\{subscriptionId\}/g, AzureConfig.SubscriptionID); if (obj.rateLimit) { setTimeout(function() { + console.log('timeout check'); + console.log(`url: ${localUrl} obj: ${JSON.stringify(obj)} localData: ${JSON.stringify(localData)}`); makeCall(localUrl, obj, cb, localData); }, obj.rateLimit); } else { diff --git a/collectors/azure/fileService/listSharesSegmented.js b/collectors/azure/fileService/listSharesSegmented.js index 8f43b68e45..8c951a5856 100644 --- a/collectors/azure/fileService/listSharesSegmented.js +++ b/collectors/azure/fileService/listSharesSegmented.js @@ -1,10 +1,9 @@ var async = require('async'); +var azureStorage = require('@azure/storage-file-share'); module.exports = function(collection, reliesOn, callback) { if (!reliesOn['storageAccounts.listKeys']) return callback(); - var azureStorage = require('azure-storage'); - if (!collection['fileService']['listSharesSegmented']) collection['fileService']['listSharesSegmented'] = {}; if (!collection['fileService']['getShareAcl']) collection['fileService']['getShareAcl'] = {}; @@ -13,39 +12,42 @@ module.exports = function(collection, reliesOn, callback) { collection['fileService']['listSharesSegmented'][region] = {}; collection['fileService']['getShareAcl'][region] = {}; - async.eachOfLimit(regionObj, 5, function(subObj, resourceId, sCb) { + async.eachOfLimit(regionObj, 5, async function(subObj, resourceId, sCb) { collection['fileService']['listSharesSegmented'][region][resourceId] = {}; if (subObj && subObj.data && subObj.data.keys && subObj.data.keys[0] && subObj.data.keys[0].value) { // Extract storage account name from resourceId - var storageAccountName = resourceId.substring(resourceId.lastIndexOf('/') + 1); - var storageService = new azureStorage['FileService'](storageAccountName, subObj.data.keys[0].value); - - storageService.listSharesSegmented(null, function(serviceErr, serviceResults) { - if (serviceErr || !serviceResults) { - collection['fileService']['listSharesSegmented'][region][resourceId].err = (serviceErr || 'No data returned'); - sCb(); - } else { - collection['fileService']['listSharesSegmented'][region][resourceId].data = serviceResults.entries; - - // Add ACLs - async.eachLimit(serviceResults.entries, 10, function(entryObj, entryCb) { - var entryId = `${resourceId}/fileService/${entryObj.name}`; - collection['fileService']['getShareAcl'][region][entryId] = {}; - - storageService.getShareAcl(entryObj.name, function(getErr, getData) { - if (getErr || !getData) { - collection['fileService']['getShareAcl'][region][entryId].err = (getErr || 'No data returned'); - } else { - collection['fileService']['getShareAcl'][region][entryId].data = getData; - } - entryCb(); + const shareItemList = []; + try { + const storageAccountName = resourceId.substring(resourceId.lastIndexOf('/') + 1); + const connectionString = `DefaultEndpointsProtocol=https;AccountName=${storageAccountName};AccountKey=${subObj.data.keys[0].value};EndpointSuffix=core.windows.net`; + const storageService = azureStorage.ShareServiceClient.fromConnectionString(connectionString); + const iterator = storageService.listShares(); + let item = await iterator.next(); + + while (!item.done) { + let fileShare = item.value.name; + var entryId = `${resourceId}/fileService/${fileShare}`; + shareItemList.push({ name: fileShare, id: entryId}); + collection['fileService']['getShareAcl'][region][entryId] = {}; + const shareClient = storageService.getShareClient(fileShare); + shareClient.getAccessPolicy() + .then(result => { + collection['fileService']['getShareAcl'][region][entryId].data = result; + }) + .catch(err => { + collection['fileService']['getShareAcl'][region][entryId].err = err; }); - }, function() { - sCb(); - }); + item = await iterator.next(); } - }); + } catch (exception) { + collection['fileService']['listSharesSegmented'][region][resourceId].err = exception.message; + } + if (shareItemList.length) { + collection['fileService']['listSharesSegmented'][region][resourceId].data = shareItemList; + } else { + collection['fileService']['listSharesSegmented'][region][resourceId].data = []; + } } else { sCb(); } diff --git a/collectors/azure/fileService/listSharesSegmentedNew.js b/collectors/azure/fileService/listSharesSegmentedNew.js deleted file mode 100644 index 9f00858fa5..0000000000 --- a/collectors/azure/fileService/listSharesSegmentedNew.js +++ /dev/null @@ -1,60 +0,0 @@ -var async = require('async'); -var azureStorage = require('@azure/storage-file-share'); - -module.exports = function(collection, reliesOn, callback) { - if (!reliesOn['storageAccounts.listKeys']) return callback(); - - if (!collection['fileService']['listSharesSegmented']) collection['fileService']['listSharesSegmented'] = {}; - if (!collection['fileService']['getShareAcl']) collection['fileService']['getShareAcl'] = {}; - - // Loop through regions and properties in reliesOn - async.eachOf(reliesOn['storageAccounts.listKeys'], function(regionObj, region, cb) { - collection['fileService']['listSharesSegmented'][region] = {}; - collection['fileService']['getShareAcl'][region] = {}; - - async.eachOfLimit(regionObj, 5, async function(subObj, resourceId, sCb) { - collection['fileService']['listSharesSegmented'][region][resourceId] = {}; - - if (subObj && subObj.data && subObj.data.keys && subObj.data.keys[0] && subObj.data.keys[0].value) { - // Extract storage account name from resourceId - const shareItemList = []; - try { - const storageAccountName = resourceId.substring(resourceId.lastIndexOf('/') + 1); - const connectionString = `DefaultEndpointsProtocol=https;AccountName=${storageAccountName};AccountKey=${subObj.data.keys[0].value};EndpointSuffix=core.windows.net`; - const storageService = azureStorage.ShareServiceClient.fromConnectionString(connectionString); - const iterator = storageService.listShares(); - let item = await iterator.next(); - - while (!item.done) { - let fileShare = item.value.name; - shareItemList.push({ name: fileShare}); - var entryId = `${resourceId}/fileService/${fileShare}`; - collection['fileService']['getShareAcl'][region][entryId] = {}; - const shareClient = storageService.getShareClient(fileShare); - shareClient.getAccessPolicy() - .then(result => { - collection['fileService']['getShareAcl'][region][entryId].data = result; - }) - .catch(err => { - collection['fileService']['getShareAcl'][region][entryId].err = err; - }); - item = await iterator.next(); - } - } catch (exception) { - collection['fileService']['listSharesSegmented'][region][resourceId].err = exception.message; - } - if (shareItemList.length) { - collection['fileService']['listSharesSegmented'][region][resourceId].data = shareItemList; - } else { - collection['fileService']['listSharesSegmented'][region][resourceId].data = []; - } - } else { - sCb(); - } - }, function() { - cb(); - }); - }, function() { - callback(); - }); -}; \ No newline at end of file diff --git a/exports.js b/exports.js index 591e428aab..53c1523d03 100644 --- a/exports.js +++ b/exports.js @@ -750,7 +750,6 @@ module.exports = { 'bastionHostExists' : require(__dirname + '/plugins/azure/bastion/bastionHostExists.js'), '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'), diff --git a/helpers/azure/api.js b/helpers/azure/api.js index 0d3a9fbf07..00657b0c7a 100644 --- a/helpers/azure/api.js +++ b/helpers/azure/api.js @@ -143,6 +143,15 @@ var serviceMap = { BridgeResourceNameIdentifier: 'name', BridgeExecutionService: 'Table Service', BridgeCollectionService: 'tableservice', DataIdentifier: 'data', }, + 'File Service': + { + enabled: true, isSingleSource: true, InvAsset: 'fileService', InvService: 'fileService', + InvResourceCategory: 'storage', InvResourceType: 'file_service', BridgeServiceName: 'fileservice', + BridgePluginCategoryName: 'File Service', BridgeProvider: 'Azure', BridgeCall: 'listSharesSegmented', + BridgeArnIdentifier: '', BridgeIdTemplate: '', BridgeResourceType: 'fileService', + BridgeResourceNameIdentifier: 'name', BridgeExecutionService: 'File Service', + BridgeCollectionService: 'fileservice', DataIdentifier: 'data', + }, 'SQL Databases': { enabled: true, isSingleSource: true, InvAsset: 'database', InvService: 'sql', @@ -950,10 +959,7 @@ var specialcalls = { reliesOnPath: ['storageAccounts.listKeys'], rateLimit: 3000 }, - listSharesSegmentedNew: { - reliesOnPath: ['storageAccounts.listKeys'], - rateLimit: 3000 - } + sendIntegration: serviceMap['File Service'] }, blobService: { listContainersSegmented: { diff --git a/helpers/azure/functions.js b/helpers/azure/functions.js index ea5c11c22a..bdf7804475 100644 --- a/helpers/azure/functions.js +++ b/helpers/azure/functions.js @@ -2,7 +2,7 @@ var shared = require(__dirname + '/../shared.js'); var auth = require(__dirname + '/auth.js'); var async = require('async'); -const defualyPolicyAssignments = { +const defualtPolicyAssignments = { adaptiveApplicationControlsMonitoringEffect: 'AuditIfNotExists', diskEncryptionMonitoringEffect: 'AuditIfNotExists', endpointProtectionMonitoringEffect: 'AuditIfNotExists', @@ -178,8 +178,8 @@ function checkPolicyAssignment(policyAssignments, param, text, results, location const policyAssignment = policyAssignments.data.find((policyAssignment) => { return (policyAssignment && - policyAssignment.displayName && - policyAssignment.displayName.toLowerCase().includes('asc default')); + policyAssignment.displayName && + policyAssignment.displayName.toLowerCase().includes('asc default')); }); if (!policyAssignment) { @@ -191,16 +191,14 @@ function checkPolicyAssignment(policyAssignments, param, text, results, location // This check is required to handle a defect in the Azure API that causes // unmodified ASC policies to return an empty object for parameters: {} // https://knowledgebase.paloaltonetworks.com/KCSArticleDetail?id=kA10g000000PMSZCA4 - if (policyAssignment.parameters && - !Object.keys(policyAssignment.parameters).length) { - addResult(results, 0, - 'There ASC Default Policy Assignment includes all plugins', location, - policyAssignment.id); - return; - } - const policyAssignmentStatus = (policyAssignment.parameters && policyAssignment.parameters[param] && policyAssignment.parameters[param].value) || - defualyPolicyAssignments[param] || ''; + // The api used returns empty parameters in case of all the default values, + var policyAssignmentStatus = ''; + if (policyAssignment.parameters && Object.keys(policyAssignment.parameters).length) { + policyAssignmentStatus = (policyAssignment.parameters && policyAssignment.parameters[param] && policyAssignment.parameters[param].value) || defualtPolicyAssignments[param] || ''; + } else { + policyAssignmentStatus = defualtPolicyAssignments[param] + } if (!policyAssignmentStatus.length) { addResult(results, 0, diff --git a/helpers/shared.js b/helpers/shared.js index e13f8e1e47..988c40dbda 100644 --- a/helpers/shared.js +++ b/helpers/shared.js @@ -20,6 +20,10 @@ var processIntegration = function(serviceName, settings, collection, calls, post let localSettings = {}; localSettings = settings; + if (settings.govcloud) { + localEvent.awsOrGov = 'aws-us-gov'; + } + localEvent.collection = {}; localEvent.previousCollection = {}; diff --git a/plugins/aws/lambda/lambdaOldRuntimes.js b/plugins/aws/lambda/lambdaOldRuntimes.js index 9ba49b5e22..57e072c487 100644 --- a/plugins/aws/lambda/lambdaOldRuntimes.js +++ b/plugins/aws/lambda/lambdaOldRuntimes.js @@ -36,14 +36,21 @@ module.exports = { { 'id':'nodejs8.10', 'name': 'Node.js 8.10', 'endOfLifeDate': '2020-03-06' }, { 'id':'nodejs10.x', 'name': 'Node.js 10.x', 'endOfLifeDate': '2022-02-14' }, { 'id':'nodejs12.x', 'name': 'Node.js 12', 'endOfLifeDate': '2023-03-31'}, + { 'id':'nodejs14.x', 'name': 'Node.js 14', 'endOfLifeDate': '2023-11-27'}, + { 'id':'nodejs16.x', 'name': 'Node.js 16', 'endOfLifeDate': '2024-03-11'}, { 'id':'dotnetcore3.1', 'name': '.Net Core 3.1', 'endOfLifeDate': '2023-03-31' }, { 'id':'dotnetcore2.1', 'name': '.Net Core 2.1', 'endOfLifeDate': '2022-04-15' }, { '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':'dotnet7', 'name': '.Net 7', 'endOfLifeDate': '2024-05-14' }, { 'id':'python2.7', 'name': 'Python 2.7', 'endOfLifeDate': '2022-05-30' }, { 'id':'python3.5', 'name': 'Python 3.5', 'endOfLifeDate': '2020-09-13' }, { 'id':'ruby2.5', 'name': 'Ruby 2.5', 'endOfLifeDate': '2022-03-31' }, + { 'id':'ruby2.7', 'name': 'Ruby 2.7', 'endOfLifeDate': '2023-12-07' }, { 'id':'python3.6', 'name': 'Python 3.6', 'endOfLifeDate': '2022-08-29'}, + { 'id':'python3.7', 'name': 'Python 3.7', 'endOfLifeDate': '2023-11-27'}, + { 'id':'go1.x', 'name': 'Go 1', 'endOfLifeDate': '2023-12-31'}, + { 'id':'java8', 'name': 'Java 8', 'endOfLifeDate': '2023-12-31'}, ]; async.each(regions.lambda, function(region, rcb){ diff --git a/plugins/azure/fileservice/fileServiceAllAccessAcl.js b/plugins/azure/fileservice/fileServiceAllAccessAcl.js index e6c7fa229d..9cdbeed9e3 100644 --- a/plugins/azure/fileservice/fileServiceAllAccessAcl.js +++ b/plugins/azure/fileservice/fileServiceAllAccessAcl.js @@ -9,8 +9,8 @@ module.exports = { description: 'Ensures file shares do not allow full write, delete, or read ACL permissions', more_info: 'File shares can be configured to allow to read, write, or delete permissions from a share. This option should not be configured unless there is a strong business requirement.', recommended_action: 'Disable global read, write, and delete policies on all file shares and ensure the share ACL is configured with least privileges.', - link: 'https://learn.microsoft.com/en-us/azure/storage/files/storage-how-to-create-file-share#create-a-file-share-through-the-azure-portal', - apis: ['storageAccounts:list', 'storageAccounts:listKeys', 'fileService:listSharesSegmentedNew', 'fileService:getShareAcl'], + link: 'https://docs.microsoft.com/en-us/azure/storage/files/storage-how-to-create-file-share#create-a-file-share-through-the-azure-portal', + apis: ['storageAccounts:list', 'storageAccounts:listKeys', 'fileService:listSharesSegmented', 'fileService:getShareAcl'], compliance: { hipaa: 'HIPAA access controls require data to be secured with least-privileged ' + 'ACLs. File Service ACLs enable granular permissions for data access.', @@ -60,7 +60,6 @@ module.exports = { 'No existing File Service shares found', location, storageAccount.id); } else { listSharesSegmented.data.forEach(function(fileShare) { - fileShare.id = `${storageAccount.id}/fileService/${fileShare.name}`; // Add share ACL var getShareAcl = helpers.addSource(cache, source, ['fileService', 'getShareAcl', location, fileShare.id]); diff --git a/plugins/azure/fileservice/fileServiceAllAccessAcl.spec.js b/plugins/azure/fileservice/fileServiceAllAccessAcl.spec.js index b9a83e5d74..449d0e171b 100644 --- a/plugins/azure/fileservice/fileServiceAllAccessAcl.spec.js +++ b/plugins/azure/fileservice/fileServiceAllAccessAcl.spec.js @@ -40,7 +40,8 @@ const listKeys = [ const listSharesSegmented = [ { - "name": "file1 " + "name": "file1", + "id": "/subscriptions/1234/resourceGroups/cloud-shell-storage-eastus/providers/Microsoft.Storage/storageAccounts/csb100320011e293683/fileService/file1" } ]; diff --git a/plugins/azure/monitor/logProfileRetentionPolicy.js b/plugins/azure/monitor/logProfileRetentionPolicy.js deleted file mode 100644 index 9c99cfc604..0000000000 --- a/plugins/azure/monitor/logProfileRetentionPolicy.js +++ /dev/null @@ -1,67 +0,0 @@ -var async = require('async'); -var helpers = require('../../../helpers/azure'); - -module.exports = { - title: 'Log Profile Retention Policy', - category: 'Monitor', - domain: 'Management and Governance', - description: 'Ensures that Log Profiles have a long retention policy.', - more_info: 'Log retention policies should be configured with sufficient retention to aid in investigation of prior security incidents and for compliance purposes.', - recommended_action: 'Ensure that the Activity Log export to Event Hub is configured with a retention policy of at least 365 days.', - link: 'https://learn.microsoft.com/en-us/azure/monitoring-and-diagnostics/monitoring-overview-activity-logs#export-the-activity-log-with-a-log-profile', - apis: ['logProfiles:list'], - compliance: { - pci: 'PCI requires log profile retention history to be' + - ' a minimum of 365 days.', - hipaa: 'HIPAA requires log profile data to be archived ' + - 'for a minimum of 365 days.' - }, - - run: function(cache, settings, callback) { - var results = []; - var source = {}; - var locations = helpers.locations(settings.govcloud); - - async.each(locations.logProfiles, (location, rcb) => { - const logProfiles = helpers.addSource(cache, source, - ['logProfiles', 'list', location]); - - if (!logProfiles) return rcb(); - - if (logProfiles.err || !logProfiles.data) { - helpers.addResult(results, 3, - 'Unable to query for Log Profiles: ' + helpers.addError(logProfiles), location); - return rcb(); - } - - if (!logProfiles.data.length) { - helpers.addResult(results, 2, 'No existing Log Profiles found', location); - return rcb(); - } - - logProfiles.data.forEach(function(logProfile) { - if (!logProfile.retentionPolicy) { - helpers.addResult(results, 2, - 'The Log Profile does not have a retention policy', - location, logProfile.id); - } else if (!logProfile.retentionPolicy.enabled) { - helpers.addResult(results, 2, - 'The Log Profile retention policy is not enabled', - location, logProfile.id); - } else if (!logProfile.retentionPolicy.days || logProfile.retentionPolicy.days < 365) { - helpers.addResult(results, 2, - `The Log Profile retention policy of ${logProfile.retentionPolicy.days || '0'} days is not sufficient (at least 365 days).`, - location, logProfile.id); - } else { - helpers.addResult(results, 0, - `The Log Profile retention policy of ${logProfile.retentionPolicy.days} days is sufficient.`, - location, logProfile.id); - } - }); - - rcb(); - }, function() { - callback(null, results, source); - }); - } -}; \ No newline at end of file diff --git a/plugins/azure/monitor/logProfileRetentionPolicy.spec.js b/plugins/azure/monitor/logProfileRetentionPolicy.spec.js deleted file mode 100644 index e3f1f6749b..0000000000 --- a/plugins/azure/monitor/logProfileRetentionPolicy.spec.js +++ /dev/null @@ -1,200 +0,0 @@ -var expect = require('chai').expect; -var logProfileRetentionPolicy = require('./logProfileRetentionPolicy'); - -const logProfile = [ - { - "id": "/subscriptions/1234/providers/microsoft.insights/logprofiles/test", - "type": null, - "name": "default", - "location": null, - "kind": null, - "tags": null, - "identity": null, - "storageAccountId": "/subscriptions/1234/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.Storage/storageAccounts/devstoragetwo", - "serviceBusRuleId": null, - "locations": [ - "australiacentral", - "australiacentral2", - "australiaeast", - "australiasoutheast", - "brazilsouth", - "canadacentral", - "canadaeast", - "centralindia", - "centralus", - "eastasia", - "eastus", - "eastus2", - "francecentral", - "francesouth", - "japaneast", - "japanwest", - "koreacentral", - "koreasouth", - "northcentralus", - "northeurope", - "southafricanorth", - "southafricawest", - "southcentralus", - "southindia", - "southeastasia", - "uaecentral", - "uaenorth", - "uksouth", - "ukwest", - "westcentralus", - "westeurope", - "westindia", - "westus", - "westus2", - "westus3", - "eastus2euap", - "centraluseuap", - "jioindiawest", - "jioindiacentral", - "swedencentral", - "germanywestcentral", - "germanycentral", - "germanynortheast", - "germanynorth", - "norwayeast", - "switzerlandnorth", - "norwaywest", - "switzerlandwest", - "brazilsoutheast", - "global" - ], - "categories": [ - "Write", - "Delete", - "Action" - ], - "retentionPolicy": { - "enabled": true, - "days": 366 - } - }, - { - "id": "/subscriptions/1234/providers/microsoft.insights/logprofiles/default", - "type": null, - "name": "default", - "location": null, - "kind": null, - "tags": null, - "identity": null, - "storageAccountId": "/subscriptions/1234/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.Storage/storageAccounts/devstoragetwo", - "serviceBusRuleId": null, - "retentionPolicy": { - "enabled": true, - "days": 82 - } - }, - { - "id": "/subscriptions/1234/providers/microsoft.insights/logprofiles/default", - "type": null, - "name": "default", - "location": null, - "kind": null, - "tags": null, - "identity": null, - "storageAccountId": "/subscriptions/1234/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.Storage/storageAccounts/devstoragetwo", - "serviceBusRuleId": null, - }, - { - "id": "/subscriptions/1234/providers/microsoft.insights/logprofiles/default", - "type": null, - "name": "default", - "location": null, - "kind": null, - "tags": null, - "identity": null, - "storageAccountId": "/subscriptions/1234/resourceGroups/Default-ActivityLogAlerts/providers/Microsoft.Storage/storageAccounts/devstoragetwo", - "serviceBusRuleId": null, - "retentionPolicy": { - } - }, -]; - -const createCache = (logProfile) => { - let settings = {}; - if (logProfile) { - settings['data'] = logProfile; - } - return { - logProfiles: { - list: { - 'global': settings - } - } - }; -}; - -describe('logProfileRetentionPolicy', function() { - describe('run', function() { - it('should give passing result if No existing Log Profiles found', function(done) { - const cache = createCache([]); - logProfileRetentionPolicy.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('No existing Log Profiles found'); - expect(results[0].region).to.equal('global'); - done(); - }); - }); - - it('should give unknown result if Unable to query for Log Profiles', function(done) { - const cache = createCache(); - logProfileRetentionPolicy.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(3); - expect(results[0].message).to.include('Unable to query for Log Profiles'); - expect(results[0].region).to.equal('global'); - done(); - }); - }); - - it('should give passing result if The Log Profile retention policy is sufficient', function(done) { - const cache = createCache([logProfile[0]]); - logProfileRetentionPolicy.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('The Log Profile retention policy'); - expect(results[0].region).to.equal('global'); - done(); - }); - }); - - it('should give failing result if The Log Profile retention policy is not sufficient', function(done) { - const cache = createCache([logProfile[1]]); - logProfileRetentionPolicy.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('The Log Profile retention policy'); - expect(results[0].region).to.equal('global'); - done(); - }); - }); - - it('should give failing result if The Log Profile does not have a retention policy', function(done) { - const cache = createCache([logProfile[2]]); - logProfileRetentionPolicy.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('The Log Profile does not have a retention policy'); - expect(results[0].region).to.equal('global'); - done(); - }); - }); - - it('should give failing result if The Log Profile retention policy is not enabled', function(done) { - const cache = createCache([logProfile[3]]); - logProfileRetentionPolicy.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('The Log Profile retention policy is not enabled'); - expect(results[0].region).to.equal('global'); - done(); - }); - }); - }); -}); diff --git a/plugins/azure/networksecuritygroups/networkWatcherEnabled.js b/plugins/azure/networksecuritygroups/networkWatcherEnabled.js index 83c5a553ec..2b51dee960 100644 --- a/plugins/azure/networksecuritygroups/networkWatcherEnabled.js +++ b/plugins/azure/networksecuritygroups/networkWatcherEnabled.js @@ -44,9 +44,8 @@ module.exports = { } networkWatchers.data.forEach((networkWatcher) => { - if (networkWatcher.properties && - networkWatcher.properties.provisioningState && - networkWatcher.properties.provisioningState.toLowerCase() == 'succeeded') { + if (networkWatcher.provisioningState && + networkWatcher.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 index 54fa27000a..35f9f6f61f 100644 --- a/plugins/azure/networksecuritygroups/networkWatcherEnabled.spec.js +++ b/plugins/azure/networksecuritygroups/networkWatcherEnabled.spec.js @@ -2,28 +2,24 @@ 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": [] + { + "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", + "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", + "provisioningState": "Failed", + "runningOperationIds": [] } - } ]; const virtualNetworks = [ @@ -41,22 +37,22 @@ const virtualNetworks = [ ] }, "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" - } + { + "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