cfn_monitor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,428 @@
1
+ templates:
2
+ HttpCheck:
3
+ EndpointAvailable:
4
+ AlarmActions: crit
5
+ Namespace: HttpCheck
6
+ ComparisonOperator: LessThanThreshold
7
+ Dimensions: [ { Name: 'Endpoint', Value: { 'Fn::Sub': ['${endpoint}', {'env': { Ref: 'EnvironmentName' } } ] } } ]
8
+ Statistic: Maximum
9
+ Threshold: 1
10
+ Period: 60
11
+ EvaluationPeriods: 2
12
+ MetricName: Available
13
+ EndpointTimeTaken:
14
+ AlarmActions: crit
15
+ Namespace: HttpCheck
16
+ ComparisonOperator: GreaterThanThreshold
17
+ Dimensions: [ { Name: 'Endpoint', Value: { 'Fn::Sub': ['${endpoint}', {'env': { Ref: 'EnvironmentName' } } ] } } ]
18
+ Statistic: Minimum
19
+ Threshold: 1000
20
+ Period: 300
21
+ EvaluationPeriods: 1
22
+ MetricName: TimeTaken
23
+ EndpointStatusCodeMatch:
24
+ AlarmActions: crit
25
+ Namespace: HttpCheck
26
+ ComparisonOperator: LessThanThreshold
27
+ Dimensions: [ { Name: 'Endpoint', Value: { 'Fn::Sub': ['${endpoint}', {'env': { Ref: 'EnvironmentName' } } ] } } ]
28
+ Statistic: Maximum
29
+ Threshold: 1
30
+ Period: 60
31
+ EvaluationPeriods: 2
32
+ MetricName: StatusCodeMatch
33
+ HttpCheckBody:
34
+ EndpointResponseBodyRegexMatch:
35
+ AlarmActions: crit
36
+ Namespace: HttpCheck
37
+ ComparisonOperator: LessThanThreshold
38
+ Dimensions: [ { Name: 'Endpoint', Value: { 'Fn::Sub': ['${endpoint}', {'env': { Ref: 'EnvironmentName' } } ] } } ]
39
+ Statistic: Maximum
40
+ Threshold: 1
41
+ Period: 60
42
+ EvaluationPeriods: 2
43
+ MetricName: ResponseBodyRegexMatch
44
+ Services:
45
+ FailedService:
46
+ AlarmActions: warn
47
+ Namespace: ServiceChecks
48
+ ComparisonOperator: GreaterThanThreshold
49
+ Dimensions: [ { Name: 'Service', Value: '${resource}' }, { Name: 'Environment', Value: { Ref: 'EnvironmentName' } } ]
50
+ Statistic: Maximum
51
+ Threshold: 0
52
+ Period: 60
53
+ EvaluationPeriods: 2
54
+ MetricName: Failed_Service
55
+ AlarmDescription: { 'Fn::Join': [ ' ', [ Ref: 'MonitoredStack', { 'Fn::Sub': ['${resource}', {'env': { Ref: 'EnvironmentName' } } ] }, '${alarmName}' ] ] }
56
+ TreatMissingData: notBreaching
57
+ # FailedSSMAgent:
58
+ # AlarmActions: warn
59
+ # Namespace: ServiceChecks
60
+ # ComparisonOperator: GreaterThanThreshold
61
+ # Dimensions: [ { Name: 'Environment', Value: { Ref: 'EnvironmentName' } } ]
62
+ # Statistic: Maximum
63
+ # Threshold: 0
64
+ # Period: 60
65
+ # EvaluationPeriods: 2
66
+ # MetricName: Failed_SSM_Agent
67
+ # AlarmDescription: { 'Fn::Join': [ ' ', [ Ref: 'MonitoredStack', { 'Fn::Sub': ['${resource}', {'env': { Ref: 'EnvironmentName' } } ] }, '${alarmName}' ] ] }
68
+ # TreatMissingData: notBreaching
69
+ Nrpe:
70
+ Warn:
71
+ AlarmActions: warn
72
+ Namespace: NRPE
73
+ ComparisonOperator: GreaterThanThreshold
74
+ Dimensions: [ { Name: 'Host', Value: { 'Fn::Join': [ '-', [ { 'Fn::Sub': ['${env}', {'env': { Ref: 'EnvironmentName' } } ] }, '${resource}' ] ] } } ]
75
+ Statistic: Maximum
76
+ Threshold: 0
77
+ Period: 60
78
+ EvaluationPeriods: 2
79
+ MetricName: ${cmd}
80
+ TreatMissingData: breaching
81
+ AlarmDescription: { 'Fn::Join': [ ' ', [ Ref: 'MonitoredStack', { 'Fn::Sub': ['${resource}', {'env': { Ref: 'EnvironmentName' } } ] }, '${templateName}', '${cmd}', '${alarmName}' ] ] }
82
+ Crit:
83
+ AlarmActions: crit
84
+ Namespace: NRPE
85
+ ComparisonOperator: GreaterThanThreshold
86
+ Dimensions: [ { Name: 'Host', Value: { 'Fn::Join': [ '-', [ { 'Fn::Sub': ['${env}', {'env': { Ref: 'EnvironmentName' } } ] }, '${resource}' ] ] } } ]
87
+ Statistic: Maximum
88
+ Threshold: 1
89
+ Period: 60
90
+ EvaluationPeriods: 2
91
+ MetricName: ${cmd}
92
+ AlarmDescription: { 'Fn::Join': [ ' ', [ Ref: 'MonitoredStack', { 'Fn::Sub': ['${resource}', {'env': { Ref: 'EnvironmentName' } } ] }, '${templateName}', '${cmd}', '${alarmName}' ] ] }
93
+ LambdaMetrics: # Lambda Functions deployed with a Function Name
94
+ Errors:
95
+ AlarmActions: crit
96
+ Namespace: AWS/Lambda
97
+ ComparisonOperator: GreaterThanThreshold
98
+ Dimensions: [ { Name: 'FunctionName', Value: { 'Fn::Sub': ['${metric}', {'env': { Ref: 'EnvironmentName' } } ] } } ]
99
+ Statistic: Average
100
+ Threshold: 0.5
101
+ Period: 60
102
+ EvaluationPeriods: 5
103
+ MetricName: Errors
104
+ TreatMissingData: notBreaching
105
+ ElasticLoadBalancer: # AWS::ElasticLoadBalancing::LoadBalancer
106
+ HealthyHosts:
107
+ AlarmActions: crit
108
+ Namespace: AWS/ELB
109
+ MetricName: HealthyHostCount
110
+ ComparisonOperator: LessThanThreshold
111
+ DimensionsName: LoadBalancerName
112
+ Statistic: Minimum
113
+ Threshold: 2
114
+ Threshold.development: 1
115
+ EvaluationPeriods: 1
116
+ TreatMissingData: notBreaching
117
+ UnHealthyHosts:
118
+ AlarmActions: warn
119
+ Namespace: AWS/ELB
120
+ MetricName: UnHealthyHostCount
121
+ ComparisonOperator: GreaterThanThreshold
122
+ DimensionsName: LoadBalancerName
123
+ Statistic: Maximum
124
+ Threshold: 0
125
+ EvaluationPeriods: 10
126
+ TreatMissingData: notBreaching
127
+ ApplicationELBTargetGroup: # AWS::ElasticLoadBalancingV2::TargetGroup / AWS::ElasticLoadBalancingV2::LoadBalancer where type: application
128
+ HealthyHosts:
129
+ AlarmActions: crit
130
+ Namespace: AWS/ApplicationELB
131
+ MetricName: HealthyHostCount
132
+ ComparisonOperator: LessThanThreshold
133
+ DimensionsName: TargetGroup/LoadBalancer
134
+ Statistic: Minimum
135
+ Threshold: 2
136
+ Threshold.development: 1
137
+ EvaluationPeriods: 1
138
+ TreatMissingData: breaching
139
+ UnHealthyHosts:
140
+ AlarmActions: warn
141
+ Namespace: AWS/ApplicationELB
142
+ MetricName: UnHealthyHostCount
143
+ ComparisonOperator: GreaterThanThreshold
144
+ DimensionsName: TargetGroup/LoadBalancer
145
+ Statistic: Maximum
146
+ Threshold: 0
147
+ EvaluationPeriods: 10
148
+ TreatMissingData: notBreaching
149
+ TargetResponseTime:
150
+ AlarmActions: crit
151
+ Namespace: AWS/ApplicationELB
152
+ MetricName: TargetResponseTime
153
+ ComparisonOperator: GreaterThanThreshold
154
+ DimensionsName: TargetGroup/LoadBalancer
155
+ Statistic: Average
156
+ Threshold: 5
157
+ EvaluationPeriods: 5
158
+ TreatMissingData: notBreaching
159
+ NetworkELBTargetGroup: # AWS::ElasticLoadBalancingV2::TargetGroup / AWS::ElasticLoadBalancingV2::LoadBalancer where type: network
160
+ HealthyHosts:
161
+ AlarmActions: crit
162
+ Namespace: AWS/NetworkELB
163
+ MetricName: HealthyHostCount
164
+ ComparisonOperator: LessThanThreshold
165
+ DimensionsName: TargetGroup/LoadBalancer
166
+ Statistic: Minimum
167
+ Threshold: 2
168
+ Threshold.development: 1
169
+ EvaluationPeriods: 1
170
+ TreatMissingData: breaching
171
+ UnHealthyHosts:
172
+ AlarmActions: warn
173
+ Namespace: AWS/NetworkELB
174
+ MetricName: UnHealthyHostCount
175
+ ComparisonOperator: GreaterThanThreshold
176
+ DimensionsName: TargetGroup/LoadBalancer
177
+ Statistic: Maximum
178
+ Threshold: 0
179
+ EvaluationPeriods: 10
180
+ TreatMissingData: notBreaching
181
+ TargetResponseTime:
182
+ AlarmActions: crit
183
+ Namespace: AWS/NetworkELB
184
+ MetricName: TargetResponseTime
185
+ ComparisonOperator: GreaterThanThreshold
186
+ DimensionsName: TargetGroup/LoadBalancer
187
+ Statistic: Average
188
+ Threshold: 5
189
+ EvaluationPeriods: 5
190
+ TreatMissingData: notBreaching
191
+ AutoScalingGroup: # AWS::AutoScaling::AutoScalingGroup
192
+ CPUUtilizationHighBase:
193
+ AlarmActions: warn
194
+ Namespace: AWS/EC2
195
+ MetricName: CPUUtilization
196
+ ComparisonOperator: GreaterThanThreshold
197
+ DimensionsName: AutoScalingGroupName
198
+ Statistic: Minimum
199
+ Threshold: 75
200
+ EvaluationPeriods: 60
201
+ TreatMissingData: notBreaching
202
+ StatusCheckFailed:
203
+ AlarmActions: warn
204
+ Namespace: AWS/EC2
205
+ MetricName: StatusCheckFailed
206
+ ComparisonOperator: GreaterThanThreshold
207
+ DimensionsName: AutoScalingGroupName
208
+ Statistic: Maximum
209
+ Threshold: 0
210
+ EvaluationPeriods: 10
211
+ Ec2Instance: # AWS::EC2::Instance
212
+ CPUUtilizationHigh:
213
+ AlarmActions: crit
214
+ Namespace: AWS/EC2
215
+ MetricName: CPUUtilization
216
+ ComparisonOperator: GreaterThanThreshold
217
+ DimensionsName: InstanceId
218
+ Statistic: Minimum
219
+ Threshold: 90
220
+ EvaluationPeriods: 10
221
+ StatusCheckFailed:
222
+ AlarmActions: crit
223
+ Namespace: AWS/EC2
224
+ MetricName: StatusCheckFailed
225
+ ComparisonOperator: GreaterThanThreshold
226
+ DimensionsName: InstanceId
227
+ Statistic: Maximum
228
+ Threshold: 0
229
+ EvaluationPeriods: 10
230
+ RDSInstance: # AWS::RDS::DBInstance
231
+ FreeStorageSpaceCrit:
232
+ AlarmActions: crit
233
+ Namespace: AWS/RDS
234
+ MetricName: FreeStorageSpace
235
+ ComparisonOperator: LessThanThreshold
236
+ DimensionsName: DBInstanceIdentifier
237
+ Statistic: Minimum
238
+ Threshold: 50000000000
239
+ Threshold.development: 10000000000
240
+ EvaluationPeriods: 1
241
+ FreeStorageSpaceTask:
242
+ AlarmActions: task
243
+ Namespace: AWS/RDS
244
+ MetricName: FreeStorageSpace
245
+ ComparisonOperator: LessThanThreshold
246
+ DimensionsName: DBInstanceIdentifier
247
+ Statistic: Minimum
248
+ Threshold: 100000000000
249
+ Threshold.development: 20000000000
250
+ EvaluationPeriods: 1
251
+ CPUUtilizationHighSpike:
252
+ AlarmActions: crit
253
+ Namespace: AWS/RDS
254
+ MetricName: CPUUtilization
255
+ ComparisonOperator: GreaterThanThreshold
256
+ DimensionsName: DBInstanceIdentifier
257
+ Statistic: Minimum
258
+ Threshold: 95
259
+ EvaluationPeriods: 10
260
+ CPUUtilizationHighBase:
261
+ AlarmActions: warn
262
+ Namespace: AWS/RDS
263
+ MetricName: CPUUtilization
264
+ ComparisonOperator: GreaterThanThreshold
265
+ DimensionsName: DBInstanceIdentifier
266
+ Statistic: Minimum
267
+ Threshold: 75
268
+ EvaluationPeriods: 60
269
+ DBCluster: # AWS::RDS::DBCluster
270
+ CPUUtilizationHighSpike:
271
+ AlarmActions: crit
272
+ Namespace: AWS/RDS
273
+ MetricName: CPUUtilization
274
+ ComparisonOperator: GreaterThanThreshold
275
+ DimensionsName: DBClusterIdentifier
276
+ Statistic: Minimum
277
+ Threshold: 95
278
+ EvaluationPeriods: 10
279
+ CPUUtilizationHighBase:
280
+ AlarmActions: warn
281
+ Namespace: AWS/RDS
282
+ MetricName: CPUUtilization
283
+ ComparisonOperator: GreaterThanThreshold
284
+ DimensionsName: DBClusterIdentifier
285
+ Statistic: Minimum
286
+ Threshold: 75
287
+ EvaluationPeriods: 60
288
+ RedshiftCluster: # AWS::Redshift::Cluster
289
+ CPUUtilizationHighSpike:
290
+ AlarmActions: crit
291
+ Namespace: AWS/Redshift
292
+ MetricName: CPUUtilization
293
+ ComparisonOperator: GreaterThanThreshold
294
+ DimensionsName: ClusterIdentifier
295
+ Statistic: Minimum
296
+ Threshold: 95
297
+ EvaluationPeriods: 10
298
+ CPUUtilizationHighBase:
299
+ AlarmActions: warn
300
+ Namespace: AWS/Redshift
301
+ MetricName: CPUUtilization
302
+ ComparisonOperator: GreaterThanThreshold
303
+ DimensionsName: ClusterIdentifier
304
+ Statistic: Minimum
305
+ Threshold: 75
306
+ EvaluationPeriods: 60
307
+ UnHealthyCluster:
308
+ AlarmActions: crit
309
+ Namespace: AWS/Redshift
310
+ MetricName: HealthStatus
311
+ ComparisonOperator: GreaterThanThreshold
312
+ DimensionsName: ClusterIdentifier
313
+ Statistic: Maximum
314
+ Threshold: 0
315
+ EvaluationPeriods: 10
316
+ TreatMissingData: notBreaching
317
+ ECSCluster: # AWS::ECS::Cluster
318
+ MemoryUtilizationWarn:
319
+ AlarmActions: warn
320
+ Namespace: AWS/ECS
321
+ MetricName: MemoryUtilization
322
+ ComparisonOperator: GreaterThanThreshold
323
+ DimensionsName: ClusterName
324
+ Statistic: Maximum
325
+ Threshold: 75
326
+ EvaluationPeriods: 10
327
+ MemoryUtilizationCrit:
328
+ AlarmActions: crit
329
+ Namespace: AWS/ECS
330
+ MetricName: MemoryUtilization
331
+ ComparisonOperator: GreaterThanThreshold
332
+ DimensionsName: ClusterName
333
+ Statistic: Maximum
334
+ Threshold: 95
335
+ EvaluationPeriods: 10
336
+ CPUUtilizationHighBase:
337
+ AlarmActions: warn
338
+ Namespace: AWS/ECS
339
+ MetricName: CPUUtilization
340
+ ComparisonOperator: GreaterThanThreshold
341
+ DimensionsName: ClusterName
342
+ Statistic: Minimum
343
+ Threshold: 75
344
+ EvaluationPeriods: 10
345
+ ECSService: #AWS::ECS::Service
346
+ UnHealthyTask:
347
+ AlarmActions: crit
348
+ MetricName: MemoryUtilization
349
+ Namespace: AWS/ECS
350
+ Statistic: SampleCount
351
+ DimensionsName: ServiceName/ClusterName
352
+ Period: 60
353
+ EvaluationPeriods: 10
354
+ DatapointsToAlarm: 8
355
+ Threshold: 0.0
356
+ ComparisonOperator: LessThanOrEqualToThreshold
357
+ TreatMissingData: breaching
358
+ ECSTasks:
359
+ UnHealthyTaskWarn:
360
+ AlarmActions: warn
361
+ MetricName: MemoryUtilization
362
+ Namespace: AWS/ECS
363
+ Statistic: SampleCount
364
+ DimensionsName: ServiceName/ClusterName
365
+ Period: 60
366
+ EvaluationPeriods: 10
367
+ DatapointsToAlarm: 10
368
+ Threshold: 1.0
369
+ ComparisonOperator: LessThanOrEqualToThreshold
370
+ TreatMissingData: breaching
371
+ ElastiCacheReplicationGroup: # AWS::ElastiCache::ReplicationGroup
372
+ FreeableMemoryWarn:
373
+ AlarmActions: warn
374
+ Namespace: AWS/ElastiCache
375
+ MetricName: FreeableMemory
376
+ ComparisonOperator: LessThanThreshold
377
+ DimensionsName: CacheClusterId
378
+ Statistic: Maximum
379
+ Threshold: 100000000
380
+ EvaluationPeriods: 10
381
+ CPUUtilizationHighBase:
382
+ AlarmActions: warn
383
+ Namespace: AWS/ElastiCache
384
+ MetricName: CPUUtilization
385
+ ComparisonOperator: GreaterThanThreshold
386
+ DimensionsName: CacheClusterId
387
+ Statistic: Minimum
388
+ Threshold: 75
389
+ EvaluationPeriods: 10
390
+ ElasticFileSystem: # AWS::EFS::FileSystem
391
+ PercentIOLimitHigh:
392
+ AlarmActions: crit
393
+ Namespace: AWS/EFS
394
+ MetricName: PercentIOLimit
395
+ ComparisonOperator: GreaterThanThreshold
396
+ DimensionsName: FileSystemId
397
+ Statistic: Minimum
398
+ Threshold: 90
399
+ EvaluationPeriods: 5
400
+ ApiGateway: #AWS:ApiGateway
401
+ ApiEndpoint5xx:
402
+ AlarmActions: crit
403
+ Namespace: AWS/ApiGateway
404
+ MetricName: 5XXError
405
+ ComparisonOperator: GreaterThanThreshold
406
+ DimensionsName: ApiName
407
+ Statistic: Sum
408
+ Threshold: 5
409
+ EvaluationPdyneriods: 2
410
+ DynamoDBTable: #AWS::DynamoDB::Table
411
+ DynamoDBReadUsage:
412
+ AlarmActions: warn
413
+ Namespace: AWS/DynamoDB
414
+ MetricName: ConsumedReadCapacityUnits
415
+ ComparisonOperator: GreaterThanThreshold
416
+ DimensionsName: TableName
417
+ Statistic: Sum
418
+ Threshold: 80
419
+ EvaluationPeriods: 2
420
+ DynamoDBWriteUsage:
421
+ AlarmActions: warn
422
+ Namespace: AWS/DynamoDB
423
+ MetricName: ConsumedWriteCapacityUnits
424
+ ComparisonOperator: GreaterThanThreshold
425
+ DimensionsName: TableName
426
+ Statistic: Sum
427
+ Threshold: 80
428
+ EvaluationPeriods: 2
data/lib/ext/alarms.rb ADDED
@@ -0,0 +1,33 @@
1
+ def replace_vars(hash,find,replace)
2
+ if hash.is_a?(Hash)
3
+ hash.each do |k, v|
4
+ replace_vars(v,find,replace)
5
+ end
6
+ elsif hash.is_a?(Array)
7
+ hash.each do |e|
8
+ replace_vars(e,find,replace)
9
+ end
10
+ elsif hash.is_a?(String) && hash == find
11
+ hash.replace replace
12
+ end
13
+ hash
14
+ end
15
+
16
+ def create_param_mappings(params,template_envs,alarmHash)
17
+ mappings = {}
18
+ params.each do |key,value|
19
+ if !key.include? '.'
20
+ if [String, Integer, Float, Fixnum, TrueClass].member?(value.class)
21
+ mappings[key] = {}
22
+ template_envs.each do |env|
23
+ if !params["#{key}.#{env}"].nil? && [String, Integer, Float, Fixnum, TrueClass].member?(params["#{key}.#{env}"].class)
24
+ mappings[key][env] = params["#{key}.#{env}"]
25
+ else
26
+ mappings[key][env] = value
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ Mapping("#{alarmHash}", mappings)
33
+ end
@@ -0,0 +1,39 @@
1
+ import json
2
+ import cfnresponse
3
+ import boto3
4
+ from botocore.exceptions import ClientError
5
+ import time
6
+
7
+ def getEnvironmentName(client,stackName):
8
+ time.sleep(5)
9
+ max_retries = 5
10
+ sleep_time = 1
11
+ for i in range(max_retries):
12
+ try:
13
+ response = client.describe_stacks(StackName=stackName)
14
+ except ClientError as e:
15
+ print e
16
+ time.sleep(sleep_time)
17
+ sleep_time += sleep_time
18
+ continue
19
+ else:
20
+ break
21
+ else:
22
+ return stackName
23
+ if 'Parameters' in response['Stacks'][0]:
24
+ for r in response['Stacks'][0]['Parameters']:
25
+ if r['ParameterKey'] == 'EnvironmentName':
26
+ return r['ParameterValue']
27
+ return stackName
28
+ else:
29
+ return stackName
30
+
31
+
32
+ def handler(event, context):
33
+ stackName = event['ResourceProperties']['StackName']
34
+ region = event['ResourceProperties']['Region']
35
+ client = boto3.client('cloudformation',region_name=region)
36
+
37
+ responseData = {}
38
+ responseData['EnvironmentName'] = getEnvironmentName(client,stackName)
39
+ cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
@@ -0,0 +1,67 @@
1
+ import json
2
+ import cfnresponse
3
+ import boto3
4
+ from botocore.exceptions import ClientError
5
+ import time
6
+
7
+ def findNestedStack(client,resource):
8
+ if len(resource) == 2:
9
+ return resource
10
+ else:
11
+ max_retries = 20
12
+ sleep_time = 1
13
+ for i in range(max_retries):
14
+ try:
15
+ response = client.list_stack_resources(StackName=resource[0])
16
+ except ClientError as e:
17
+ print e
18
+ time.sleep(sleep_time)
19
+ sleep_time += 1
20
+ continue
21
+ else:
22
+ break
23
+ else:
24
+ return
25
+ for r in response['StackResourceSummaries']:
26
+ if r['ResourceType'] == 'AWS::CloudFormation::Stack':
27
+ if r['LogicalResourceId'] == resource[1]:
28
+ resource[1] = r['PhysicalResourceId']
29
+ del resource[0]
30
+ return findNestedStack(client,resource)
31
+
32
+ def findResource(client,resource):
33
+ time.sleep(5)
34
+ if resource:
35
+ max_retries = 20
36
+ sleep_time = 1
37
+ for i in range(max_retries):
38
+ try:
39
+ paginator = client.get_paginator('list_stack_resources')
40
+ page_iterator = paginator.paginate(StackName=resource[0])
41
+ response = []
42
+ for page in page_iterator:
43
+ response = response + page['StackResourceSummaries']
44
+ except ClientError as e:
45
+ print e
46
+ time.sleep(sleep_time)
47
+ sleep_time += 1
48
+ continue
49
+ else:
50
+ break
51
+ else:
52
+ return
53
+ for r in response:
54
+ if r['LogicalResourceId'] == resource[1]:
55
+ return r['PhysicalResourceId']
56
+ else:
57
+ return
58
+
59
+ def handler(event, context):
60
+ resource = event['ResourceProperties']['LogicalResourceId'].split(".")
61
+ region = event['ResourceProperties']['Region']
62
+ client = boto3.client('cloudformation',region_name=region)
63
+
64
+ responseData = {}
65
+ responseData['PhysicalResourceId'] = findResource(client,findNestedStack(client,resource))
66
+ cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
67
+