Skip to content

Commit

Permalink
feat(HIPAA Security): DynamoDB check (#342)
Browse files Browse the repository at this point in the history
Closes #179 

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
dontirun authored Sep 14, 2021
1 parent a9a7022 commit 49c55a0
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 9 deletions.
3 changes: 1 addition & 2 deletions RULES.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,11 @@ There are currently no warnings for this rule pack.
| [HIPAA.Security-CloudWatchAlarmAction](https://docs.aws.amazon.com/config/latest/developerguide/cloudwatch-alarm-action-check.html) | The CloudWatch alarm does not have at least one alarm action, one INSUFFICIENT_DATA action, or one OK action enabled. | Amazon CloudWatch alarms alert when a metric breaches the threshold for a specified number of evaluation periods. The alarm performs one or more actions based on the value of the metric or expression relative to a threshold over a number of time periods. | 164.312(b) |
| [HIPAA.Security-CloudWatchLogGroupEncrypted](https://docs.aws.amazon.com/config/latest/developerguide/cloudwatch-log-group-encrypted.html) | The CloudWatch Log Group is not encrypted with an AWS KMS key. | To help protect sensitive data at rest, ensure encryption is enabled for your Amazon CloudWatch Log Groups. | 164.312(a)(2)(iv), 164.312(e)(2)(ii) |
| [HIPAA.Security-DMSReplicationNotPublic](https://docs.aws.amazon.com/config/latest/developerguide/dms-replication-not-public.html) | The DMS replication instance is public. | DMS replication instances can contain sensitive information and access control is required for such accounts. | 164.308(a)(3)(i), 164.308(a)(4)(ii)(A), 164.308(a)(4)(ii)(C), 164.312(a)(1), 164.312(e)(1) |
| [HIPAA.Security-DynamoDBPITREnabled](https://docs.aws.amazon.com/config/latest/developerguide/dynamodb-pitr-enabled.html) | The DynamoDB table does not have Point-in-time Recovery enabled. | The recovery maintains continuous backups of your table for the last 35 days. | 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.308(a)(7)(ii)(B) |
| [HIPAA.Security-EC2InstanceDetailedMonitoringEnabled](https://docs.aws.amazon.com/config/latest/developerguide/ec2-instance-detailed-monitoring-enabled.html) | The EC2 instance does not have detailed monitoring enabled. | Enable this rule to help improve Amazon Elastic Compute Cloud (Amazon EC2) instance monitoring on the Amazon EC2 console, which displays monitoring graphs with a 1-minute period for the instance. | 164.312(b) |
| [HIPAA.Security-EC2InstanceNoPublicIp](https://docs.aws.amazon.com/config/latest/developerguide/ec2-instance-no-public-ip.html) | The EC2 instance is associated with a public IP address. | Manage access to the AWS Cloud by ensuring Amazon Elastic Compute Cloud (Amazon EC2) instances cannot be publicly accessed. Amazon EC2 instances can contain sensitive information and access control is required for such accounts. | 164.308(a)(3)(i), 164.308(a)(4)(ii)(A), 164.308(a)(4)(ii)(C), 164.312(a)(1), 164.312(e)(1) |
| [HIPAA.Security-EC2InstancesInVPC](https://docs.aws.amazon.com/config/latest/developerguide/ec2-instances-in-vpc.html) | The EC2 instance is not within a VPC. | Deploy Amazon Elastic Compute Cloud (Amazon EC2) instances within an Amazon Virtual Private Cloud (Amazon VPC) to enable secure communication between an instance and other services within the amazon VPC, without requiring an internet gateway, NAT device, or VPN connection. All traffic remains securely within the AWS Cloud. Because of their logical isolation, domains that reside within anAmazon VPC have an extra layer of security when compared to domains that use public endpoints. Assign Amazon EC2 instances to an Amazon VPC to properly manage access. | 164.308(a)(3)(i), 164.308(a)(4)(ii)(A), 164.308(a)(4)(ii)(C), 164.312(a)(1), 164.312(e)(1) |



### Excluded Rules

Unimplemented rules from the AWS HIPAA Security Conformance Pack.
Expand Down
29 changes: 22 additions & 7 deletions src/HIPAA-Security/hipaa-security.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
hipaaSecurityCodeBuildProjectSourceRepoUrl,
} from './rules/codebuild';
import { hipaaSecurityDMSReplicationNotPublic } from './rules/dms';
import { hipaaSecurityDynamoDBPITREnabled } from './rules/dynamodb';
import {
hipaaSecurityEC2InstanceDetailedMonitoringEnabled,
hipaaSecurityEC2InstancesInVPC,
Expand All @@ -51,7 +52,7 @@ export class HIPAASecurityChecks extends NagPack {
this.checkCloudWatch(node, ignores);
// this.checkCodeBuild(node, ignores);
this.checkDMS(node, ignores);
// this.checkDynamoDB(node, ignores);
this.checkDynamoDB(node, ignores);
this.checkEC2(node, ignores);
// this.checkECS(node, ignores);
// this.checkEFS(node, ignores);
Expand Down Expand Up @@ -326,12 +327,26 @@ export class HIPAASecurityChecks extends NagPack {
}
}

// /**
// * Check DynamoDB Resources
// * @param node the IConstruct to evaluate
// * @param ignores list of ignores for the resource
// */
// private checkDynamoDB(node: CfnResource, ignores: any): void {}
/**
* Check DynamoDB Resources
* @param node the IConstruct to evaluate
* @param ignores list of ignores for the resource
*/
private checkDynamoDB(node: CfnResource, ignores: any) {
if (
!this.ignoreRule(ignores, 'HIPAA.Security-DynamoDBPITREnabled') &&
!hipaaSecurityDynamoDBPITREnabled(node)
) {
const ruleId = 'HIPAA.Security-DynamoDBPITREnabled';
const info =
'The DynamoDB table does not have Point-in-time Recovery enabled - (Control IDs: 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.308(a)(7)(ii)(B)).';
const explanation =
'The recovery maintains continuous backups of your table for the last 35 days.';
Annotations.of(node).addError(
this.createMessage(ruleId, info, explanation)
);
}
}

/**
* Check EC2 Resources
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
import { CfnTable } from '@aws-cdk/aws-dynamodb';
import { CfnResource, Stack } from '@aws-cdk/core';

/**
* DynamoDB tables have Point-in-time Recovery enabled - (Control IDs: 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.308(a)(7)(ii)(B))
* @param node the CfnResource to check
*/

export default function (node: CfnResource): boolean {
if (node instanceof CfnTable) {
if (node.pointInTimeRecoverySpecification == undefined) {
return false;
}
const pitr = Stack.of(node).resolve(node.pointInTimeRecoverySpecification);
const enabled = Stack.of(node).resolve(pitr.pointInTimeRecoveryEnabled);
if (!enabled) {
return false;
}
}
return true;
}
1 change: 1 addition & 0 deletions src/HIPAA-Security/rules/dynamodb/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
export { default as hipaaSecurityDynamoDBPITREnabled } from './hipaaSecurityDynamoDBPITREnabled';
41 changes: 41 additions & 0 deletions test/HIPAA-Security/HIPAA-Security-DynamoDB.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
import { SynthUtils } from '@aws-cdk/assert';
import { AttributeType, Table } from '@aws-cdk/aws-dynamodb';
import { Aspects, Stack } from '@aws-cdk/core';
import { HIPAASecurityChecks } from '../../src';

describe('Amazon DynamoDB', () => {
test('HIPAA.Security-DynamoDBPITREnabled: - DynamoDB tables have point in time recovery enabled - (Control IDs: 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.308(a)(7)(ii)(B)', () => {
const nonCompliant = new Stack();
Aspects.of(nonCompliant).add(new HIPAASecurityChecks());
new Table(nonCompliant, 'rTable', {
partitionKey: { name: 'foo', type: AttributeType.STRING },
});
const messages = SynthUtils.synthesize(nonCompliant).messages;
expect(messages).toContainEqual(
expect.objectContaining({
entry: expect.objectContaining({
data: expect.stringContaining('HIPAA.Security-DynamoDBPITREnabled:'),
}),
})
);

const compliant = new Stack();
Aspects.of(compliant).add(new HIPAASecurityChecks());
new Table(compliant, 'rTable', {
partitionKey: { name: 'foo', type: AttributeType.STRING },
pointInTimeRecovery: true,
});
const messages2 = SynthUtils.synthesize(compliant).messages;
expect(messages2).not.toContainEqual(
expect.objectContaining({
entry: expect.objectContaining({
data: expect.stringContaining('HIPAA.Security-DynamoDBPITREnabled:'),
}),
})
);
});
});

0 comments on commit 49c55a0

Please sign in to comment.