Skip to content

Commit cf9cd42

Browse files
authored
Merge pull request #2206 from Hamza-Aziz61/SLK-137462/azure-plugins-draft-2
SLK-137462/azure-plugins-draft-2
2 parents 40b42b3 + 7be3574 commit cf9cd42

35 files changed

Lines changed: 3207 additions & 0 deletions

‎exports.js‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,10 +732,14 @@ module.exports = {
732732
'blobServiceEncryption' : require(__dirname + '/plugins/azure/storageaccounts/blobServiceEncryption.js'),
733733
'trustedMsAccessEnabled' : require(__dirname + '/plugins/azure/storageaccounts/trustedMsAccessEnabled.js'),
734734
'blobSoftDeletionEnabled' : require(__dirname + '/plugins/azure/storageaccounts/blobSoftDeletionEnabled.js'),
735+
'containerSoftDeletionEnabled' : require(__dirname + '/plugins/azure/storageaccounts/containerSoftDeletionEnabled.js'),
736+
'blobVersioningEnabled' : require(__dirname + '/plugins/azure/storageaccounts/blobVersioningEnabled.js'),
735737
'storageAccountKeyRotationReminder': require(__dirname + '/plugins/azure/storageaccounts/storageAccountKeyRotationReminder.js'),
736738
'storageAccountKeyRotation' : require(__dirname + '/plugins/azure/storageaccounts/storageAccountKeyRotation.js'),
737739
'sharedKeyAccessDisabled' : require(__dirname + '/plugins/azure/storageaccounts/sharedKeyAccessDisabled.js'),
738740
'storageAccountEntraIdAuthDefault': require(__dirname + '/plugins/azure/storageaccounts/storageAccountEntraIdAuthDefault.js'),
741+
'crossTenantReplicationDisabled': require(__dirname + '/plugins/azure/storageaccounts/crossTenantReplicationDisabled.js'),
742+
'blobAnonymousAccessDisabled' : require(__dirname + '/plugins/azure/storageaccounts/blobAnonymousAccessDisabled.js'),
739743
'geoRedundantStorage' : require(__dirname + '/plugins/azure/storageaccounts/geoRedundantStorage.js'),
740744
'fileShareSoftDeletionEnabled' : require(__dirname + '/plugins/azure/storageaccounts/fileShareSoftDeletionEnabled.js'),
741745
'fileShareSmbProtocolVersion' : require(__dirname + '/plugins/azure/storageaccounts/fileShareSmbProtocolVersion.js'),
@@ -785,8 +789,10 @@ module.exports = {
785789
'redisCacheVNetIntegrated' : require(__dirname + '/plugins/azure/redisCache/redisCacheVNetIntegrated.js'),
786790

787791
'multipleSubnets' : require(__dirname + '/plugins/azure/virtualnetworks/multipleSubnets.js'),
792+
'subnetNetworkSecurityGroup' : require(__dirname + '/plugins/azure/virtualnetworks/subnetNetworkSecurityGroup.js'),
788793
'ddosStandardProtectionEnabled' : require(__dirname + '/plugins/azure/virtualnetworks/ddosStandardProtectionEnabled.js'),
789794
'noNetworkGatewaysInUse' : require(__dirname + '/plugins/azure/virtualnetworks/noNetworkGatewaysInUse.js'),
795+
'vpnGatewayEntraIdAuth' : require(__dirname + '/plugins/azure/virtualnetworks/vpnGatewayEntraIdAuth.js'),
790796
'virtualNetworkPeering' : require(__dirname + '/plugins/azure/virtualnetworks/virtualNetworkPeering.js'),
791797
'noGatewayConnections' : require(__dirname + '/plugins/azure/virtualnetworks/noGatewayConnections.js'),
792798
'managedNatGateway' : require(__dirname + '/plugins/azure/virtualnetworks/managedNatGateway.js'),
@@ -849,6 +855,7 @@ module.exports = {
849855
'bastionHostHasTags' : require(__dirname + '/plugins/azure/bastion/bastionHostHasTags.js'),
850856

851857
'logProfileArchiveData' : require(__dirname + '/plugins/azure/monitor/logProfileArchiveData.js'),
858+
'appInsightsConfigured' : require(__dirname + '/plugins/azure/monitor/appInsightsConfigured.js'),
852859
'logAnalyticsWorkspacePublic' : require(__dirname + '/plugins/azure/monitor/logAnalyticsWorkspacePublic.js'),
853860
'monitorLogsEnabled' : require(__dirname + '/plugins/azure/monitor/monitorLogsEnabled.js'),
854861
'diagnosticsCapturedCategories' : require(__dirname + '/plugins/azure/monitor/diagnosticsCapturedCategories.js'),
@@ -857,6 +864,7 @@ module.exports = {
857864

858865
'securityPolicyAlertsEnabled' : require(__dirname + '/plugins/azure/logalerts/securityPolicyAlertsEnabled.js'),
859866
'nsgLoggingEnabled' : require(__dirname + '/plugins/azure/logalerts/nsgLoggingEnabled.js'),
867+
'serviceHealthAlertEnabled' : require(__dirname + '/plugins/azure/logalerts/serviceHealthAlertEnabled.js'),
860868
'sqlServerFirewallRuleEnabled' : require(__dirname + '/plugins/azure/logalerts/sqlServerFirewallRuleEnabled.js'),
861869
'virtualNetworkRuleEnabled' : require(__dirname + '/plugins/azure/logalerts/virtualNetworkRuleEnabled.js'),
862870
'securitySolutionLogging' : require(__dirname + '/plugins/azure/logalerts/securitySolutionLogging.js'),
@@ -1065,7 +1073,10 @@ module.exports = {
10651073
'passwordRequiresUppercase' : require(__dirname + '/plugins/azure/entraid/passwordRequiresUppercase.js'),
10661074
'minPasswordLength' : require(__dirname + '/plugins/azure/entraid/minPasswordLength.js'),
10671075
'ensureNoGuestUser' : require(__dirname + '/plugins/azure/entraid/ensureNoGuestUser.js'),
1076+
'securityDefaultsEnabled' : require(__dirname + '/plugins/azure/entraid/securityDefaultsEnabled.js'),
10681077
'userAccessAdminRestricted' : require(__dirname + '/plugins/azure/entraid/userAccessAdminRestricted.js'),
1078+
'disabledUserRoleAssignments' : require(__dirname + '/plugins/azure/entraid/disabledUserRoleAssignments.js'),
1079+
'resourceLockAdminRole' : require(__dirname + '/plugins/azure/entraid/resourceLockAdminRole.js'),
10691080
'subscriptionOwnerCount' : require(__dirname + '/plugins/azure/entraid/subscriptionOwnerCount.js'),
10701081
'noCustomOwnerRoles' : require(__dirname + '/plugins/azure/entraid/noCustomOwnerRoles.js'),
10711082
'appOrgnaizationalDirectoryAccess' : require(__dirname + '/plugins/azure/entraid/appOrgnaizationalDirectoryAccess.js'),
@@ -1099,6 +1110,9 @@ module.exports = {
10991110
'keyVaultSecretExpiry' : require(__dirname + '/plugins/azure/keyvaults/keyVaultSecretExpiry.js'),
11001111
'keyVaultSecretExpiryNonRbac' : require(__dirname + '/plugins/azure/keyvaults/keyVaultSecretExpiryNonRbac.js'),
11011112
'keyVaultKeyExpiry' : require(__dirname + '/plugins/azure/keyvaults/keyVaultKeyExpiry.js'),
1113+
'keyVaultRbacEnabled' : require(__dirname + '/plugins/azure/keyvaults/keyVaultRbacEnabled.js'),
1114+
'keyVaultKeyRotation' : require(__dirname + '/plugins/azure/keyvaults/keyVaultKeyRotation.js'),
1115+
'certificateValidityPeriod' : require(__dirname + '/plugins/azure/keyvaults/certificateValidityPeriod.js'),
11021116
'keyVaultKeyExpiryNonRbac' : require(__dirname + '/plugins/azure/keyvaults/keyVaultKeyExpiryNonRbac.js'),
11031117
'allowedCertificateKeyTypes' : require(__dirname + '/plugins/azure/keyvaults/allowedCertificateKeyTypes.js'),
11041118
'appTierCmkInUse' : require(__dirname + '/plugins/azure/keyvaults/appTierCmkInUse.js'),
@@ -1135,6 +1149,7 @@ module.exports = {
11351149
'enableDefenderForCosmosDB' : require(__dirname + '/plugins/azure/defender/enableDefenderForCosmosDB.js'),
11361150
'enableDefenderForSqlServersVMs': require(__dirname + '/plugins/azure/defender/enableDefenderForSqlServersVMs.js'),
11371151
'highSeverityAlertsEnabled' : require(__dirname + '/plugins/azure/defender/highSeverityAlertsEnabled.js'),
1152+
'attackPathNotificationsEnabled': require(__dirname + '/plugins/azure/defender/attackPathNotificationsEnabled.js'),
11381153
'standardPricingEnabled' : require(__dirname + '/plugins/azure/defender/standardPricingEnabled.js'),
11391154
'monitorExternalAccounts' : require(__dirname + '/plugins/azure/defender/monitorExternalAccounts.js'),
11401155
'monitorIpForwarding' : require(__dirname + '/plugins/azure/defender/monitorIpForwarding.js'),
@@ -1151,6 +1166,7 @@ module.exports = {
11511166
'securityContactsEnabled' : require(__dirname + '/plugins/azure/defender/securityContactsEnabled.js'),
11521167

11531168
'agWafEnabled' : require(__dirname + '/plugins/azure/applicationGateway/agWafEnabled'),
1169+
'agHttp2Enabled' : require(__dirname + '/plugins/azure/applicationGateway/agHttp2Enabled'),
11541170
'applicationGatewayHasTags' : require(__dirname + '/plugins/azure/applicationGateway/applicationGatewayHasTags.js'),
11551171
'agSecurityLoggingEnabled' : require(__dirname + '/plugins/azure/applicationGateway/agSecurityLoggingEnabled.js'),
11561172
'agSslPolicy' : require(__dirname + '/plugins/azure/applicationGateway/agSslPolicy'),
@@ -1165,6 +1181,7 @@ module.exports = {
11651181
'rgHasTags' : require(__dirname + '/plugins/azure/resourceGroup/rgHasTags.js'),
11661182

11671183
'wafPolicyHasTags' : require(__dirname + '/plugins/azure/waf/wafPolicyHasTags.js'),
1184+
'wafPolicyBotProtection' : require(__dirname + '/plugins/azure/waf/wafPolicyBotProtection.js'),
11681185

11691186
'recoveryVaultByokEncrypted' : require(__dirname + '/plugins/azure/recoveryService/recoveryVaultByokEncrypted.js'),
11701187
'recoveryVaultLoggingEnabled' : require(__dirname + '/plugins/azure/recoveryService/recoveryVaultLoggingEnabled.js'),
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
const async = require('async');
2+
const helpers = require('../../../helpers/azure');
3+
4+
module.exports = {
5+
title: 'Application Gateway HTTP2 Enabled',
6+
category: 'Application Gateway',
7+
domain: 'Network Access Control',
8+
severity: 'Low',
9+
description: 'Ensures that HTTP2 is enabled for Application Gateways.',
10+
more_info: 'HTTP2 support is available to clients that connect to application gateway listeners and provides improved performance and efficiency over HTTP1.1. Clients and backend services that do not support HTTP2 fall back to HTTP1.1.',
11+
recommended_action: 'Enable HTTP2 from the configuration settings of the application gateway.',
12+
link: 'https://learn.microsoft.com/en-us/azure/application-gateway/configuration-overview',
13+
apis: ['applicationGateway:listAll'],
14+
realtime_triggers: ['microsoftnetwork:applicationgateways:write', 'microsoftnetwork:applicationgateways:delete'],
15+
16+
run: function(cache, settings, callback) {
17+
const results = [];
18+
const source = {};
19+
const locations = helpers.locations(settings.govcloud);
20+
21+
async.each(locations.applicationGateway, (location, rcb) => {
22+
var appGateways = helpers.addSource(cache, source,
23+
['applicationGateway', 'listAll', location]);
24+
25+
if (!appGateways) return rcb();
26+
27+
if (appGateways.err || !appGateways.data) {
28+
helpers.addResult(results, 3, 'Unable to query for Application Gateway: ' + helpers.addError(appGateways), location);
29+
return rcb();
30+
}
31+
32+
if (!appGateways.data.length) {
33+
helpers.addResult(results, 0, 'No existing Application Gateway found', location);
34+
return rcb();
35+
}
36+
37+
for (let appGateway of appGateways.data) {
38+
if (!appGateway.id) continue;
39+
40+
if (appGateway.enableHttp2) {
41+
helpers.addResult(results, 0, 'HTTP2 is enabled for Application Gateway', location, appGateway.id);
42+
} else {
43+
helpers.addResult(results, 2, 'HTTP2 is not enabled for Application Gateway', location, appGateway.id);
44+
}
45+
}
46+
47+
rcb();
48+
}, function() {
49+
callback(null, results, source);
50+
});
51+
}
52+
};
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
var expect = require('chai').expect;
2+
var agHttp2Enabled = require('./agHttp2Enabled');
3+
4+
const appGateways = [
5+
{
6+
'name': 'test-ag',
7+
'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Network/applicationGateways/test-ag',
8+
'type': 'Microsoft.Network/applicationGateways',
9+
'location': 'eastus',
10+
'enableHttp2': true
11+
},
12+
{
13+
'name': 'test-ag',
14+
'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Network/applicationGateways/test-ag',
15+
'type': 'Microsoft.Network/applicationGateways',
16+
'location': 'eastus',
17+
'enableHttp2': false
18+
},
19+
{
20+
'name': 'test-ag',
21+
'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Network/applicationGateways/test-ag',
22+
'type': 'Microsoft.Network/applicationGateways',
23+
'location': 'eastus'
24+
}
25+
];
26+
27+
const createCache = (appGateways) => {
28+
return {
29+
applicationGateway: {
30+
listAll: {
31+
'eastus': {
32+
data: appGateways
33+
}
34+
}
35+
}
36+
};
37+
};
38+
39+
const createErrorCache = () => {
40+
return {
41+
applicationGateway: {
42+
listAll: {
43+
'eastus': {}
44+
}
45+
}
46+
};
47+
};
48+
49+
describe('agHttp2Enabled', function () {
50+
describe('run', function () {
51+
it('should give passing result if no application gateways found', function (done) {
52+
const cache = createCache([]);
53+
agHttp2Enabled.run(cache, {}, (err, results) => {
54+
expect(results.length).to.equal(1);
55+
expect(results[0].status).to.equal(0);
56+
expect(results[0].message).to.include('No existing Application Gateway found');
57+
expect(results[0].region).to.equal('eastus');
58+
done();
59+
});
60+
});
61+
62+
it('should give unknown result if unable to query for application gateways', function (done) {
63+
const cache = createErrorCache();
64+
agHttp2Enabled.run(cache, {}, (err, results) => {
65+
expect(results.length).to.equal(1);
66+
expect(results[0].status).to.equal(3);
67+
expect(results[0].message).to.include('Unable to query for Application Gateway');
68+
expect(results[0].region).to.equal('eastus');
69+
done();
70+
});
71+
});
72+
73+
it('should give passing result if HTTP2 is enabled for application gateway', function (done) {
74+
const cache = createCache([appGateways[0]]);
75+
agHttp2Enabled.run(cache, {}, (err, results) => {
76+
expect(results.length).to.equal(1);
77+
expect(results[0].status).to.equal(0);
78+
expect(results[0].message).to.include('HTTP2 is enabled for Application Gateway');
79+
expect(results[0].region).to.equal('eastus');
80+
done();
81+
});
82+
});
83+
84+
it('should give failing result if HTTP2 is not enabled for application gateway', function (done) {
85+
const cache = createCache([appGateways[1]]);
86+
agHttp2Enabled.run(cache, {}, (err, results) => {
87+
expect(results.length).to.equal(1);
88+
expect(results[0].status).to.equal(2);
89+
expect(results[0].message).to.include('HTTP2 is not enabled for Application Gateway');
90+
expect(results[0].region).to.equal('eastus');
91+
done();
92+
});
93+
});
94+
95+
it('should give failing result if HTTP2 setting does not exist for application gateway', function (done) {
96+
const cache = createCache([appGateways[2]]);
97+
agHttp2Enabled.run(cache, {}, (err, results) => {
98+
expect(results.length).to.equal(1);
99+
expect(results[0].status).to.equal(2);
100+
expect(results[0].message).to.include('HTTP2 is not enabled for Application Gateway');
101+
expect(results[0].region).to.equal('eastus');
102+
done();
103+
});
104+
});
105+
});
106+
});
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
const async = require('async');
2+
const helpers = require('../../../helpers/azure');
3+
4+
module.exports = {
5+
title: 'Attack Path Notifications Enabled',
6+
category: 'Defender',
7+
domain: 'Management and Governance',
8+
severity: 'Low',
9+
description: 'Ensures that email notifications for attack paths are enabled for the subscription.',
10+
more_info: 'Enabling attack path email notifications ensures that the subscription owner or other designated security contact is notified of new attack paths detected by Microsoft Defender for Cloud, allowing for quick mitigation of the associated risks.',
11+
recommended_action: 'Enable email notifications for attack paths from the Microsoft Defender for Cloud email notifications settings.',
12+
link: 'https://learn.microsoft.com/en-us/azure/defender-for-cloud/configure-email-notifications',
13+
apis: ['securityContactv3:listAll'],
14+
realtime_triggers: ['microsoftsecurity:securitycontacts:write', 'microsoftsecurity:securitycontacts:delete'],
15+
16+
run: function(cache, settings, callback) {
17+
const results = [];
18+
const source = {};
19+
const locations = helpers.locations(settings.govcloud);
20+
21+
async.each(locations.securityContactv3, (location, rcb) => {
22+
var securityContacts = helpers.addSource(cache, source,
23+
['securityContactv3', 'listAll', location]);
24+
25+
if (!securityContacts) return rcb();
26+
27+
if (securityContacts.err || !securityContacts.data) {
28+
helpers.addResult(results, 3,
29+
'Unable to query for security contacts: ' + helpers.addError(securityContacts), location);
30+
return rcb();
31+
}
32+
33+
if (!securityContacts.data.length) {
34+
helpers.addResult(results, 2, 'No existing security contacts found', location);
35+
return rcb();
36+
}
37+
38+
for (let contact of securityContacts.data) {
39+
if (!contact.id) continue;
40+
41+
var attackPathSource = contact.notificationsSources ?
42+
contact.notificationsSources.find(notifSource => notifSource.sourceType &&
43+
notifSource.sourceType.toLowerCase() === 'attackpath') : null;
44+
45+
if (attackPathSource && attackPathSource.minimalRiskLevel) {
46+
helpers.addResult(results, 0,
47+
`Attack path email notifications are enabled with minimum risk level ${attackPathSource.minimalRiskLevel}`, location, contact.id);
48+
} else {
49+
helpers.addResult(results, 2, 'Attack path email notifications are not enabled', location, contact.id);
50+
}
51+
}
52+
53+
rcb();
54+
}, function() {
55+
callback(null, results, source);
56+
});
57+
}
58+
};

0 commit comments

Comments
 (0)