Skip to content

Commit deed353

Browse files
jogoldrix0rrr
authored andcommitted
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.
1 parent 7dd0e1a commit deed353

File tree

10 files changed

+1310
-8
lines changed

10 files changed

+1310
-8
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,72 @@
11
## The CDK Construct Library for AWS Config
22
This module is part of the [AWS Cloud Development Kit](https://github.com/awslabs/aws-cdk) project.
3+
4+
Supported:
5+
* Config rules
6+
7+
Not supported
8+
* Configuration recoder
9+
* Delivery channel
10+
* Aggregation
11+
12+
### Rules
13+
14+
#### AWS managed rules
15+
To set up a managed rule, define a `ManagedRule` and specify its identifier:
16+
17+
```ts
18+
new ManagedRule(this, 'AccessKeysRotated', {
19+
identifier: 'ACCESS_KEYS_ROTATED'
20+
});
21+
```
22+
23+
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).
24+
25+
26+
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).
27+
28+
#### Custom rules
29+
To set up a custom rule, define a `CustomRule` and specify the Lambda Function to run and the trigger types:
30+
31+
```ts
32+
new CustomRule(this, 'CustomRule', {
33+
lambdaFunction: myFn,
34+
configurationChanges: true,
35+
periodic: true
36+
});
37+
```
38+
39+
#### Restricting the scope
40+
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:
41+
42+
```ts
43+
const sshRule = new ManagedRule(this, 'SSH', {
44+
identifier: 'INCOMING_SSH_DISABLED'
45+
});
46+
47+
// Restrict to a specific security group
48+
rule.scopeToResource('AWS::EC2::SecurityGroup', 'sg-1234567890abcdefgh');
49+
50+
const customRule = new CustomRule(this, 'CustomRule', {
51+
lambdaFunction: myFn,
52+
configurationChanges: true
53+
});
54+
55+
// Restrict to a specific tag
56+
customRule.scopeToTag('Cost Center', 'MyApp');
57+
```
58+
59+
Only one type of scope restriction can be added to a rule (the last call to `scopeToXxx()` sets the scope).
60+
61+
#### Events
62+
To define Amazon CloudWatch event rules, use the `onComplianceChange()` or `onReEvaluationStatus()` methods:
63+
64+
```ts
65+
const rule = new CloudFormationStackDriftDetectionCheck(this, 'Drift');
66+
rule.onComplianceChange(topic);
67+
```
68+
69+
#### Example
70+
Creating custom and managed rules with scope restriction and events:
71+
72+
[example of setting up rules](test/integ.rule.lit.ts)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
export * from './rule';
2+
export * from './managed-rules';
3+
14
// AWS::Config CloudFormation Resources:
25
export * from './config.generated';
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import iam = require('@aws-cdk/aws-iam');
2+
import sns = require('@aws-cdk/aws-sns');
3+
import { Construct, Token } from '@aws-cdk/cdk';
4+
import { ManagedRule, RuleProps } from './rule';
5+
6+
/**
7+
* Construction properties for a AccessKeysRotated
8+
*/
9+
export interface AccessKeysRotatedProps extends RuleProps {
10+
/**
11+
* The maximum number of days within which the access keys must be rotated.
12+
*
13+
* @default 90 days
14+
*/
15+
readonly maxDays?: number;
16+
}
17+
18+
/**
19+
* Checks whether the active access keys are rotated within the number of days
20+
* specified in `maxDays`.
21+
*
22+
* @see https://docs.aws.amazon.com/config/latest/developerguide/access-keys-rotated.html
23+
*
24+
* @resource AWS::Config::ConfigRule
25+
*/
26+
export class AccessKeysRotated extends ManagedRule {
27+
constructor(scope: Construct, id: string, props: AccessKeysRotatedProps = {}) {
28+
super(scope, id, {
29+
...props,
30+
identifier: 'ACCESS_KEYS_ROTATED',
31+
inputParameters: {
32+
...props.maxDays
33+
? {
34+
maxAccessKeyAge: props.maxDays
35+
}
36+
: {}
37+
}
38+
});
39+
}
40+
}
41+
42+
/**
43+
* Construction properties for a CloudFormationStackDriftDetectionCheck
44+
*/
45+
export interface CloudFormationStackDriftDetectionCheckProps extends RuleProps {
46+
/**
47+
* Whether to check only the stack where this rule is deployed.
48+
*
49+
* @default false
50+
*/
51+
readonly ownStackOnly?: boolean;
52+
53+
/**
54+
* The IAM role to use for this rule. It must have permissions to detect drift
55+
* for AWS CloudFormation stacks. Ensure to attach `config.amazonaws.com` trusted
56+
* permissions and `ReadOnlyAccess` policy permissions. For specific policy permissions,
57+
* refer to https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-drift.html.
58+
*
59+
* @default a role will be created
60+
*/
61+
readonly role?: iam.IRole;
62+
}
63+
64+
/**
65+
* Checks whether your CloudFormation stacks' actual configuration differs, or
66+
* has drifted, from its expected configuration.
67+
*
68+
* @see https://docs.aws.amazon.com/config/latest/developerguide/cloudformation-stack-drift-detection-check.html
69+
*
70+
* @resource AWS::Config::ConfigRule
71+
*/
72+
export class CloudFormationStackDriftDetectionCheck extends ManagedRule {
73+
private readonly role: iam.IRole;
74+
75+
constructor(scope: Construct, id: string, props: CloudFormationStackDriftDetectionCheckProps = {}) {
76+
super(scope, id, {
77+
...props,
78+
identifier: 'CLOUDFORMATION_STACK_DRIFT_DETECTION_CHECK',
79+
inputParameters: {
80+
cloudformationRoleArn: new Token(() => this.role.roleArn)
81+
}
82+
});
83+
84+
this.scopeToResource('AWS::CloudFormation::Stack', props.ownStackOnly ? this.node.stack.stackId : undefined);
85+
86+
this.role = props.role || new iam.Role(this, 'Role', {
87+
assumedBy: new iam.ServicePrincipal('config.amazonaws.com'),
88+
managedPolicyArns: [
89+
new iam.AwsManagedPolicy('ReadOnlyAccess', this).policyArn,
90+
]
91+
});
92+
}
93+
}
94+
95+
/**
96+
* Construction properties for a CloudFormationStackNotificationCheck.
97+
*/
98+
export interface CloudFormationStackNotificationCheckProps extends RuleProps {
99+
/**
100+
* A list of allowed topics. At most 5 topics.
101+
*/
102+
readonly topics?: sns.ITopic[];
103+
}
104+
105+
/**
106+
* Checks whether your CloudFormation stacks are sending event notifications to
107+
* a SNS topic. Optionally checks whether specified SNS topics are used.
108+
*
109+
* @see https://docs.aws.amazon.com/config/latest/developerguide/cloudformation-stack-notification-check.html
110+
*
111+
* @resource AWS::Config::ConfigRule
112+
*/
113+
export class CloudFormationStackNotificationCheck extends ManagedRule {
114+
constructor(scope: Construct, id: string, props: CloudFormationStackNotificationCheckProps = {}) {
115+
if (props.topics && props.topics.length > 5) {
116+
throw new Error('At most 5 topics can be specified.');
117+
}
118+
119+
super(scope, id, {
120+
...props,
121+
identifier: 'CLOUDFORMATION_STACK_NOTIFICATION_CHECK',
122+
inputParameters: props.topics && props.topics.reduce(
123+
(params, topic, idx) => ({ ...params, [`snsTopic${idx + 1}`]: topic.topicArn }),
124+
{}
125+
)
126+
});
127+
128+
this.scopeToResource('AWS::CloudFormation::Stack');
129+
}
130+
}

0 commit comments

Comments
 (0)