Skip to content

Commit

Permalink
Added Alibaba RDS Log Duration plugin and test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
AkhtarAmir committed May 6, 2021
1 parent c0707f2 commit 9d49871
Show file tree
Hide file tree
Showing 6 changed files with 296 additions and 210 deletions.
12 changes: 9 additions & 3 deletions collectors/alibaba/collector.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ var async = require('async');
var helpers = require(__dirname + '/../../helpers/alibaba');

var apiVersion = '2015-05-01';
var regionEndpointMap = {
rds: ['cn-zhangjiakou', 'cn-huhehaote', 'cn-chengdu', 'ap-southeast-2', 'ap-southeast-3', 'ap-southeast-5',
'ap-northeast-1', 'ap-south-1', 'eu-central-1', 'eu-west-1', 'me-east-1']
};

var globalServices = [
'RAM'
Expand Down Expand Up @@ -130,7 +134,7 @@ var postcalls = [
}
},
RDS: {
DescribeDBInstanceSSL: {
DescribeParameters: {
reliesOnService: 'rds',
reliesOnCall: 'DescribeDBInstances',
filterKey: ['DBInstanceId'],
Expand Down Expand Up @@ -170,7 +174,8 @@ var collect = function(AlibabaConfig, settings, callback) {

var LocalAlibabaConfig = JSON.parse(JSON.stringify(AlibabaConfig));

var endpoint = `https://${serviceLower}.aliyuncs.com`;
var endpoint = (callObj.regionalEndpoint || (regionEndpointMap[serviceLower] && regionEndpointMap[serviceLower].includes(region))) ?
`https://${serviceLower}.${region}.aliyuncs.com` : `https://${serviceLower}.aliyuncs.com`;
LocalAlibabaConfig['endpoint'] = endpoint;
LocalAlibabaConfig['apiVersion'] = callObj.apiVersion || apiVersion;
var client = new alicloud(LocalAlibabaConfig);
Expand Down Expand Up @@ -269,7 +274,8 @@ var collect = function(AlibabaConfig, settings, callback) {

var LocalAlibabaConfig = JSON.parse(JSON.stringify(AlibabaConfig));

LocalAlibabaConfig['endpoint'] = `https://${serviceLower}.aliyuncs.com`;
LocalAlibabaConfig['endpoint'] = (callObj.regionalEndpoint || (regionEndpointMap[serviceLower] && regionEndpointMap[serviceLower].includes(region))) ?
`https://${serviceLower}.${region}.aliyuncs.com` : `https://${serviceLower}.aliyuncs.com`;
LocalAlibabaConfig['apiVersion'] = callObj.apiVersion || apiVersion;
var client = new alicloud(LocalAlibabaConfig);

Expand Down
2 changes: 1 addition & 1 deletion exports.js
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,6 @@ module.exports = {
'logSinksEnabled' : require(__dirname + '/plugins/google/logging/logSinksEnabled.js'),
},
alibaba: {
'rdsSslEncryptionEnabled' : require(__dirname + '/plugins/alibaba/rds/rdsSslEncryptionEnabled.js')
'rdsLogDuration' : require(__dirname + '/plugins/alibaba/rds/rdsLogDuration.js')
}
};
93 changes: 93 additions & 0 deletions plugins/alibaba/rds/rdsLogDuration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
var async = require('async');
var helpers = require('../../../helpers/alibaba');

module.exports = {
title: 'RDS Log Duration',
category: 'RDS',
description: 'Ensure that RDS DB instances have log_duration paraemeter enabled.',
more_info: 'Enabling log_duration parameter logs the duration of each completed SQL statement generating query and error logs ' +
'which can be used to identify, troubleshoot, and repair configuration errors and sub-optimal performance.',
link: 'https://partners-intl.aliyun.com/help/doc-detail/26179.htm',
recommended_action: 'Modify RDS DB instances to set value for log_duration parameter to ON',
apis: ['RDS:DescribeDBInstances', 'RDS:DescribeParameters', 'STS:GetCallerIdentity'],

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

var accountId = helpers.addSource(cache, source, ['sts', 'GetCallerIdentity', defaultRegion, 'data']);

async.each(regions.rds, function(region, rcb) {
var describeDBInstances = helpers.addSource(cache, source,
['rds', 'DescribeDBInstances', region]);

if (!describeDBInstances) {
return rcb();
}

if (describeDBInstances.err || !describeDBInstances.data) {
helpers.addResult(results, 3,
`Unable to query RDS DB instances: ${helpers.addError(describeDBInstances)}`,
region);
return rcb();
}

if (!describeDBInstances.data.length) {
helpers.addResult(results, 0, 'No RDS DB instances found', region);
return rcb();
}

async.each(describeDBInstances.data, function(instance, cb){
if (!instance.DBInstanceId) return cb();

var resource = helpers.createArn('rds', accountId, 'instance', instance.DBInstanceId, region);

if (instance.Engine && instance.Engine.toUpperCase() !== 'POSTGRESQL') {
helpers.addResult(results, 0,
`Log Duration is not supported for ${instance.Engine} engine type`,
region, resource);
return cb();
}

var describeParameters = helpers.addSource(cache, source,
['rds', 'DescribeParameters', region, instance.DBInstanceId]);

if (!describeParameters || describeParameters.err || !describeParameters.data) {
helpers.addResult(results, 3,
`Unable to query DB parameters: ${helpers.addError(describeParameters)}`,
region, resource);
return cb();
}

if (describeParameters.data.RunningParameters &&
describeParameters.data.RunningParameters.DBInstanceParameter &&
describeParameters.data.RunningParameters.DBInstanceParameter.length) {
let parameters = describeParameters.data.RunningParameters.DBInstanceParameter;
let found = parameters.find(parameter => parameter.ParameterName == 'log_duration' && parameter.ParameterValue.toLowerCase() == 'on');

if (found) {
helpers.addResult(results, 0,
'RDS DB instance has log_duration parameter enabled',
region, resource);
} else {
helpers.addResult(results, 2,
'RDS DB instance does not have log_duration parameter enabled',
region, resource);
}
} else {
helpers.addResult(results, 2,
'RDS DB instance does not have log_duration parameter enabled',
region, resource);
}

cb();
}, function(){
rcb();
});
}, function(){
callback(null, results, source);
});
}
};
193 changes: 193 additions & 0 deletions plugins/alibaba/rds/rdsLogDuration.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
var expect = require('chai').expect;
var rdsLogDuration = require('./rdsLogDuration.js');

const describeDBInstances = [
{
"EngineVersion": "13.0",
"DBInstanceStatus": "Running",
"ResourceGroupId": "rg-aekzsj44b4lt5fa",
"DBInstanceNetType": "Intranet",
"DBInstanceClass": "pg.n2.small.2c",
"CreateTime": "2021-05-04T17:13:45Z",
"VSwitchId": "vsw-rj94uhhrj5qz5008lwi1x",
"DBInstanceType": "Primary",
"PayType": "Postpaid",
"LockMode": "Unlock",
"MutriORsignle": false,
"InstanceNetworkType": "VPC",
"InsId": 1,
"VpcId": "vpc-rj9vu86hdve3qr173ew17",
"DBInstanceId": "pgm-2ev213kfnogf7mfi",
"ConnectionMode": "Standard",
"ReadOnlyDBInstanceIds": {
"ReadOnlyDBInstanceId": []
},
"VpcCloudInstanceId": "pgm-2ev213kfnogf7mfi",
"ExpireTime": "",
"LockReason": "",
"Engine": "PostgreSQL"
}
];

const describeParameters = [
{
"RunningParameters": {
"DBInstanceParameter": [
{
"ParameterValue": "on",
"ParameterName": "log_duration",
"ParameterDescription": "Logs the duration of each completed SQL statement."
},
{
"ParameterValue": "off",
"ParameterName": "jit",
"ParameterDescription": "allow JIT compilation"
},
{
"ParameterValue": "0",
"ParameterName": "lock_timeout",
"ParameterDescription": "Sets the maximum allowed duration of any wait for a lock. A value of 0 turns off the timeout."
},
{
"ParameterValue": "off",
"ParameterName": "log_connections",
"ParameterDescription": "Logs each successful connection."
},
{
"ParameterValue": "off",
"ParameterName": "log_disconnections",
"ParameterDescription": "Logs end of a session, including duration."
},
{
"ParameterValue": "1000",
"ParameterName": "log_min_duration_statement",
"ParameterDescription": "SQL with execution time exceeding this value will be logged. Note that a too small value may cause performance degradation and increase the amount of logs."
},
{
"ParameterValue": "ddl",
"ParameterName": "log_statement",
"ParameterDescription": "Sets the type of statements logged. Setting it to all or mod will cause performance degradation and increase the amount of logs."
},
{
"ParameterValue": "-1",
"ParameterName": "old_snapshot_threshold",
"ParameterDescription": "Time before a snapshot is too old to read pages changed after the snapshot was taken."
},
{
"ParameterValue": "disable",
"ParameterName": "sql_firewall.firewall",
"ParameterDescription": "The parameter is to detemine running mode of sql_firewall extension."
},
{
"ParameterValue": "off",
"ParameterName": "ssl",
"ParameterDescription": "Enables SSL connections."
},
{
"ParameterValue": "TLSv1",
"ParameterName": "ssl_min_protocol_version",
"ParameterDescription": "Sets the minimum SSL/TLS protocol version to use"
},
{
"ParameterValue": "0",
"ParameterName": "statement_timeout",
"ParameterDescription": "Sets the maximum allowed duration of any statement. A value of 0 turns off the timeout."
},
]
},
"EngineVersion": "13.0",
"Engine": "PostgreSQL"
},
{
"RunningParameters": {
"DBInstanceParameter": [
{
"ParameterValue": "off",
"ParameterName": "log_duration",
"ParameterDescription": "Logs the duration of each completed SQL statement."
},
]
}
}
];

const createCache = (dbInstances, describeParameters, dbInstancesErr, describeParametersErr) => {
let instanceId = (dbInstances && dbInstances.length) ? dbInstances[0].DBInstanceId : null;
return {
rds: {
DescribeDBInstances: {
'cn-hangzhou': {
data: dbInstances,
err: dbInstancesErr
},
},
DescribeParameters: {
'cn-hangzhou': {
[instanceId]: {
data: describeParameters,
err: describeParametersErr
}
}
}
},
};
};

describe('rdsLogDuration', function () {
describe('run', function () {
it('should FAIL if RDS DB instance does not have log_duration parameter enabled', function (done) {
const cache = createCache(describeDBInstances, describeParameters[1]);
rdsLogDuration.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(2);
expect(results[0].message).to.include('RDS DB instance does not have log_duration parameter enabled');
expect(results[0].region).to.equal('cn-hangzhou');
done();
});
});

it('should PASS if RDS DB instance has log_duration parameter enabled', function (done) {
const cache = createCache(describeDBInstances, describeParameters[0]);
rdsLogDuration.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(0);
expect(results[0].message).to.include('RDS DB instance has log_duration parameter enabled');
expect(results[0].region).to.equal('cn-hangzhou');
done();
});
});

it('should PASS if no RDS DB instances found', function (done) {
const cache = createCache([]);
rdsLogDuration.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(0);
expect(results[0].message).to.include('No RDS DB instances found');
expect(results[0].region).to.equal('cn-hangzhou');
done();
});
});

it('should UNKNOWN if unable to query RDS DB instances', function (done) {
const cache = createCache([], null, { err: 'Unable to query RDS DB instances' });
rdsLogDuration.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 RDS DB instances');
expect(results[0].region).to.equal('cn-hangzhou');
done();
});
});

it('should UNKNOWN if unable to query DB parameters', function (done) {
const cache = createCache([describeDBInstances[0]], {}, null, { err: 'Unable to query DB parameters' });
rdsLogDuration.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 DB parameters');
expect(results[0].region).to.equal('cn-hangzhou');
done();
});
});
})
})
Loading

0 comments on commit 9d49871

Please sign in to comment.