From c586294b859bcf4dfdaa1045a51d313314faac6a Mon Sep 17 00:00:00 2001 From: Ali Imran <79709033+ali-imran7@users.noreply.github.com> Date: Tue, 1 Jun 2021 22:18:30 +0500 Subject: [PATCH] feature/AKD-189: Added Azure 'Always On Enabled' Plugin and test cases (#741) * feature/AKD-189: Added Azure 'Always On Enabled' Plugin and test cases * feature/AKD-189: Added Azure 'Always On Enabled' Plugin and test cases * Update plugins/azure/appservice/alwaysOnEnabled.js Co-authored-by: Gio Rodriguez --- exports.js | 1 + plugins/azure/appservice/alwaysOnEnabled.js | 64 ++++++++ .../azure/appservice/alwaysOnEnabled.spec.js | 143 ++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 plugins/azure/appservice/alwaysOnEnabled.js create mode 100644 plugins/azure/appservice/alwaysOnEnabled.spec.js diff --git a/exports.js b/exports.js index 7dd0ff10b4..37ac9908a1 100644 --- a/exports.js +++ b/exports.js @@ -496,6 +496,7 @@ module.exports = { 'http20Enabled' : require(__dirname + '/plugins/azure/appservice/http20Enabled.js'), 'httpsOnlyEnabled' : require(__dirname + '/plugins/azure/appservice/httpsOnlyEnabled.js'), 'tlsVersionCheck' : require(__dirname + '/plugins/azure/appservice/tlsVersionCheck.js'), + 'alwaysOnEnabled' : require(__dirname + '/plugins/azure/appservice/alwaysOnEnabled.js'), 'rbacEnabled' : require(__dirname + '/plugins/azure/kubernetesservice/rbacEnabled.js'), 'aksLatestVersion' : require(__dirname + '/plugins/azure/kubernetesservice/aksLatestVersion.js'), diff --git a/plugins/azure/appservice/alwaysOnEnabled.js b/plugins/azure/appservice/alwaysOnEnabled.js new file mode 100644 index 0000000000..2e956ac4b6 --- /dev/null +++ b/plugins/azure/appservice/alwaysOnEnabled.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', + 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', '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 alwaysOnEnabled = configs.data.some(config => config.alwaysOn); + 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/alwaysOnEnabled.spec.js b/plugins/azure/appservice/alwaysOnEnabled.spec.js new file mode 100644 index 0000000000..14f782071b --- /dev/null +++ b/plugins/azure/appservice/alwaysOnEnabled.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(); + }); + }); + }); +}); \ No newline at end of file