Skip to content

Commit

Permalink
feat: LexBotAliasEncryptedConversationLogs rule (AwsSolutions-LEX4) (c…
Browse files Browse the repository at this point in the history
…dklabs#929)

* feat: LexBotAliasEncryptedConversationLogs rule

* chore: upgrade deps

* chore: self mutation

Signed-off-by: github-actions <github-actions@github.com>

* docs: removing duplicate sentence in RULES.md

Co-authored-by: github-actions <github-actions@github.com>
  • Loading branch information
dontirun and github-actions authored Jun 29, 2022
1 parent 348c163 commit a92da8c
Show file tree
Hide file tree
Showing 11 changed files with 409 additions and 46 deletions.
14 changes: 6 additions & 8 deletions .projen/deps.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 2 additions & 7 deletions .projenrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ const { awscdk } = require('projen');
const project = new awscdk.AwsCdkConstructLibrary({
author: 'Arun Donti',
authorAddress: 'donti@amazon.com',
cdkVersion: '2.11.0',
cdkVersion: '2.18.0',
defaultReleaseBranch: 'main',
majorVersion: 2,
npmDistTag: 'latest',
name: 'cdk-nag',
description:
'Check CDK v2 applications for best practices using a combination on available rule packs.',
repositoryUrl: 'https://github.com/cdklabs/cdk-nag.git',
devDeps: ['@aws-cdk/assert@^2.11'],
devDeps: ['@aws-cdk/assert@^2.18'],
publishToPypi: {
distName: 'cdk-nag',
module: 'cdk_nag',
Expand Down Expand Up @@ -51,11 +51,6 @@ const project = new awscdk.AwsCdkConstructLibrary({
release: true,
gitignore: ['.vscode'],
});
project.package.addField('resolutions', {
'ansi-regex': '^5.0.1',
'json-schema': '^0.4.0',
'@types/prettier': '2.6.0',
});
project.package.addField('prettier', {
singleQuote: true,
semi: true,
Expand Down
1 change: 1 addition & 0 deletions RULES.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ The [AWS Solutions Library](https://aws.amazon.com/solutions/) offers a collecti
| AwsSolutions-KDS1 | The Kinesis Data Stream does not has server-side encryption enabled. | Data is encrypted before it's written to the Kinesis stream storage layer, and decrypted after it’s retrieved from storage. This allows the system to meet strict regulatory requirements and enhance the security of system data. |
| AwsSolutions-KMS5 | The KMS Symmetric key does not have automatic key rotation enabled. | KMS key rotation allow a system to set an yearly rotation schedule for a KMS key so when a AWS KMS key is required to encrypt new data, the KMS service can automatically use the latest version of the HSA backing key to perform the encryption. |
| AwsSolutions-L1 | The non-container Lambda function is not configured to use the latest runtime version. | Use the latest available runtime for the targeted language to avoid technical debt. Runtimes specific to a language or framework version are deprecated when the version reaches end of life. This rule only applies to non-container Lambda functions. |
| AwsSolutions-LEX4 | Lex conversation logs are enabled and not encrypted with a KMS key. | You can use encryption to help protect the contents of your conversation logs. For text and audio logs, you can use AWS KMS customer managed CMKs to encrypt data in your CloudWatch Logs log group and S3 bucket. |
| AwsSolutions-MS1 | The MediaStore container does not have container access logging enabled. | The container should have access logging enabled to provide detailed records for the requests that are made to the container. |
| AwsSolutions-MS3 | The MediaStore container does not require requests to use SSL. | You can use HTTPS (TLS) to help prevent potential attackers from eavesdropping on or manipulating network traffic using person-in-the-middle or similar attacks. You should allow only encrypted connections over HTTPS (TLS) using the aws:SecureTransport condition on MediaStore container policies. |
| AwsSolutions-MSK2 | The MSK cluster uses plaintext communication between clients and brokers. | TLS only communication secures data-in-transit by encrypting the connection between the clients and brokers. |
Expand Down
16 changes: 7 additions & 9 deletions package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/packs/aws-solutions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ import {
} from '../rules/kinesis';
import { KMSBackingKeyRotationEnabled } from '../rules/kms';
import { LambdaLatestVersion } from '../rules/lambda';
import { LexBotAliasEncryptedConversationLogs } from '../rules/lex';
import {
MediaStoreCloudWatchMetricPolicy,
MediaStoreContainerAccessLogging,
Expand Down Expand Up @@ -961,6 +962,15 @@ export class AwsSolutionsChecks extends NagPack {
* @param ignores list of ignores for the resource
*/
private checkMachineLearning(node: CfnResource): void {
this.applyRule({
ruleSuffixOverride: 'LEX4',
info: 'Lex conversation logs are enabled and not encrypted with a KMS key.',
explanation:
'You can use encryption to help protect the contents of your conversation logs. For text and audio logs, you can use AWS KMS customer managed CMKs to encrypt data in your CloudWatch Logs log group and S3 bucket.',
level: NagMessageLevel.ERROR,
rule: LexBotAliasEncryptedConversationLogs,
node: node,
});
this.applyRule({
ruleSuffixOverride: 'SM1',
info: 'The SageMaker notebook instance is not provisioned inside a VPC.',
Expand Down
1 change: 1 addition & 0 deletions src/rules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export * as iam from './iam';
export * as kinesis from './kinesis';
export * as kms from './kms';
export * as lambda from './lambda';
export * as lex from './lex';
export * as mediastore from './mediastore';
export * as msk from './msk';
export * as neptune from './neptune';
Expand Down
91 changes: 91 additions & 0 deletions src/rules/lex/LexBotAliasEncryptedConversationLogs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
import { parse } from 'path';
import { CfnResource, Stack } from 'aws-cdk-lib';
import { CfnBot, CfnBotAlias } from 'aws-cdk-lib/aws-lex';
import { CfnLogGroup } from 'aws-cdk-lib/aws-logs';
import { NagRuleCompliance, NagRules } from '../../nag-rules';

/**
* Lex Bot conversation logs are encrypted with KMS keys
* @param node the CfnResource to check
*/
export default Object.defineProperty(
(node: CfnResource): NagRuleCompliance => {
if (node instanceof CfnBotAlias || node instanceof CfnBot) {
const settingLocation =
node instanceof CfnBotAlias
? node
: Stack.of(node).resolve(node.testBotAliasSettings);
const conversationLogSettings = Stack.of(node).resolve(
settingLocation?.conversationLogSettings
);
if (conversationLogSettings !== undefined) {
const audioLogSettings =
Stack.of(node).resolve(conversationLogSettings.audioLogSettings) ??
[];
for (const log of audioLogSettings) {
const resolvedLog = Stack.of(node).resolve(log);
if (Stack.of(node).resolve(resolvedLog.enabled) === true) {
const resolvedDestination = Stack.of(node).resolve(
resolvedLog.destination
);
const s3Bucket = Stack.of(node).resolve(
resolvedDestination.s3Bucket
);
const kmsKeyArn = Stack.of(node).resolve(s3Bucket.kmsKeyArn);
if (kmsKeyArn === undefined) {
return NagRuleCompliance.NON_COMPLIANT;
}
}
}
const textLogSettings =
Stack.of(node).resolve(conversationLogSettings.textLogSettings) ?? [];
for (const log of textLogSettings) {
const resolvedLog = Stack.of(node).resolve(log);
if (Stack.of(node).resolve(resolvedLog.enabled) === true) {
const resolvedDestination = Stack.of(node).resolve(
resolvedLog.destination
);
const cloudwatch = Stack.of(node).resolve(
resolvedDestination.cloudWatch
);
const logGroupLogicalId = NagRules.resolveResourceFromInstrinsic(
node,
cloudwatch.cloudWatchLogGroupArn
);
let found = false;
for (const child of Stack.of(node).node.findAll()) {
if (child instanceof CfnLogGroup) {
if (
logGroupLogicalId ===
NagRules.resolveResourceFromInstrinsic(child, child.logicalId)
) {
found = true;
if (child.kmsKeyId === undefined) {
return NagRuleCompliance.NON_COMPLIANT;
}
break;
}
}
}
if (!found) {
throw Error(
`Unable to find the CloudWatch Log group "${JSON.stringify(
logGroupLogicalId
)}" used in one of Text Log Destinations in the CDK Application. Therefore the rule could not be validated.`
);
}
}
}
}
return NagRuleCompliance.COMPLIANT;
} else {
return NagRuleCompliance.NOT_APPLICABLE;
}
},
'name',
{ value: parse(__filename).name }
);
5 changes: 5 additions & 0 deletions src/rules/lex/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
export { default as LexBotAliasEncryptedConversationLogs } from './LexBotAliasEncryptedConversationLogs';
1 change: 1 addition & 0 deletions test/Packs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ describe('Check NagPack Details', () => {
'AwsSolutions-KDS1',
'AwsSolutions-KMS5',
'AwsSolutions-L1',
'AwsSolutions-LEX4',
'AwsSolutions-MS1',
'AwsSolutions-MS3',
'AwsSolutions-MSK2',
Expand Down
Loading

0 comments on commit a92da8c

Please sign in to comment.