Skip to content

Commit 4c72a7d

Browse files
feat(chatbot): support guardrail policies (#24114)
Support defining guardrail policies when creating a SlackChannelConfiguration Closes #20788 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 1e9220f commit 4c72a7d

9 files changed

+376
-0
lines changed

packages/@aws-cdk/aws-chatbot/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,8 @@ allows you to customize the maximum number of retries and base backoff duration.
5252
resource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cfn-customresource.html) is added
5353
to the stack that pre-creates the log group as part of the stack deployment, if it already doesn't exist, and sets the
5454
correct log retention period (never expire, by default).
55+
56+
## Guardrails
57+
58+
By default slack channel will use `AdministratorAccess` managed policy as guardrail policy.
59+
The `guardrailPolicies` property can be used to set a different set of managed policies.

packages/@aws-cdk/aws-chatbot/lib/slack-channel-configuration.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ export interface SlackChannelConfigurationProps {
8181
* @default - Default AWS SDK retry options.
8282
*/
8383
readonly logRetentionRetryOptions?: logs.LogRetentionRetryOptions;
84+
85+
/**
86+
* A list of IAM managed policies that are applied as channel guardrails.
87+
* @default - The AWS managed 'AdministratorAccess' policy is applied as a default if this is not set.
88+
*/
89+
readonly guardrailPolicies?: iam.IManagedPolicy[];
8490
}
8591

