Skip to content

Commit 6348717

Browse files
feat(iot): configure IoT Logging (#31352)
### Issue # (if applicable) Closes #31357. ### Reason for this change Cloudformation supports for configuring [AWS IoT logging](https://docs.aws.amazon.com/iot/latest/developerguide/configure-logging.html) but AWS CDK doesn't support it. We have to create [logging role](https://docs.aws.amazon.com/iot/latest/developerguide/configure-logging.html#configure-logging-role-and-policy) to enable IoT logging. It is not particularly difficult, but it is user-friendly if IAM roles are implicitly generated by CDK simultaneously. ### Description of changes - define `ILogging` interface - define `LoggingProps` - define `Logging` class - create `CfnLogging` - generate logging role ### Description of how you validated changes Added both unit and integ tests. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent ed91671 commit 6348717

14 files changed

+822
-1
lines changed

packages/@aws-cdk/aws-iot-alpha/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,17 @@ new iot.TopicRule(this, 'TopicRule', {
7777
```
7878

7979
See also [@aws-cdk/aws-iot-actions-alpha](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-iot-actions-alpha-readme.html) for other actions.
80+
81+
## Logging
82+
83+
AWS IoT provides a [logging feature](https://docs.aws.amazon.com/iot/latest/developerguide/configure-logging.html) that allows you to monitor and log AWS IoT activity.
84+
85+
You can enable IoT logging with the following code:
86+
87+
```ts
88+
new iot.Logging(this, 'Logging', {
89+
logLevel: iot.LogLevel.INFO,
90+
});
91+
```
92+
93+
**Note**: All logs are forwarded to the `AWSIotLogsV2` log group in CloudWatch.
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"exclude": [
3-
"no-unused-type:@aws-cdk/aws-iot-alpha.ActionConfig"
3+
"no-unused-type:@aws-cdk/aws-iot-alpha.ActionConfig",
4+
"props-physical-name:@aws-cdk/aws-iot-alpha.LoggingProps"
45
]
56
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * from './action';
22
export * from './iot-sql';
3+
export * from './logging';
34
export * from './topic-rule';
45

56
// AWS::IoT CloudFormation Resources:
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import { Resource, Stack, IResource } from 'aws-cdk-lib/core';
2+
import { Construct } from 'constructs';
3+
import * as iot from 'aws-cdk-lib/aws-iot';
4+
import * as iam from 'aws-cdk-lib/aws-iam';
5+
6+
/**
7+
* Represents AWS IoT Logging
8+
*/
9+
export interface ILogging extends IResource {
10+
/**
11+
* The log ID
12+
* @attribute
13+
*/
14+
readonly logId: string;
15+
}
16+
17+
/**
18+
* The log level for the AWS IoT Logging
19+
*/
20+
export enum LogLevel {
21+
/**
22+
* Any error that causes an operation to fail
23+
*
24+
* Logs include ERROR information only
25+
*/
26+
ERROR = 'ERROR',
27+
28+
/**
29+
* Anything that can potentially cause inconsistencies in the system, but might not cause the operation to fail
30+
*
31+
* Logs include ERROR and WARN information
32+
*/
33+
WARN = 'WARN',
34+
35+
/**
36+
* High-level information about the flow of things
37+
*
38+
* Logs include INFO, ERROR, and WARN information
39+
*/
40+
INFO = 'INFO',
41+
42+
/**
43+
* Information that might be helpful when debugging a problem
44+
*
45+
* Logs include DEBUG, INFO, ERROR, and WARN information
46+
*/
47+
DEBUG = 'DEBUG',
48+
49+
/**
50+
* All logging is disabled
51+
*/
52+
DISABLED = 'DISABLED',
53+
}
54+
55+
/**
56+
* Properties for defining AWS IoT Logging
57+
*/
58+
export interface LoggingProps {
59+
/**
60+
* The log level for the AWS IoT Logging
61+
*
62+
* @default LogLevel.ERROR
63+
*/
64+
readonly logLevel?: LogLevel;
65+
}
66+
67+
/**
68+
* Defines AWS IoT Logging
69+
*/
70+
export class Logging extends Resource implements ILogging {
71+
/**
72+
* Import an existing AWS IoT Logging
73+
*
74+
* @param scope The parent creating construct (usually `this`)
75+
* @param id The construct's name
76+
* @param logId AWS IoT Logging ID
77+
*/
78+
public static fromLogId(scope: Construct, id: string, logId: string): ILogging {
79+
class Import extends Resource implements ILogging {
80+
public readonly logId = logId;
81+
}
82+
return new Import(scope, id);
83+
}
84+
85+
/**
86+
* The logging ID
87+
* @attribute
88+
*/
89+
public readonly logId: string;
90+
91+
constructor(scope: Construct, id: string, props?: LoggingProps) {
92+
super(scope, id);
93+
94+
const accountId = Stack.of(this).account;
95+
96+
// Create a role for logging
97+
// https://docs.aws.amazon.com/iot/latest/developerguide/configure-logging.html#configure-logging-role-and-policy
98+
const role = new iam.Role(this, 'Role', {
99+
assumedBy: new iam.ServicePrincipal('iot.amazonaws.com'),
100+
inlinePolicies: {
101+
LoggingPolicy: new iam.PolicyDocument({
102+
statements: [
103+
new iam.PolicyStatement({
104+
actions: [
105+
'logs:CreateLogGroup',
106+
'logs:CreateLogStream',
107+
'logs:PutLogEvents',
108+
'logs:PutMetricFilter',
109+
'logs:PutRetentionPolicy',
110+
'iot:GetLoggingOptions',
111+
'iot:SetLoggingOptions',
112+
'iot:SetV2LoggingOptions',
113+
'iot:GetV2LoggingOptions',
114+
'iot:SetV2LoggingLevel',
115+
'iot:ListV2LoggingLevels',
116+
'iot:DeleteV2LoggingLevel',
117+
],
118+
resources: [
119+
Stack.of(this).formatArn({
120+
service: 'logs',
121+
resource: 'log-group',
122+
sep: ':',
123+
resourceName: 'AWSIotLogsV2:*',
124+
}),
125+
],
126+
}),
127+
],
128+
}),
129+
},
130+
});
131+
132+
const resource = new iot.CfnLogging(this, 'Resource', {
133+
accountId,
134+
defaultLogLevel: props?.logLevel ?? LogLevel.ERROR,
135+
roleArn: role.roleArn,
136+
});
137+
138+
this.logId = resource.ref;
139+
}
140+
}

packages/@aws-cdk/aws-iot-alpha/test/integ.logging.js.snapshot/IotLoggingTestDefaultTestDeployAssertB1DE3CEF.assets.json

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@aws-cdk/aws-iot-alpha/test/integ.logging.js.snapshot/IotLoggingTestDefaultTestDeployAssertB1DE3CEF.template.json

Lines changed: 36 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@aws-cdk/aws-iot-alpha/test/integ.logging.js.snapshot/IotLoggingTestStack.assets.json

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
{
2+
"Resources": {
3+
"LoggingRoleF8CB8FA1": {
4+
"Type": "AWS::IAM::Role",
5+
"Properties": {
6+
"AssumeRolePolicyDocument": {
7+
"Statement": [
8+
{
9+
"Action": "sts:AssumeRole",
10+
"Effect": "Allow",
11+
"Principal": {
12+
"Service": "iot.amazonaws.com"
13+
}
14+
}
15+
],
16+
"Version": "2012-10-17"
17+
},
18+
"Policies": [
19+
{
20+
"PolicyDocument": {
21+
"Statement": [
22+
{
23+
"Action": [
24+
"iot:DeleteV2LoggingLevel",
25+
"iot:GetLoggingOptions",
26+
"iot:GetV2LoggingOptions",
27+
"iot:ListV2LoggingLevels",
28+
"iot:SetLoggingOptions",
29+
"iot:SetV2LoggingLevel",
30+
"iot:SetV2LoggingOptions",
31+
"logs:CreateLogGroup",
32+
"logs:CreateLogStream",
33+
"logs:PutLogEvents",
34+
"logs:PutMetricFilter",
35+
"logs:PutRetentionPolicy"
36+
],
37+
"Effect": "Allow",
38+
"Resource": {
39+
"Fn::Join": [
40+
"",
41+
[
42+
"arn:",
43+
{
44+
"Ref": "AWS::Partition"
45+
},
46+
":logs:",
47+
{
48+
"Ref": "AWS::Region"
49+
},
50+
":",
51+
{
52+
"Ref": "AWS::AccountId"
53+
},
54+
":log-group:AWSIotLogsV2:*"
55+
]
56+
]
57+
}
58+
}
59+
],
60+
"Version": "2012-10-17"
61+
},
62+
"PolicyName": "LoggingPolicy"
63+
}
64+
]
65+
}
66+
},
67+
"Logging019093B9": {
68+
"Type": "AWS::IoT::Logging",
69+
"Properties": {
70+
"AccountId": {
71+
"Ref": "AWS::AccountId"
72+
},
73+
"DefaultLogLevel": "DEBUG",
74+
"RoleArn": {
75+
"Fn::GetAtt": [
76+
"LoggingRoleF8CB8FA1",
77+
"Arn"
78+
]
79+
}
80+
}
81+
}
82+
},
83+
"Parameters": {
84+
"BootstrapVersion": {
85+
"Type": "AWS::SSM::Parameter::Value<String>",
86+
"Default": "/cdk-bootstrap/hnb659fds/version",
87+
"Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
88+
}
89+
},
90+
"Rules": {
91+
"CheckBootstrapVersion": {
92+
"Assertions": [
93+
{
94+
"Assert": {
95+
"Fn::Not": [
96+
{
97+
"Fn::Contains": [
98+
[
99+
"1",
100+
"2",
101+
"3",
102+
"4",
103+
"5"
104+
],
105+
{
106+
"Ref": "BootstrapVersion"
107+
}
108+
]
109+
}
110+
]
111+
},
112+
"AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
113+
}
114+
]
115+
}
116+
}
117+
}

packages/@aws-cdk/aws-iot-alpha/test/integ.logging.js.snapshot/cdk.out

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@aws-cdk/aws-iot-alpha/test/integ.logging.js.snapshot/integ.json

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)