Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions exports.js
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ module.exports = {
'neptuneDBMultiAz' : require(__dirname + '/plugins/aws/neptune/neptuneDBMultiAz.js'),
'neptuneDbDeletionProtection' : require(__dirname + '/plugins/aws/neptune/neptuneDbDeletionProtection.js'),
'neptuneDBIamAuth' : require(__dirname + '/plugins/aws/neptune/neptuneDBIamAuth.js'),
'neptuneAuditLoggingEnabled' : require(__dirname + '/plugins/aws/neptune/neptuneAuditLoggingEnabled.js'),

'monitoringMetrics' : require(__dirname + '/plugins/aws/cloudwatchlogs/monitoringMetrics.js'),

Expand Down
59 changes: 59 additions & 0 deletions plugins/aws/neptune/neptuneAuditLoggingEnabled.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
var async = require('async');
var helpers = require('../../../helpers/aws');

module.exports = {
title: 'Neptune Audit Logging Enabled',
category: 'Neptune',
domain: 'Databases',
severity: 'Medium',
description: 'Ensure that audit logging is enabled for Neptune clusters to capture database activities, including login attempts, queries, and modifications.',
more_info: 'Enable that audit logging to capture database activities, including login attempts, queries, and modifications. Send the logs to Amazon CloudWatch or a centralized log management system for analysis and monitoring.',
recommended_action: 'Modify Neptune cluster and enable audit logging feature.',
link: 'https://docs.aws.amazon.com/neptune/latest/userguide/enable-cloudwatch-logs.html',
apis: ['Neptune:describeDBClusters'],
realtime_triggers: ['neptune:CreateDBCluster','neptune:ModifyDBCluster','neptune:DeleteDBCluster'],

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

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

if (!describeDBClusters) return rcb();

if (describeDBClusters.err || !describeDBClusters.data) {
helpers.addResult(results, 3,
`Unable to list Neptune database clusters: ${helpers.addError(describeDBClusters)}`, region);
return rcb();
}

if (!describeDBClusters.data.length) {
helpers.addResult(results, 0,
'No Neptune database clusters found', region);
return rcb();
}

for (let cluster of describeDBClusters.data) {
if (!cluster.DBClusterArn || cluster.Engine !== 'neptune') continue;

let resource = cluster.DBClusterArn;

if (cluster.EnabledCloudwatchLogsExports &&
cluster.EnabledCloudwatchLogsExports.length &&
cluster.EnabledCloudwatchLogsExports.includes('audit')) {
helpers.addResult(results, 0, 'Neptune database cluster has audit logging enabled', region, resource);
} else {
helpers.addResult(results, 2, 'Neptune database cluster does not have audit logging enabled', region, resource);
}
}

rcb();
}, function(){
callback(null, results, source);
});
}
};

132 changes: 132 additions & 0 deletions plugins/aws/neptune/neptuneAuditLoggingEnabled.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
var expect = require('chai').expect;
var neptuneAuditLoggingEnabled = require('./neptuneAuditLoggingEnabled');

const describeDBClusters = [
{
AvailabilityZones: [],
BackupRetentionPeriod: 1,
DBClusterArn: 'arn:aws:rds:us-east-1:000011112222:cluster:neptune-cluster-1',
DBClusterIdentifier: 'neptune-cluster-1',
DBClusterParameterGroup: 'default.neptune1',
DBSubnetGroup: 'default-vpc-99de2fe4',
Status: 'available',
Engine: 'neptune',
EnabledCloudwatchLogsExports: [ "audit", "error"]
},
{
AvailabilityZones: [],
BackupRetentionPeriod: 10,
DBClusterArn: 'arn:aws:rds:us-east-1:000011112223:cluster:neptune-cluster-2',
DBClusterIdentifier: 'neptune-cluster-2',
DBClusterParameterGroup: 'default.neptune1',
DBSubnetGroup: 'default-vpc-99de2fe4',
Status: 'available',
Engine: 'neptune',
EnabledCloudwatchLogsExports: [ "error"]
},
{
AvailabilityZones: [],
BackupRetentionPeriod: 10,
DBClusterArn: 'arn:aws:rds:us-east-1:000011112224:cluster:neptune-cluster-3',
DBClusterIdentifier: 'neptune-cluster-3',
DBClusterParameterGroup: 'default.neptune1',
DBSubnetGroup: 'default-vpc-99de2fe4',
Status: 'available',
Engine: 'neptune',
EnabledCloudwatchLogsExports: []
},
{
AvailabilityZones: [],
BackupRetentionPeriod: 10,
DBClusterArn: 'arn:aws:rds:us-east-1:000011112225:cluster:neptune-cluster-4',
DBClusterIdentifier: 'neptune-cluster-4',
DBClusterParameterGroup: 'default.neptune1',
DBSubnetGroup: 'default-vpc-99de2fe4',
Status: 'available',
Engine: 'neptune'
}
];

const createCache = (clusters, clustersErr) => {
return {
neptune: {
describeDBClusters: {
'us-east-1': {
err: clustersErr,
data: clusters
},
},
}
};
};

describe('neptuneAuditLoggingEnabled', function () {
describe('run', function () {
it('should PASS if Neptune cluster has audit logging enabled', function (done) {
const cache = createCache([describeDBClusters[0]]);
neptuneAuditLoggingEnabled.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(0);
expect(results[0].message).to.include('Neptune database cluster has audit logging enabled');
expect(results[0].region).to.equal('us-east-1');
done();
});
});

it('should FAIL if Neptune cluster does not have audit logging enabled', function (done) {
const cache = createCache([describeDBClusters[1]]);
neptuneAuditLoggingEnabled.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(2);
expect(results[0].message).to.include('Neptune database cluster does not have audit logging enabled');
expect(results[0].region).to.equal('us-east-1');
done();
});
});

it('should FAIL if Neptune cluster has empty EnabledCloudwatchLogsExports', function (done) {
const cache = createCache([describeDBClusters[2]]);
neptuneAuditLoggingEnabled.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(2);
expect(results[0].message).to.include('Neptune database cluster does not have audit logging enabled');
expect(results[0].region).to.equal('us-east-1');
done();
});
});

it('should FAIL if Neptune cluster does not have EnabledCloudwatchLogsExports property', function (done) {
const cache = createCache([describeDBClusters[3]]);
neptuneAuditLoggingEnabled.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(2);
expect(results[0].message).to.include('Neptune database cluster does not have audit logging enabled');
expect(results[0].region).to.equal('us-east-1');
done();
});
});

it('should PASS if no Neptune clusters found', function (done) {
const cache = createCache([]);
neptuneAuditLoggingEnabled.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(0);
expect(results[0].message).to.include('No Neptune database clusters found');
expect(results[0].region).to.equal('us-east-1');
done();
});
});

it('should UNKNOWN if unable to list Neptune clusters', function (done) {
const cache = createCache(null, { message: "Unable to list Neptune clusters" });
neptuneAuditLoggingEnabled.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 list Neptune database clusters:');
expect(results[0].region).to.equal('us-east-1');
done();
});
});
});
});