Skip to content

Commit e22ab1c

Browse files
authored
Patch in CodeDeploy permissions for hooks (#110)
* Patch in CodeDeploy permissions for hooks `BeforeAllowTrafficHook`s and `AfterAllowTrafficHook`s require access to report their status back to CodeDeploy. It's tedious and brittle to manually add these to `iamRoleStatements` as they rely on CloudFormation logical IDs generated by the plugin itself. This detects which functions have a hook defined and appends permissions to report on their corresponding deployment groups. Resolves #93.
1 parent aaf7fc7 commit e22ab1c

15 files changed

+1127
-4
lines changed

fixtures/1.output.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,17 @@
116116
]
117117
}
118118
]
119+
},
120+
{
121+
"Action": [
122+
"codedeploy:PutLifecycleEventHookExecutionStatus"
123+
],
124+
"Effect": "Allow",
125+
"Resource": [
126+
{
127+
"Fn::Sub": "arn:${AWS::Partition}:codedeploy:${AWS::Region}:${AWS::AccountId}:deploymentgroup:${CanarydeploymentstestdevDeploymentApplication}/${HelloLambdaFunctionDeploymentGroup}"
128+
}
129+
]
119130
}
120131
]
121132
}

fixtures/10.output.v2-websocket.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,17 @@
176176
]
177177
}
178178
]
179+
},
180+
{
181+
"Action": [
182+
"codedeploy:PutLifecycleEventHookExecutionStatus"
183+
],
184+
"Effect": "Allow",
185+
"Resource": [
186+
{
187+
"Fn::Sub": "arn:${AWS::Partition}:codedeploy:${AWS::Region}:${AWS::AccountId}:deploymentgroup:${CanarydeploymentstestdevDeploymentApplication}/${HelloLambdaFunctionDeploymentGroup}"
188+
}
189+
]
179190
}
180191
]
181192
}

