Skip to content

Commit

Permalink
feat(deadline): Enable audit logging for DocDB (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
kozlove-aws authored Aug 10, 2020
1 parent 715be7c commit 00367f2
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 0 deletions.
27 changes: 27 additions & 0 deletions examples/kitchen-sink/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import {
DatabaseCluster,
ClusterParameterGroup,
CfnDBCluster,
} from '@aws-cdk/aws-docdb';
import {
AmazonLinuxImage,
Expand Down Expand Up @@ -121,6 +123,23 @@ export class KitchenSinkApp extends App {
filesystem: fileSystem,
});

/**
* This option is part of enabling audit logging for DocumentDB; the other required part is the enabling of the CloudWatch exports below.
*
* Audit logs are a security best-practice. They record connection, data definition language (DDL), user management,
* and authorization events within the database, and are useful for post-incident auditing. That is, they can help you
* figure out what an unauthorized user, who gained access to your database, has done with that access.
*
* For more information about audit logging in DocumentDB, see: https://docs.aws.amazon.com/documentdb/latest/developerguide/event-auditing.html
*/
const parameterGroup = new ClusterParameterGroup(infrastructureStack, 'ParameterGroup', {
description: 'DocDB cluster parameter group with enabled audit logs',
family: 'docdb3.6',
parameters: {
audit_logs: 'enabled',
},
});

/*
* DocumentDB database cluster for storing the render farm database.
*/
Expand All @@ -134,6 +153,7 @@ export class KitchenSinkApp extends App {
InstanceClass.R4,
InstanceSize.LARGE
),
parameterGroup,
vpc,
vpcSubnets: {
onePerAz: true,
Expand All @@ -151,6 +171,13 @@ export class KitchenSinkApp extends App {
removalPolicy: RemovalPolicy.DESTROY
});

/**
* This option enable export audit logs to Amazon CloudWatch.
* This is second options that required for enable audit log.
*/
const cfnDB = database.node.findChild('Resource') as CfnDBCluster;
cfnDB.enableCloudwatchLogsExports = ['audit'];

/**
* Bastion instance.
*
Expand Down
42 changes: 42 additions & 0 deletions packages/aws-rfdk/lib/deadline/lib/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
import {
CfnDBInstance,
DatabaseCluster,
CfnDBCluster,
ClusterParameterGroup,
} from '@aws-cdk/aws-docdb';
import {
AmazonLinuxGeneration,
Expand Down Expand Up @@ -296,6 +298,17 @@ export interface RepositoryProps {
*/
readonly removalPolicy?: RepositoryRemovalPolicies;

/**
* If this Repository is creating its own DocumentDB database, then this specifies if audit logging will be enabled
*
* Audit logs are a security best-practice. They record connection, data definition language (DDL), user management,
* and authorization events within the database, and are useful for post-incident auditing. That is, they can help you
* figure out what an unauthorized user, who gained access to your database, has done with that access.
*
* @default true
*/
readonly databaseAuditLogging?: boolean;

/**
* If this Repository is creating its own Amazon DocumentDB database, then this specifies the number of
* compute instances to be created.
Expand Down Expand Up @@ -444,7 +457,26 @@ export class Repository extends Construct implements IRepository {

if (props.database) {
this.databaseConnection = props.database;
if (props.databaseAuditLogging !== undefined){
this.node.addWarning(`The parameter databaseAuditLogging only has an effect when the Repository is creating its own database.
Please ensure that the Database provided is configured correctly.`);
}
} else {
const databaseAuditLogging = props.databaseAuditLogging ?? true;

/**
* This option is part of enabling audit logging for DocumentDB; the other required part is the enabling of the CloudWatch exports below.
*
* For more information about audit logging in DocumentDB, see: https://docs.aws.amazon.com/documentdb/latest/developerguide/event-auditing.html
*/
const parameterGroup = databaseAuditLogging ? new ClusterParameterGroup(this, 'ParameterGroup', {
description: 'DocDB cluster parameter group with enabled audit logs',
family: 'docdb3.6',
parameters: {
audit_logs: 'enabled',
},
}) : undefined;

const instances = props.documentDbInstanceCount ?? Repository.DEFAULT_NUM_DOCDB_INSTANCES;
const dbCluster = new DatabaseCluster(this, 'DocumentDatabase', {
masterUser: {username: 'DocDBUser'},
Expand All @@ -457,8 +489,18 @@ export class Repository extends Construct implements IRepository {
backup: {
retention: props.backupOptions?.databaseRetention ?? Repository.DEFAULT_DATABASE_RETENTION_PERIOD,
},
parameterGroup,
removalPolicy: props.removalPolicy?.database ?? RemovalPolicy.RETAIN,
});

if (databaseAuditLogging) {
/**
* This option enable export audit logs to Amazon CloudWatch.
* This is second options that required for enable audit log.
*/
const cfnDB = dbCluster.node.findChild('Resource') as CfnDBCluster;
cfnDB.enableCloudwatchLogsExports = ['audit'];
}
/* istanbul ignore next */
if (!dbCluster.secret) {
/* istanbul ignore next */
Expand Down
79 changes: 79 additions & 0 deletions packages/aws-rfdk/lib/deadline/test/repository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,11 +496,90 @@ test('repository creates deadlineDatabase if none provided', () => {

// THEN
expectCDK(stack).to(haveResource('AWS::DocDB::DBCluster'));
expectCDK(stack).to(haveResource('AWS::DocDB::DBInstance'));
expectCDK(stack).to(haveResourceLike('AWS::DocDB::DBCluster', {
EnableCloudwatchLogsExports: [ 'audit' ],
}, ResourcePart.Properties));
expectCDK(stack).to(haveResourceLike('AWS::DocDB::DBClusterParameterGroup', {
Parameters: {
audit_logs: 'enabled',
},
}, ResourcePart.Properties));
expectCDK(stack).to(haveResourceLike('AWS::DocDB::DBInstance', {
AutoMinorVersionUpgrade: true,
}));
});

test('disabling Audit logging does not enable Cloudwatch audit logs', () => {
const testEFS = new EfsFileSystem(stack, 'TestEfsFileSystem', {
vpc,
});
const testFS = new MountableEfs(stack, {
filesystem: testEFS,
});

// WHEN
new Repository(stack, 'repositoryInstaller', {
vpc,
fileSystem: testFS,
version: deadlineVersion,
databaseAuditLogging: false,
});

// THEN
expectCDK(stack).to(haveResource('AWS::DocDB::DBCluster'));
expectCDK(stack).notTo(haveResourceLike('AWS::DocDB::DBCluster', {
EnableCloudwatchLogsExports: [ 'audit' ],
}, ResourcePart.Properties));
expectCDK(stack).notTo(haveResourceLike('AWS::DocDB::DBClusterParameterGroup', {
Parameters: {
audit_logs: 'enabled',
},
}, ResourcePart.Properties));
});

test('repository warns if databaseAuditLogging defined and database is specified', () => {
// GIVEN
const fsDatabase = new DatabaseCluster(stack, 'TestDbCluster', {
masterUser: {
username: 'master',
},
instanceProps: {
instanceType: InstanceType.of(
InstanceClass.R4,
InstanceSize.LARGE,
),
vpc,
vpcSubnets: {
onePerAz: true,
subnetType: SubnetType.PRIVATE,
},
},
});

// WHEN
const repo = new Repository(stack, 'repositoryInstaller', {
vpc,
version: deadlineVersion,
removalPolicy: {
filesystem: RemovalPolicy.DESTROY,
},
database: DatabaseConnection.forDocDB({ database: fsDatabase, login: fsDatabase.secret! }),
databaseAuditLogging: true,
});

// THEN
expect(repo.node.metadata).toEqual(
expect.arrayContaining([
expect.objectContaining({
type: 'aws:cdk:warning',
data: `The parameter databaseAuditLogging only has an effect when the Repository is creating its own database.
Please ensure that the Database provided is configured correctly.`,
}),
]),
);
});

test('honors subnet specification', () => {
// GIVEN
const app = new App();
Expand Down

0 comments on commit 00367f2

Please sign in to comment.