Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/AKD-110: Added Azure 'Auto-Failover Groups Enabled' plugin and test cases #636

Merged
merged 6 commits into from
Jun 1, 2021
7 changes: 7 additions & 0 deletions collectors/azure/collector.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,13 @@ var postcalls = {
url: 'https://management.azure.com/{id}/securityAlertPolicies?api-version=2017-03-01-preview'
}
},
failoverGroups: {
listByServer: {
reliesOnPath: 'servers.listSql',
properties: ['id'],
url: 'https://management.azure.com/{id}/failoverGroups?api-version=2017-03-01-preview'
}
},
configurations: {
listByServer: {
reliesOnPath: 'servers.listPostgres',
Expand Down
1 change: 1 addition & 0 deletions exports.js
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ module.exports = {
'serverAuditingEnabled' : require(__dirname + '/plugins/azure/sqlserver/serverAuditingEnabled.js'),
'azureADAdminEnabled' : require(__dirname + '/plugins/azure/sqlserver/azureADAdminEnabled.js'),
'sqlServerTlsVersion' : require(__dirname + '/plugins/azure/sqlserver/sqlServerTlsVersion.js'),
'autoFailoverGroupsEnabled' : require(__dirname + '/plugins/azure/sqlserver/autoFailoverGroupsEnabled.js'),

'javaVersion' : require(__dirname + '/plugins/azure/appservice/javaVersion.js'),
'phpVersion' : require(__dirname + '/plugins/azure/appservice/phpVersion.js'),
Expand Down
59 changes: 59 additions & 0 deletions plugins/azure/sqlserver/autoFailoverGroupsEnabled.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
var async = require('async');
const helpers = require('../../../helpers/azure');

module.exports = {
title: 'Auto-Failover Groups Enabled',
category: 'SQL Server',
description: 'Ensures that auto-failover groups are configured for Azure SQL database servers.',
more_info: 'In case of any outage that impacts one or more SQL databases, automatic failover process switches all secondary databases in the group to primary databases to ensure high availability.',
recommended_action: 'Ensure that auto-failover Groups are configured for Azure SQL database servers',
link: 'https://docs.microsoft.com/en-us/azure/azure-sql/database/auto-failover-group-overview',
apis: ['servers:listSql', 'failoverGroups:listByServer'],

run: function(cache, settings, callback) {
var results = [];
var source = {};
var locations = helpers.locations(settings.govcloud);

async.each(locations.servers, function(location, rcb) {

const 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();
}

for (const server of servers.data) {
const failoverGroups = helpers.addSource(cache, source,
['failoverGroups', 'listByServer', location, server.id]);

if (!failoverGroups || failoverGroups.err || !failoverGroups.data) {
helpers.addResult(results, 3,
'Unable to query for auto-failover groups: ' + helpers.addError(failoverGroups), location, server.id);
return rcb();
giorod3 marked this conversation as resolved.
Show resolved Hide resolved
}

if (failoverGroups.data.length) {
helpers.addResult(results, 0, 'Auto-failover groups are configured for the SQL server', location, server.id);
} else {
helpers.addResult(results, 2, 'Auto-failover groups are not configured for the SQL server', location, server.id);
}
}

rcb();
}, function() {
// Global checking goes here
callback(null, results, source);
});
}
};
103 changes: 103 additions & 0 deletions plugins/azure/sqlserver/autoFailoverGroupsEnabled.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
var expect = require('chai').expect;
var autoFailoverGroupsEnabled = require('./autoFailoverGroupsEnabled');

const servers = [
{
'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Sql/servers/test-server',
'name': 'test-server',
'location': 'eastus'
}
];

const failoverGroups = [
{
'id': '/subscriptions/123/resourceGroups/aqua-resource-group/providers/Microsoft.Sql/servers/test-server/failoverGroups/test-group',
'name': 'test-group',
'type': 'Microsoft.Sql/servers/failoverGroups'
}
];


const createCache = (servers, failoverGroups) => {
let server = {};
let groups = {};
if (servers) {
server['data'] = servers;
if (servers.length > 0 && failoverGroups) {
groups[servers[0].id] = {
data: failoverGroups
};
}
}
return {
servers: {
listSql: {
'eastus': server
}
},
failoverGroups: {
listByServer: {
'eastus': groups
}
}
};
};

describe('autoFailoverGroupsEnabled', function() {
describe('run', function() {
it('should give passing result if no SQL servers', function(done) {
const cache = createCache([], null);
autoFailoverGroupsEnabled.run(cache, {}, (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();
});
});

it('should give unknown result if unable to query for SQL servers', function(done) {
const cache = createCache(null);
autoFailoverGroupsEnabled.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 SQL servers:');
expect(results[0].region).to.equal('eastus');
done();
});
});

it('should give unknown result if unable to query for failover groups', function(done) {
const cache = createCache([servers[0]], null);
autoFailoverGroupsEnabled.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 auto-failover groups:');
expect(results[0].region).to.equal('eastus');
done();
});
});

it('should give passing result if auto-failover groups are configured', function(done) {
const cache = createCache([servers[0]], [failoverGroups[0]]);
autoFailoverGroupsEnabled.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(0);
expect(results[0].message).to.include('Auto-failover groups are configured for the SQL server');
expect(results[0].region).to.equal('eastus');
done();
});
});

it('should give failing result if no auto-failover groups found', function(done) {
const cache = createCache([servers[0]], []);
autoFailoverGroupsEnabled.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(2);
expect(results[0].message).to.include('Auto-failover groups are not configured for the SQL server');
expect(results[0].region).to.equal('eastus');
done();
});
});
});
});