diff --git a/exports.js b/exports.js index 0fab601115..6168426a0b 100644 --- a/exports.js +++ b/exports.js @@ -1038,7 +1038,9 @@ module.exports = { 'amsDiagnosticLogsEnabled' : require(__dirname + '/plugins/azure/mediaServices/amsDiagnosticLogsEnabled.js'), 'amsPublicAccessDisabled' : require(__dirname + '/plugins/azure/mediaServices/amsPublicAccessDisabled.js'), 'amsManagedIdentityEnabled' : require(__dirname + '/plugins/azure/mediaServices/amsManagedIdentityEnabled.js'), - 'amsClassicApiDisabled' : require(__dirname + '/plugins/azure/mediaServices/amsClassicApiDisabled.js') + 'amsClassicApiDisabled' : require(__dirname + '/plugins/azure/mediaServices/amsClassicApiDisabled.js'), + + 'scaleSetLinuxSSHEnabled' : require(__dirname + '/plugins/azure/virtualmachinescaleset/scaleSetLinuxSSHEnabled.js'), }, github: { 'publicKeysRotated' : require(__dirname + '/plugins/github/users/publicKeysRotated.js'), diff --git a/helpers/azure/api.js b/helpers/azure/api.js index d2a855693d..2806750d18 100644 --- a/helpers/azure/api.js +++ b/helpers/azure/api.js @@ -383,7 +383,7 @@ var calls = { }, virtualMachineScaleSets: { listAll: { - url: 'https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Compute/virtualMachineScaleSets?api-version=2019-12-01' + url: 'https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Compute/virtualMachineScaleSets?api-version=2023-09-01' } }, bastionHosts: { diff --git a/plugins/azure/virtualmachinescaleset/scaleSetLinuxSSHEnabled.js b/plugins/azure/virtualmachinescaleset/scaleSetLinuxSSHEnabled.js new file mode 100644 index 0000000000..6a9df5cb6c --- /dev/null +++ b/plugins/azure/virtualmachinescaleset/scaleSetLinuxSSHEnabled.js @@ -0,0 +1,56 @@ +var async = require('async'); +var helpers = require('../../../helpers/azure'); + +module.exports = { + title: 'VM Scale Set Linux SSH Enabled', + category: 'Virtual Machine Scale Set', + domain: 'Compute', + description: 'Ensures that Azure Virtual Machine scale sets with Linux OS has SSH enabled.', + more_info: 'SSH is an encrypted connection protocol that allows secure sign-ins over unsecured connections. SSH is the default connection protocol for Linux VMs hosted in Azure.', + link: 'https://learn.microsoft.com/en-us/azure/virtual-machines/linux/ssh-from-windows', + recommended_action: 'Remove existing scale set and create new with SSH enabled', + apis: ['virtualMachineScaleSets:listAll'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var locations = helpers.locations(settings.govcloud); + + async.each(locations.vmScaleSet, function(location, rcb) { + + var vmScaleSets = helpers.addSource(cache, source, ['virtualMachineScaleSets', 'listAll', location]); + + if (!vmScaleSets) return rcb(); + + if (vmScaleSets.err || !vmScaleSets.data) { + helpers.addResult(results, 3, 'Unable to query for Virtual Machine Scale Sets: ' + helpers.addError(vmScaleSets), location); + return rcb(); + } + if (!vmScaleSets.data.length) { + helpers.addResult(results, 0, 'No existing Virtual Machine Scale Sets found', location); + return rcb(); + } + for (let scaleSet of vmScaleSets.data) { + if (!scaleSet.id) continue; + + if ((scaleSet.virtualMachineProfile.storageProfile && scaleSet.virtualMachineProfile.storageProfile.osDisk && + scaleSet.virtualMachineProfile.storageProfile.osDisk.osType && + scaleSet.virtualMachineProfile.storageProfile.osDisk.osType.toLowerCase() === 'linux')){ + + if (scaleSet.virtualMachineProfile && scaleSet.virtualMachineProfile.osProfile && + scaleSet.virtualMachineProfile.osProfile.linuxConfiguration && + scaleSet.virtualMachineProfile.osProfile.linuxConfiguration.ssh){ + helpers.addResult(results, 0, 'VM scale set for linux has SSH enabled', location, scaleSet.id); + } else { + helpers.addResult(results, 2, 'VM scale set for linux does not have SSH enabled', location, scaleSet.id); + } + } else { + continue; + } + } + rcb(); + }, function() { + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/azure/virtualmachinescaleset/scaleSetLinuxSSHEnabled.spec.js b/plugins/azure/virtualmachinescaleset/scaleSetLinuxSSHEnabled.spec.js new file mode 100644 index 0000000000..b5a23208d6 --- /dev/null +++ b/plugins/azure/virtualmachinescaleset/scaleSetLinuxSSHEnabled.spec.js @@ -0,0 +1,109 @@ +var expect = require('chai').expect; +var scaleSetLinuxSSHEnabled = require('./scaleSetLinuxSSHEnabled'); + +const virtualMachineScaleSets = [ + { + 'name': 'test-vmss', + 'id': '/subscriptions/123/resourceGroups/AQUA-RESOURCE-GROUP/providers/Microsoft.Compute/virtualMachineScaleSets/test-vmss', + 'type': 'Microsoft.Compute/virtualMachineScaleSets', + "virtualMachineProfile": { + "osProfile": { + "linuxConfiguration": { + "disablePasswordAuthentication": true, + "ssh": { + "publicKeys": [ + { + "path": "/home/azureuser/.ssh/authorized_keys", + "keyData": "" + } + ] + }, + }, + }, + "storageProfile": { + "osDisk": { + "osType": "Linux", + }, + } + } + }, + { + 'name': 'test-vmss', + 'id': '/subscriptions/123/resourceGroups/AQUA-RESOURCE-GROUP/providers/Microsoft.Compute/virtualMachineScaleSets/test-vmss', + 'type': 'Microsoft.Compute/virtualMachineScaleSets', + "virtualMachineProfile": { + "osProfile": { + "linuxConfiguration": { + "disablePasswordAuthentication": false + }, + }, + "storageProfile": { + "osDisk": { + "osType": "Linux", + }, + } + } + }, +]; + +const createCache = (virtualMachineScaleSets) => { + let machine = {}; + if (virtualMachineScaleSets) { + machine['data'] = virtualMachineScaleSets; + } + return { + virtualMachineScaleSets: { + listAll: { + 'eastus': machine + } + } + }; +}; + +describe('scaleSetLinuxSSHEnabled', function() { + describe('run', function() { + it('should give passing result if no virtual machine scale sets', function(done) { + const cache = createCache([]); + scaleSetLinuxSSHEnabled.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 Virtual Machine Scale Sets found'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give unknown result if unable to query for virtual machine scale sets', function(done) { + const cache = createCache(); + scaleSetLinuxSSHEnabled.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 Machine Scale Sets:'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give passing result if VM scale set for linux has SSH enabled', function(done) { + const cache = createCache([virtualMachineScaleSets[0]]); + scaleSetLinuxSSHEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].message).to.include('VM scale set for linux has SSH enabled'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + + it('should give failing result if VM scale set for linux does not have SSH enabled', function(done) { + const cache = createCache([virtualMachineScaleSets[1]]); + scaleSetLinuxSSHEnabled.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].message).to.include('VM scale set for linux does not have SSH enabled'); + expect(results[0].region).to.equal('eastus'); + done(); + }); + }); + }); +}); \ No newline at end of file