fixtures/11.output.v2-websocket-authorizer.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,17 @@
186186
]
187187
}
188188
]
189+
},
190+
{
191+
"Action": [
192+
"codedeploy:PutLifecycleEventHookExecutionStatus"
193+
],
194+
"Effect": "Allow",
195+
"Resource": [
196+
{
197+
"Fn::Sub": "arn:${AWS::Partition}:codedeploy:${AWS::Region}:${AWS::AccountId}:deploymentgroup:${CanarydeploymentstestdevDeploymentApplication}/${HelloLambdaFunctionDeploymentGroup}"
198+
}
199+
]
189200
}
190201
]
191202
}
Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
{
2+
"AWSTemplateFormatVersion": "2010-09-09",
3+
"Description": "The AWS CloudFormation template for this Serverless application",
4+
"Resources": {
5+
"ServerlessDeploymentBucket": {
6+
"Type": "AWS::S3::Bucket"
7+
},
8+
"HelloLogGroup": {
9+
"Type": "AWS::Logs::LogGroup",
10+
"Properties": {
11+
"LogGroupName": "/aws/lambda/canary-deployments-test-dev-hello"
12+
}
13+
},
14+
"GoodbyeLogGroup": {
15+
"Type": "AWS::Logs::LogGroup",
16+
"Properties": {
17+
"LogGroupName": "/aws/lambda/canary-deployments-test-dev-goodbye"
18+
}
19+
},
20+
"PreHookLogGroup": {
21+
"Type": "AWS::Logs::LogGroup",
22+
"Properties": {
23+
"LogGroupName": "/aws/lambda/canary-deployments-test-dev-preHook"
24+
}
25+
},
26+
"PostHookLogGroup": {
27+
"Type": "AWS::Logs::LogGroup",
28+
"Properties": {
29+
"LogGroupName": "/aws/lambda/canary-deployments-test-dev-postHook"
30+
}
31+
},
32+
"IamRoleLambdaExecution": {
33+
"Type": "AWS::IAM::Role",
34+
"Properties": {
35+
"AssumeRolePolicyDocument": {
36+
"Version": "2012-10-17",
37+
"Statement": [
38+
{
39+
"Effect": "Allow",
40+
"Principal": {
41+
"Service": [
42+
"lambda.amazonaws.com"
43+
]
44+
},
45+
"Action": [
46+
"sts:AssumeRole"
47+
]
48+
}
49+
]
50+
},
51+
"Policies": [
52+
{
53+
"PolicyName": {
54+
"Fn::Join": [
55+
"-",
56+
[
57+
"dev",
58+
"canary-deployments-test",
59+
"lambda"
60+
]
61+
]
62+
},
63+
"PolicyDocument": {
64+
"Version": "2012-10-17",
65+
"Statement": [
66+
{
67+
"Effect": "Allow",
68+
"Action": [
69+
"logs:CreateLogStream"
70+
],
71+
"Resource": [
72+
{
73+
"Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/canary-deployments-test-dev-hello:*"
74+
},
75+
{
76+
"Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/canary-deployments-test-dev-goodbye:*"
77+
},
78+
{
79+
"Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/canary-deployments-test-dev-preHook:*"
80+
},
81+
{
82+
"Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/canary-deployments-test-dev-postHook:*"
83+
}
84+
]
85+
},
86+
{
87+
"Effect": "Allow",
88+
"Action": [
89+
"logs:PutLogEvents"
90+
],
91+
"Resource": [
92+
{
93+
"Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/canary-deployments-test-dev-hello:*:*"
94+
},
95+
{
96+
"Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/canary-deployments-test-dev-goodbye:*:*"
97+
},
98+
{
99+
"Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/canary-deployments-test-dev-preHook:*:*"
100+
},
101+
{
102+
"Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/canary-deployments-test-dev-postHook:*:*"
103+
}
104+
]
105+
}
106+
]
107+
}
108+
}
109+
],
110+
"Path": "/",
111+
"RoleName": {
112+
"Fn::Join": [
113+
"-",
114+
[
115+
"canary-deployments-test",
116+
"dev",
117+
"us-east-1",
118+
"lambdaRole"
119+
]
120+
]
121+
}
122+
}
123+
},
124+
"HelloLambdaFunction": {
125+
"Type": "AWS::Lambda::Function",
126+
"Properties": {
127+
"Code": {
128+
"S3Bucket": {
129+
"Ref": "ServerlessDeploymentBucket"
130+
},
131+
"S3Key": "serverless/canary-deployments-test/dev/1520191533287-2018-03-04T19:25:33.287Z/canary-deployments-test.zip"
132+
},
133+
"FunctionName": "canary-deployments-test-dev-hello",
134+
"Handler": "handler.hello",
135+
"MemorySize": 1024,
136+
"Role": {
137+
"Fn::GetAtt": [
138+
"IamRoleLambdaExecution",
139+
"Arn"
140+
]
141+
},
142+
"Runtime": "nodejs6.10",
143+
"Timeout": 6
144+
},
145+
"DependsOn": [
146+
"HelloLogGroup",
147+
"IamRoleLambdaExecution"
148+
]
149+
},
150+
"HelloLambdaVersionFYAirphUvjV7H12yGxU1eQrqAiSBMjAi9hdLPgV62L8": {
151+
"Type": "AWS::Lambda::Version",
152+
"DeletionPolicy": "Retain",
153+
"Properties": {
154+
"FunctionName": {
155+
"Ref": "HelloLambdaFunction"
156+
},
157+
"CodeSha256": "sZvdDgxnAbKe1yaQga0XJPD82+o5jFWz+J3lR+q9UHU="
158+
}
159+
},
160+
"GoodbyeLambdaFunction": {
161+
"Type": "AWS::Lambda::Function",
162+
"Properties": {
163+
"Code": {
164+
"S3Bucket": {
165+
"Ref": "ServerlessDeploymentBucket"
166+
},
167+
"S3Key": "serverless/canary-deployments-test/dev/1575930299000-2019-12-09T22:24:59.000Z/canary-deployments-test.zip"
168+
},
169+
"FunctionName": "canary-deployments-test-dev-goodbye",
170+
"Handler": "handler.goodbye",
171+
"MemorySize": 1024,
172+
"Role": {
173+
"Fn::GetAtt": [
174+
"IamRoleLambdaExecution",
175+
"Arn"
176+
]
177+
},
178+
"Runtime": "nodejs10.x",
179+
"Timeout": 6
180+
},
181+
"DependsOn": [
182+
"GoodbyeLogGroup",
183+
"IamRoleLambdaExecution"
184+
]
185+
},
186+
"GoodbyeLambdaVersionbTfsT57iU4ZfOGZTf3Zj4S1BeSuy3parpc3gsEQB14": {
187+
"Type": "AWS::Lambda::Version",
188+
"DeletionPolicy": "Retain",
189+
"Properties": {
190+
"FunctionName": {
191+
"Ref": "GoodbyeLambdaFunction"
192+
},
193+
"CodeSha256": "Ofxyq/kgN80mbxe4T0albpCu+wmd3J6qqY/ur4VFDMQ="
194+
}
195+
},
196+
"PreHookLambdaFunction": {
197+
"Type": "AWS::Lambda::Function",
198+
"Properties": {
199+
"Code": {
200+
"S3Bucket": {
201+
"Ref": "ServerlessDeploymentBucket"
202+
},
203+
"S3Key": "serverless/canary-deployments-test/dev/1520191533287-2018-03-04T19:25:33.287Z/canary-deployments-test.zip"
204+
},
205+
"FunctionName": "canary-deployments-test-dev-preHook",
206+
"Handler": "hooks.pre",
207+
"MemorySize": 1024,
208+
"Role": {
209+
"Fn::GetAtt": [
210+
"IamRoleLambdaExecution",
211+
"Arn"
212+
]
213+
},
214+
"Runtime": "nodejs6.10",
215+
"Timeout": 6
216+
},
217+
"DependsOn": [
218+
"PreHookLogGroup",
219+
"IamRoleLambdaExecution"
220+
]
221+
},
222+
"PreHookLambdaVersionIYyrXlfQM5jjU68REvnAzRxhgq9eoLqSsDjy0": {
223+
"Type": "AWS::Lambda::Version",
224+
"DeletionPolicy": "Retain",
225+
"Properties": {
226+
"FunctionName": {
227+
"Ref": "PreHookLambdaFunction"
228+
},
229+
"CodeSha256": "sZvdDgxnAbKe1yaQga0XJPD82+o5jFWz+J3lR+q9UHU="
230+
}
231+
},
232+
"PostHookLambdaFunction": {
233+
"Type": "AWS::Lambda::Function",
234+
"Properties": {
235+
"Code": {
236+
"S3Bucket": {
237+
"Ref": "ServerlessDeploymentBucket"
238+
},
239+
"S3Key": "serverless/canary-deployments-test/dev/1520191533287-2018-03-04T19:25:33.287Z/canary-deployments-test.zip"
240+
},
241+
"FunctionName": "canary-deployments-test-dev-postHook",
242+
"Handler": "hooks.post",
243+
"MemorySize": 1024,
244+
"Role": {
245+
"Fn::GetAtt": [
246+
"IamRoleLambdaExecution",
247+
"Arn"
248+
]
249+
},
250+
"Runtime": "nodejs6.10",
251+
"Timeout": 6
252+
},
253+
"DependsOn": [
254+
"PostHookLogGroup",
255+
"IamRoleLambdaExecution"
256+
]
257+
},
258+
"PostHookLambdaVersiondh0VUUAh9BrmvORqx3vDEIcHxolKWKCO1YL45mVTbg": {
259+
"Type": "AWS::Lambda::Version",
260+
"DeletionPolicy": "Retain",
261+
"Properties": {
262+
"FunctionName": {
263+
"Ref": "PostHookLambdaFunction"
264+
},
265+
"CodeSha256": "sZvdDgxnAbKe1yaQga0XJPD82+o5jFWz+J3lR+q9UHU="
266+
}
267+
}
268+
},
269+
"Outputs": {
270+
"ServerlessDeploymentBucketName": {
271+
"Value": {
272+
"Ref": "ServerlessDeploymentBucket"
273+
}
274+
},
275+
"HelloLambdaFunctionQualifiedArn": {
276+
"Description": "Current Lambda function version",
277+
"Value": {
278+
"Ref": "HelloLambdaVersionFYAirphUvjV7H12yGxU1eQrqAiSBMjAi9hdLPgV62L8"
279+
}
280+
},
281+
"GoodbyeLambdaFunctionQualifiedArn": {
282+
"Description": "Current Lambda function version",
283+
"Value": {
284+
"Ref": "GoodbyeLambdaVersionbTfsT57iU4ZfOGZTf3Zj4S1BeSuy3parpc3gsEQB14"
285+
}
286+
},
287+
"PreHookLambdaFunctionQualifiedArn": {
288+
"Description": "Current Lambda function version",
289+
"Value": {
290+
"Ref": "PreHookLambdaVersionIYyrXlfQM5jjU68REvnAzRxhgq9eoLqSsDjy0"
291+
}
292+
},
293+
"PostHookLambdaFunctionQualifiedArn": {
294+
"Description": "Current Lambda function version",
295+
"Value": {
296+
"Ref": "PostHookLambdaVersiondh0VUUAh9BrmvORqx3vDEIcHxolKWKCO1YL45mVTbg"
297+
}
298+
},
299+
"ServiceEndpoint": {
300+
"Description": "URL of the service endpoint",
301+
"Value": {
302+
"Fn::Join": [
303+
"",
304+
[
305+
"https://",
306+
{
307+
"Ref": "ApiGatewayRestApi"
308+
},
309+
".execute-api.us-east-1.amazonaws.com/dev"
310+
]
311+
]
312+
}
313+
}
314+
}
315+
}

0 commit comments

Comments
 (0)