-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(config): AWS Config, Managed and Custom rules (#2326)
Specific classes are exposed for an AWS managed rule (`ManagedRule`) and a custom rule (`CustomRule`) with support for compliance and re-evaluation events. Higher level constructs for configured AWS managed rules are also exposed (starting with Access Keys Rotated and CloudFormation rules). This defines a pattern for future configured managed rules.
- Loading branch information
Showing
10 changed files
with
1,310 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,72 @@ | ||
## The CDK Construct Library for AWS Config | ||
This module is part of the [AWS Cloud Development Kit](https://github.com/awslabs/aws-cdk) project. | ||
|
||
Supported: | ||
* Config rules | ||
|
||
Not supported | ||
* Configuration recoder | ||
* Delivery channel | ||
* Aggregation | ||
|
||
### Rules | ||
|
||
#### AWS managed rules | ||
To set up a managed rule, define a `ManagedRule` and specify its identifier: | ||
|
||
```ts | ||
new ManagedRule(this, 'AccessKeysRotated', { | ||
identifier: 'ACCESS_KEYS_ROTATED' | ||
}); | ||
``` | ||
|
||
Available identifiers and parameters are listed in the [List of AWS Config Managed Rules](https://docs.aws.amazon.com/config/latest/developerguide/managed-rules-by-aws-config.html). | ||
|
||
|
||
Higher level constructs for managed rules are available, see [Managed Rules](https://github.com/awslabs/aws-cdk/blob/master/packages/%40aws-cdk/aws-config/lib/managed-rules.ts). Prefer to use those constructs when available (PRs welcome to add more of those). | ||
|
||
#### Custom rules | ||
To set up a custom rule, define a `CustomRule` and specify the Lambda Function to run and the trigger types: | ||
|
||
```ts | ||
new CustomRule(this, 'CustomRule', { | ||
lambdaFunction: myFn, | ||
configurationChanges: true, | ||
periodic: true | ||
}); | ||
``` | ||
|
||
#### Restricting the scope | ||
By default rules are triggered by changes to all [resources](https://docs.aws.amazon.com/config/latest/developerguide/resource-config-reference.html#supported-resources). Use the `scopeToResource()`, `scopeToResources()` or `scopeToTag()` methods to restrict the scope of both managed and custom rules: | ||
|
||
```ts | ||
const sshRule = new ManagedRule(this, 'SSH', { | ||
identifier: 'INCOMING_SSH_DISABLED' | ||
}); | ||
|
||
// Restrict to a specific security group | ||
rule.scopeToResource('AWS::EC2::SecurityGroup', 'sg-1234567890abcdefgh'); | ||
|
||
const customRule = new CustomRule(this, 'CustomRule', { | ||
lambdaFunction: myFn, | ||
configurationChanges: true | ||
}); | ||
|
||
// Restrict to a specific tag | ||
customRule.scopeToTag('Cost Center', 'MyApp'); | ||
``` | ||
|
||
Only one type of scope restriction can be added to a rule (the last call to `scopeToXxx()` sets the scope). | ||
|
||
#### Events | ||
To define Amazon CloudWatch event rules, use the `onComplianceChange()` or `onReEvaluationStatus()` methods: | ||
|
||
```ts | ||
const rule = new CloudFormationStackDriftDetectionCheck(this, 'Drift'); | ||
rule.onComplianceChange(topic); | ||
``` | ||
|
||
#### Example | ||
Creating custom and managed rules with scope restriction and events: | ||
|
||
[example of setting up rules](test/integ.rule.lit.ts) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
export * from './rule'; | ||
export * from './managed-rules'; | ||
|
||
// AWS::Config CloudFormation Resources: | ||
export * from './config.generated'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
import iam = require('@aws-cdk/aws-iam'); | ||
import sns = require('@aws-cdk/aws-sns'); | ||
import { Construct, Token } from '@aws-cdk/cdk'; | ||
import { ManagedRule, RuleProps } from './rule'; | ||
|
||
/** | ||
* Construction properties for a AccessKeysRotated | ||
*/ | ||
export interface AccessKeysRotatedProps extends RuleProps { | ||
/** | ||
* The maximum number of days within which the access keys must be rotated. | ||
* | ||
* @default 90 days | ||
*/ | ||
readonly maxDays?: number; | ||
} | ||
|
||
/** | ||
* Checks whether the active access keys are rotated within the number of days | ||
* specified in `maxDays`. | ||
* | ||
* @see https://docs.aws.amazon.com/config/latest/developerguide/access-keys-rotated.html | ||
* | ||
* @resource AWS::Config::ConfigRule | ||
*/ | ||
export class AccessKeysRotated extends ManagedRule { | ||
constructor(scope: Construct, id: string, props: AccessKeysRotatedProps = {}) { | ||
super(scope, id, { | ||
...props, | ||
identifier: 'ACCESS_KEYS_ROTATED', | ||
inputParameters: { | ||
...props.maxDays | ||
? { | ||
maxAccessKeyAge: props.maxDays | ||
} | ||
: {} | ||
} | ||
}); | ||
} | ||
} | ||
|
||
/** | ||
* Construction properties for a CloudFormationStackDriftDetectionCheck | ||
*/ | ||
export interface CloudFormationStackDriftDetectionCheckProps extends RuleProps { | ||
/** | ||
* Whether to check only the stack where this rule is deployed. | ||
* | ||
* @default false | ||
*/ | ||
readonly ownStackOnly?: boolean; | ||
|
||
/** | ||
* The IAM role to use for this rule. It must have permissions to detect drift | ||
* for AWS CloudFormation stacks. Ensure to attach `config.amazonaws.com` trusted | ||
* permissions and `ReadOnlyAccess` policy permissions. For specific policy permissions, | ||
* refer to https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-drift.html. | ||
* | ||
* @default a role will be created | ||
*/ | ||
readonly role?: iam.IRole; | ||
} | ||
|
||
/** | ||
* Checks whether your CloudFormation stacks' actual configuration differs, or | ||
* has drifted, from its expected configuration. | ||
* | ||
* @see https://docs.aws.amazon.com/config/latest/developerguide/cloudformation-stack-drift-detection-check.html | ||
* | ||
* @resource AWS::Config::ConfigRule | ||
*/ | ||
export class CloudFormationStackDriftDetectionCheck extends ManagedRule { | ||
private readonly role: iam.IRole; | ||
|
||
constructor(scope: Construct, id: string, props: CloudFormationStackDriftDetectionCheckProps = {}) { | ||
super(scope, id, { | ||
...props, | ||
identifier: 'CLOUDFORMATION_STACK_DRIFT_DETECTION_CHECK', | ||
inputParameters: { | ||
cloudformationRoleArn: new Token(() => this.role.roleArn) | ||
} | ||
}); | ||
|
||
this.scopeToResource('AWS::CloudFormation::Stack', props.ownStackOnly ? this.node.stack.stackId : undefined); | ||
|
||
this.role = props.role || new iam.Role(this, 'Role', { | ||
assumedBy: new iam.ServicePrincipal('config.amazonaws.com'), | ||
managedPolicyArns: [ | ||
new iam.AwsManagedPolicy('ReadOnlyAccess', this).policyArn, | ||
] | ||
}); | ||
} | ||
} | ||
|
||
/** | ||
* Construction properties for a CloudFormationStackNotificationCheck. | ||
*/ | ||
export interface CloudFormationStackNotificationCheckProps extends RuleProps { | ||
/** | ||
* A list of allowed topics. At most 5 topics. | ||
*/ | ||
readonly topics?: sns.ITopic[]; | ||
} | ||
|
||
/** | ||
* Checks whether your CloudFormation stacks are sending event notifications to | ||
* a SNS topic. Optionally checks whether specified SNS topics are used. | ||
* | ||
* @see https://docs.aws.amazon.com/config/latest/developerguide/cloudformation-stack-notification-check.html | ||
* | ||
* @resource AWS::Config::ConfigRule | ||
*/ | ||
export class CloudFormationStackNotificationCheck extends ManagedRule { | ||
constructor(scope: Construct, id: string, props: CloudFormationStackNotificationCheckProps = {}) { | ||
if (props.topics && props.topics.length > 5) { | ||
throw new Error('At most 5 topics can be specified.'); | ||
} | ||
|
||
super(scope, id, { | ||
...props, | ||
identifier: 'CLOUDFORMATION_STACK_NOTIFICATION_CHECK', | ||
inputParameters: props.topics && props.topics.reduce( | ||
(params, topic, idx) => ({ ...params, [`snsTopic${idx + 1}`]: topic.topicArn }), | ||
{} | ||
) | ||
}); | ||
|
||
this.scopeToResource('AWS::CloudFormation::Stack'); | ||
} | ||
} |
Oops, something went wrong.