8692
/**
@@ -293,6 +299,7 @@ export class SlackChannelConfiguration extends SlackChannelConfigurationBase {
293299
slackChannelId: props.slackChannelId,
294300
snsTopicArns: cdk.Lazy.list({ produce: () => this.notificationTopics.map(topic => topic.topicArn) }, { omitEmpty: true } ),
295301
loggingLevel: props.loggingLevel?.toString(),
302+
guardrailPolicies: cdk.Lazy.list({ produce: () => props.guardrailPolicies?.map(policy => policy.managedPolicyArn) }, { omitEmpty: true } ),
296303
});
297304

298305
// Log retention
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"version": "29.0.0",
3+
"files": {
4+
"6c1ea5243130449f4b215f7eac487f2dd07715c6751857440bbbfeb883e736ce": {
5+
"source": {
6+
"path": "ChatbotGuardrailsInteg.template.json",
7+
"packaging": "file"
8+
},
9+
"destinations": {
10+
"current_account-current_region": {
11+
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12+
"objectKey": "6c1ea5243130449f4b215f7eac487f2dd07715c6751857440bbbfeb883e736ce.json",
13+
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
14+
}
15+
}
16+
}
17+
},
18+
"dockerImages": {}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
{
2+
"Resources": {
3+
"MySlackChannelConfigurationRole1D3F23AE": {
4+
"Type": "AWS::IAM::Role",
5+
"Properties": {
6+
"AssumeRolePolicyDocument": {
7+
"Statement": [
8+
{
9+
"Action": "sts:AssumeRole",
10+
"Effect": "Allow",
11+
"Principal": {
12+
"Service": "chatbot.amazonaws.com"
13+
}
14+
}
15+
],
16+
"Version": "2012-10-17"
17+
}
18+
}
19+
},
20+
"MySlackChannelA8E0B56C": {
21+
"Type": "AWS::Chatbot::SlackChannelConfiguration",
22+
"Properties": {
23+
"ConfigurationName": "test-channel",
24+
"IamRoleArn": {
25+
"Fn::GetAtt": [
26+
"MySlackChannelConfigurationRole1D3F23AE",
27+
"Arn"
28+
]
29+
},
30+
"SlackChannelId": "C0187JABUE9",
31+
"SlackWorkspaceId": "T49239U4W",
32+
"GuardrailPolicies": [
33+
{
34+
"Fn::Join": [
35+
"",
36+
[
37+
"arn:",
38+
{
39+
"Ref": "AWS::Partition"
40+
},
41+
":iam::aws:policy/CloudWatchReadOnlyAccess"
42+
]
43+
]
44+
}
45+
]
46+
}
47+
}
48+
},
49+
"Parameters": {
50+
"BootstrapVersion": {
51+
"Type": "AWS::SSM::Parameter::Value<String>",
52+
"Default": "/cdk-bootstrap/hnb659fds/version",
53+
"Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
54+
}
55+
},
56+
"Rules": {
57+
"CheckBootstrapVersion": {
58+
"Assertions": [
59+
{
60+
"Assert": {
61+
"Fn::Not": [
62+
{
63+
"Fn::Contains": [
64+
[
65+
"1",
66+
"2",
67+
"3",
68+
"4",
69+
"5"
70+
],
71+
{
72+
"Ref": "BootstrapVersion"
73+
}
74+
]
75+
}
76+
]
77+
},
78+
"AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
79+
}
80+
]
81+
}
82+
}
83+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"version":"29.0.0"}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{
2+
"version": "29.0.0",
3+
"artifacts": {
4+
"ChatbotGuardrailsInteg.assets": {
5+
"type": "cdk:asset-manifest",
6+
"properties": {
7+
"file": "ChatbotGuardrailsInteg.assets.json",
8+
"requiresBootstrapStackVersion": 6,
9+
"bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version"
10+
}
11+
},
12+
"ChatbotGuardrailsInteg": {
13+
"type": "aws:cloudformation:stack",
14+
"environment": "aws://unknown-account/unknown-region",
15+
"properties": {
16+
"templateFile": "ChatbotGuardrailsInteg.template.json",
17+
"validateOnSynth": false,
18+
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}",
19+
"cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}",
20+
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/6c1ea5243130449f4b215f7eac487f2dd07715c6751857440bbbfeb883e736ce.json",
21+
"requiresBootstrapStackVersion": 6,
22+
"bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version",
23+
"additionalDependencies": [
24+
"ChatbotGuardrailsInteg.assets"
25+
],
26+
"lookupRole": {
27+
"arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}",
28+
"requiresBootstrapStackVersion": 8,
29+
"bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version"
30+
}
31+
},
32+
"dependencies": [
33+
"ChatbotGuardrailsInteg.assets"
34+
],
35+
"metadata": {
36+
"/ChatbotGuardrailsInteg/MySlackChannel/ConfigurationRole/Resource": [
37+
{
38+
"type": "aws:cdk:logicalId",
39+
"data": "MySlackChannelConfigurationRole1D3F23AE"
40+
}
41+
],
42+
"/ChatbotGuardrailsInteg/MySlackChannel/Resource": [
43+
{
44+
"type": "aws:cdk:logicalId",
45+
"data": "MySlackChannelA8E0B56C"
46+
}
47+
],
48+
"/ChatbotGuardrailsInteg/BootstrapVersion": [
49+
{
50+
"type": "aws:cdk:logicalId",
51+
"data": "BootstrapVersion"
52+
}
53+
],
54+
"/ChatbotGuardrailsInteg/CheckBootstrapVersion": [
55+
{
56+
"type": "aws:cdk:logicalId",
57+
"data": "CheckBootstrapVersion"
58+
}
59+
]
60+
},
61+
"displayName": "ChatbotGuardrailsInteg"
62+
},
63+
"Tree": {
64+
"type": "cdk:tree",
65+
"properties": {
66+
"file": "tree.json"
67+
}
68+
}
69+
}
70+
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
{
2+
"version": "tree-0.1",
3+
"tree": {
4+
"id": "App",
5+
"path": "",
6+
"children": {
7+
"ChatbotGuardrailsInteg": {
8+
"id": "ChatbotGuardrailsInteg",
9+
"path": "ChatbotGuardrailsInteg",
10+
"children": {
11+
"MyPolicy": {
12+
"id": "MyPolicy",
13+
"path": "ChatbotGuardrailsInteg/MyPolicy",
14+
"constructInfo": {
15+
"fqn": "@aws-cdk/core.Resource",
16+
"version": "0.0.0"
17+
}
18+
},
19+
"MySlackChannel": {
20+
"id": "MySlackChannel",
21+
"path": "ChatbotGuardrailsInteg/MySlackChannel",
22+
"children": {
23+
"ConfigurationRole": {
24+
"id": "ConfigurationRole",
25+
"path": "ChatbotGuardrailsInteg/MySlackChannel/ConfigurationRole",
26+
"children": {
27+
"ImportConfigurationRole": {
28+
"id": "ImportConfigurationRole",
29+
"path": "ChatbotGuardrailsInteg/MySlackChannel/ConfigurationRole/ImportConfigurationRole",
30+
"constructInfo": {
31+
"fqn": "@aws-cdk/core.Resource",
32+
"version": "0.0.0"
33+
}
34+
},
35+
"Resource": {
36+
"id": "Resource",
37+
"path": "ChatbotGuardrailsInteg/MySlackChannel/ConfigurationRole/Resource",
38+
"attributes": {
39+
"aws:cdk:cloudformation:type": "AWS::IAM::Role",
40+
"aws:cdk:cloudformation:props": {
41+
"assumeRolePolicyDocument": {
42+
"Statement": [
43+
{
44+
"Action": "sts:AssumeRole",
45+
"Effect": "Allow",
46+
"Principal": {
47+
"Service": "chatbot.amazonaws.com"
48+
}
49+
}
50+
],
51+
"Version": "2012-10-17"
52+
}
53+
}
54+
},
55+
"constructInfo": {
56+
"fqn": "@aws-cdk/aws-iam.CfnRole",
57+
"version": "0.0.0"
58+
}
59+
}
60+
},
61+
"constructInfo": {
62+
"fqn": "@aws-cdk/aws-iam.Role",
63+
"version": "0.0.0"
64+
}
65+
},
66+
"Resource": {
67+
"id": "Resource",
68+
"path": "ChatbotGuardrailsInteg/MySlackChannel/Resource",
69+
"attributes": {
70+
"aws:cdk:cloudformation:type": "AWS::Chatbot::SlackChannelConfiguration",
71+
"aws:cdk:cloudformation:props": {
72+
"configurationName": "test-channel",
73+
"iamRoleArn": {
74+
"Fn::GetAtt": [
75+
"MySlackChannelConfigurationRole1D3F23AE",
76+
"Arn"
77+
]
78+
},
79+
"slackChannelId": "C0187JABUE9",
80+
"slackWorkspaceId": "T49239U4W",
81+
"guardrailPolicies": [
82+
{
83+
"Fn::Join": [
84+
"",
85+
[
86+
"arn:",
87+
{
88+
"Ref": "AWS::Partition"
89+
},
90+
":iam:",
91+
{
92+
"Ref": "AWS::Region"
93+
},
94+
":",
95+
{
96+
"Ref": "AWS::AccountId"
97+
},
98+
":Policy/CloudWatchReadOnlyAccess"
99+
]
100+
]
101+
}
102+
]
103+
}
104+
},
105+
"constructInfo": {
106+
"fqn": "@aws-cdk/aws-chatbot.CfnSlackChannelConfiguration",
107+
"version": "0.0.0"
108+
}
109+
}
110+
},
111+
"constructInfo": {
112+
"fqn": "@aws-cdk/aws-chatbot.SlackChannelConfiguration",
113+
"version": "0.0.0"
114+
}
115+
},
116+
"BootstrapVersion": {
117+
"id": "BootstrapVersion",
118+
"path": "ChatbotGuardrailsInteg/BootstrapVersion",
119+
"constructInfo": {
120+
"fqn": "@aws-cdk/core.CfnParameter",
121+
"version": "0.0.0"
122+
}
123+
},
124+
"CheckBootstrapVersion": {
125+
"id": "CheckBootstrapVersion",
126+
"path": "ChatbotGuardrailsInteg/CheckBootstrapVersion",
127+
"constructInfo": {
128+
"fqn": "@aws-cdk/core.CfnRule",
129+
"version": "0.0.0"
130+
}
131+
}
132+
},
133+
"constructInfo": {
134+
"fqn": "@aws-cdk/core.Stack",
135+
"version": "0.0.0"
136+
}
137+
},
138+
"Tree": {
139+
"id": "Tree",
140+
"path": "Tree",
141+
"constructInfo": {
142+
"fqn": "constructs.Construct",
143+
"version": "10.1.237"
144+
}
145+
}
146+
},
147+
"constructInfo": {
148+
"fqn": "@aws-cdk/core.App",
149+
"version": "0.0.0"
150+
}
151+
}
152+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import * as iam from '@aws-cdk/aws-iam';
2+
import * as cdk from '@aws-cdk/core';
3+
import * as chatbot from '../lib';
4+
5+
class ChatbotGuardrailsInteg extends cdk.Stack {
6+
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
7+
super(scope, id, props);
8+
9+
const guardrailPolicy = iam.ManagedPolicy.fromAwsManagedPolicyName('CloudWatchReadOnlyAccess');
10+
11+
new chatbot.SlackChannelConfiguration(this, 'MySlackChannel', {
12+
slackChannelConfigurationName: 'test-channel',
13+
slackWorkspaceId: 'T49239U4W', // modify to your slack workspace id
14+
slackChannelId: 'C0187JABUE9', // modify to your slack channel id
15+
guardrailPolicies: [guardrailPolicy],
16+
});
17+
}
18+
}
19+
20+
const app = new cdk.App();
21+
22+
new ChatbotGuardrailsInteg(app, 'ChatbotGuardrailsInteg');
23+
24+
app.synth();

0 commit comments

Comments
 (0)