cfn-guardian 0.4.0 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build-gem.yml +25 -0
  3. data/.github/workflows/release-gem.yml +25 -0
  4. data/.github/workflows/release-image.yml +33 -0
  5. data/.rspec +1 -0
  6. data/Gemfile.lock +13 -13
  7. data/README.md +3 -819
  8. data/cfn-guardian.gemspec +1 -3
  9. data/docs/alarm_templates.md +130 -0
  10. data/docs/cli.md +182 -0
  11. data/docs/composite_alarms.md +24 -0
  12. data/docs/custom_checks/azure_file_check.md +28 -0
  13. data/docs/custom_checks/domain_expiry.md +10 -0
  14. data/docs/custom_checks/http.md +59 -0
  15. data/docs/custom_checks/log_group_metric_filters.md +27 -0
  16. data/docs/custom_checks/nrpe.md +29 -0
  17. data/docs/custom_checks/port.md +40 -0
  18. data/docs/custom_checks/sftp.md +73 -0
  19. data/docs/custom_checks/sql.md +44 -0
  20. data/docs/custom_checks/tls.md +25 -0
  21. data/docs/custom_metrics.md +71 -0
  22. data/docs/event_subscriptions.md +67 -0
  23. data/docs/maintenance_mode.md +85 -0
  24. data/docs/notifiers.md +33 -0
  25. data/docs/overview.md +22 -0
  26. data/docs/resources.md +93 -0
  27. data/docs/variables.md +58 -0
  28. data/lib/cfnguardian.rb +72 -58
  29. data/lib/cfnguardian/cloudwatch.rb +43 -32
  30. data/lib/cfnguardian/compile.rb +82 -5
  31. data/lib/cfnguardian/deploy.rb +2 -16
  32. data/lib/cfnguardian/display_formatter.rb +1 -2
  33. data/lib/cfnguardian/error.rb +4 -0
  34. data/lib/cfnguardian/models/alarm.rb +40 -28
  35. data/lib/cfnguardian/models/check.rb +30 -12
  36. data/lib/cfnguardian/models/event.rb +43 -15
  37. data/lib/cfnguardian/models/event_subscription.rb +96 -0
  38. data/lib/cfnguardian/resources/azure_file.rb +20 -0
  39. data/lib/cfnguardian/resources/base.rb +111 -26
  40. data/lib/cfnguardian/resources/ec2_instance.rb +11 -0
  41. data/lib/cfnguardian/resources/http.rb +1 -0
  42. data/lib/cfnguardian/resources/rds_cluster.rb +14 -0
  43. data/lib/cfnguardian/resources/rds_instance.rb +71 -0
  44. data/lib/cfnguardian/stacks/main.rb +7 -6
  45. data/lib/cfnguardian/stacks/resources.rb +34 -5
  46. data/lib/cfnguardian/version.rb +1 -1
  47. metadata +35 -10
@@ -9,50 +9,61 @@ module CfnGuardian
9
9
  alarm_id = alarm.resource_name.nil? ? alarm.resource_id : alarm.resource_name
10
10
  return "guardian-#{alarm.group}-#{alarm_id}-#{alarm.name}"
11
11
  end
12
-
13
- def self.get_alarms(alarms)
14
- alarm_names = alarms.map {|alarm| self.get_alarm_name(alarm)}
15
-
12
+
13
+ def self.get_alarms_by_prefix(prefix:, state: nil, action_prefix: nil)
16
14
  client = Aws::CloudWatch::Client.new()
15
+ options = {max_records: 100}
16
+ options[:alarm_name_prefix] = prefix
17
+
18
+ unless state.nil?
19
+ options[:state_value] = state
20
+ end
21
+
22
+ unless action_prefix.nil?
23
+ options[:action_prefix] = action_prefix
24
+ end
25
+
26
+ resp = client.describe_alarms(options)
27
+ return resp.metric_alarms
28
+ end
29
+
30
+ def self.get_alarms_by_name(alarm_names:, state: nil, action_prefix: nil)
31
+ client = Aws::CloudWatch::Client.new()
32
+ options = {max_records: 100}
33
+
34
+ unless state.nil?
35
+ options[:state_value] = state
36
+ end
37
+
38
+ unless action_prefix.nil?
39
+ options[:action_prefix] = "arn:aws:sns:#{Aws.config[:region]}:#{aws_account_id()}:#{action_prefix}"
40
+ end
41
+
17
42
  metric_alarms = []
18
43
  alarm_names.each_slice(100) do |batch|
19
- resp = client.describe_alarms({alarm_names: batch, max_records: 100})
44
+ options[:alarm_names] = batch
45
+ resp = client.describe_alarms(options)
20
46
  metric_alarms.push(*resp.metric_alarms)
21
47
  end
22
-
48
+
23
49
  return metric_alarms
24
50
  end
25
-
26
- def self.get_alarm_state(config_alarms: [], alarm_names: [], alarm_prefix: nil, state: nil)
27
- rows = []
28
-
29
- if config_alarms.any?
30
- alarm_names = config_alarms.map {|alarm| self.get_alarm_name(alarm)}
31
- end
32
-
33
- client = Aws::CloudWatch::Client.new()
34
-
35
- options = {max_records: 100}
36
- options[:state_value] = state if !state.nil?
37
-
38
- cw_alarms = []
39
- if !alarm_prefix.nil?
40
- options[:alarm_name_prefix] = alarm_prefix
41
- resp = client.describe_alarms(options)
42
- cw_alarms = resp.metric_alarms
43
- else
44
- alarm_names.each_slice(100) do |batch|
45
- options[:alarm_names] = batch
46
- resp = client.describe_alarms(options)
47
- cw_alarms.push(*resp.metric_alarms)
51
+
52
+ def self.filter_alarms(filters:, alarms:)
53
+ return alarms unless filters.is_a?(Hash)
54
+ filters = filters.slice('group', 'resource', 'alarm', 'stack-id')
55
+
56
+ filtered_alarms = []
57
+ alarms.each do |alarm|
58
+ if filters.values.all? {|filter| alarm.alarm_name.include? (filter)}
59
+ filtered_alarms << alarm
48
60
  end
49
61
  end
50
-
51
- return cw_alarms
62
+
63
+ return filtered_alarms
52
64
  end
53
65
 
54
66
  def self.get_alarm_history(alarm_name,type)
55
- rows = []
56
67
  client = Aws::CloudWatch::Client.new()
57
68
 
58
69
  logger.debug "Searching #{type} history for #{alarm_name}"
@@ -35,6 +35,9 @@ require 'cfnguardian/resources/log_group'
35
35
  require 'cfnguardian/resources/sftp'
36
36
  require 'cfnguardian/resources/internal_sftp'
37
37
  require 'cfnguardian/resources/tls'
38
+ require 'cfnguardian/resources/azure_file'
39
+ require 'cfnguardian/version'
40
+ require 'cfnguardian/error'
38
41
 
39
42
  module CfnGuardian
40
43
  class Compile
@@ -50,9 +53,10 @@ module CfnGuardian
50
53
  @templates = config.fetch('Templates',{})
51
54
  @topics = config.fetch('Topics',{})
52
55
  @maintenance_groups = config.fetch('MaintenaceGroups', {})
56
+ @event_subscriptions = config.fetch('EventSubscriptions', {})
53
57
 
54
58
  # Make sure the default topics exist if they aren't supplied in the alarms.yaml
55
- %w(Critical Warning Task Informational).each do |topic|
59
+ %w(Critical Warning Task Informational Events).each do |topic|
56
60
  @topics[topic] = '' unless @topics.has_key?(topic)
57
61
  end
58
62
 
@@ -86,10 +90,15 @@ module CfnGuardian
86
90
  end
87
91
  end
88
92
 
89
- overides = @templates.has_key?(group) ? @templates[group] : {}
90
- @resources.concat resource_class.get_alarms(resource,group,overides)
93
+ template_overides = @templates.has_key?(group) ? @templates[group] : {}
94
+ @resources.concat resource_class.get_alarms(group,template_overides)
95
+
91
96
  @resources.concat resource_class.get_metric_filters()
92
97
  @resources.concat resource_class.get_events()
98
+
99
+ event_subscriptions = @event_subscriptions.has_key?(group) ? @event_subscriptions[group] : {}
100
+ @resources.concat resource_class.get_event_subscriptions(group,event_subscriptions)
101
+
93
102
  @checks.concat resource_class.get_checks()
94
103
 
95
104
  @cost += resource_class.get_cost
@@ -100,13 +109,16 @@ module CfnGuardian
100
109
  resource_groups.each do |group, alarms|
101
110
  alarms.each do |alarm, resources|
102
111
  resources.each do |resource|
112
+
103
113
  res = @resources.find {|r|
104
114
  (r.type == 'Alarm') &&
105
- (r.class == group && r.name == alarm) &&
115
+ (r.group == group && r.name == alarm) &&
106
116
  (r.resource_id == resource['Id'] || r.resource_name == resource['Name'])}
117
+
107
118
  unless res.nil?
108
119
  res.maintenance_groups.append("#{maintenance_group}MaintenanceGroup")
109
120
  end
121
+
110
122
  end
111
123
  end
112
124
  end
@@ -118,11 +130,39 @@ module CfnGuardian
118
130
  end
119
131
 
120
132
  @ssm_parameters = @resources.select {|resource| resource.type == 'Event'}.map {|event| event.ssm_parameters}.flatten.uniq
133
+
134
+ validate_resources()
121
135
  end
122
136
 
123
137
  def alarms
124
138
  @resources.select {|resource| resource.type == 'Alarm'}
125
139
  end
140
+
141
+ def validate_resources()
142
+ errors = []
143
+ @resources.each do |resource|
144
+ case resource.type
145
+ when 'Alarm'
146
+ %w(metric_name namespace).each do |property|
147
+ if resource.send(property).nil?
148
+ errors << "Alarm #{resource.name} for resource #{resource.resource_id} has nil value for property #{property.to_camelcase}"
149
+ end
150
+ end
151
+ when 'Check'
152
+ # no validation check yet
153
+ when 'Event'
154
+ # no validation check yet
155
+ when 'Composite'
156
+ # no validation check yet
157
+ when 'EventSubscription'
158
+ # no validation check yet
159
+ when 'MetricFilter'
160
+ # no validation check yet
161
+ end
162
+ end
163
+
164
+ raise CfnGuardian::ValidationError, "#{errors.size} errors found\n[*] #{errors.join("\n[*] ")}" if errors.any?
165
+ end
126
166
 
127
167
  def split_resources(bucket,path)
128
168
  split = @resources.each_slice(200).to_a
@@ -147,7 +187,7 @@ module CfnGuardian
147
187
  File.write("out/guardian.compiled.yaml", JSON.parse(valid.to_json).to_yaml)
148
188
 
149
189
  resources.each_with_index do |resources,index|
150
- stack = CfnGuardian::Stacks::Resources.new(main_stack.parameters)
190
+ stack = CfnGuardian::Stacks::Resources.new(main_stack.parameters,index)
151
191
  stack.build_template(resources)
152
192
  valid = stack.template.validate
153
193
  File.write("out/guardian-stack-#{index}.compiled.yaml", JSON.parse(valid.to_json).to_yaml)
@@ -157,6 +197,43 @@ module CfnGuardian
157
197
  def clean_out_directory
158
198
  Dir["out/*.yaml"].each {|file| File.delete(file)}
159
199
  end
200
+
201
+ def load_parameters(options)
202
+ parameters = {}
203
+ # Load sns topic parameters in order of preference
204
+ @topics.each do |key, value|
205
+ # if parameter is passed in as a command line option
206
+ if options.has_key?("sns_#{key.downcase}")
207
+ parameters[key.to_sym] = options["sns_#{key.downcase}"]
208
+ # if parameter is in config
209
+ elsif !value.empty?
210
+ parameters[key.to_sym] = value
211
+ # if parameter is set as environment variable
212
+ elsif ENV.has_key?("GUARDIAN_TOPIC_#{key.upcase}")
213
+ parameters[key.to_sym] = ENV["GUARDIAN_TOPIC_#{key.upcase}"]
214
+ end
215
+ end
216
+
217
+ return parameters
218
+ end
219
+
220
+ def genrate_template_config(parameters)
221
+ template = {
222
+ Tags: {
223
+ 'guardian:version': CfnGuardian::VERSION
224
+ }
225
+ }
226
+
227
+ if ENV.has_key?('CODEBUILD_RESOLVED_SOURCE_VERSION')
228
+ template[:Tags][:'guardian:config:commit'] = ENV['CODEBUILD_RESOLVED_SOURCE_VERSION']
229
+ end
230
+
231
+ unless parameters.empty?
232
+ template[:Parameters] = parameters
233
+ end
234
+
235
+ File.write("out/template-config.guardian.json", template.to_json)
236
+ end
160
237
 
161
238
  end
162
239
  end
@@ -7,27 +7,13 @@ module CfnGuardian
7
7
  class Deploy
8
8
  include Logging
9
9
 
10
- def initialize(opts,bucket)
10
+ def initialize(opts,bucket,parameters)
11
11
  @stack_name = opts.fetch(:stack_name,'guardian')
12
12
  @bucket = bucket
13
13
  @prefix = @stack_name
14
14
  @template_path = "out/guardian.compiled.yaml"
15
15
  @template_url = "https://#{@bucket}.s3.amazonaws.com/#{@prefix}/guardian.compiled.yaml"
16
- @parameters = {}
17
-
18
- config = YAML.load_file(opts[:config])
19
- if config.has_key?('Topics')
20
- @parameters['Critical'] = config['Topics'].fetch('Critical','')
21
- @parameters['Warning'] = config['Topics'].fetch('Warning','')
22
- @parameters['Task'] = config['Topics'].fetch('Task','')
23
- @parameters['Informational'] = config['Topics'].fetch('Informational','')
24
- end
25
-
26
- @parameters['Critical'] = opts.fetch(:sns_critical,@parameters['Critical'])
27
- @parameters['Warning'] = opts.fetch(:sns_warning,@parameters['Warning'])
28
- @parameters['Task'] = opts.fetch(:sns_task,@parameters['Task'])
29
- @parameters['Informational'] = opts.fetch(:sns_informational,@parameters['Informational'])
30
-
16
+ @parameters = parameters
31
17
  @client = Aws::CloudFormation::Client.new()
32
18
  end
33
19
 
@@ -14,7 +14,6 @@ module CfnGuardian
14
14
 
15
15
  @alarms.each do |alarm|
16
16
  alarm_name = CfnGuardian::CloudWatch.get_alarm_name(alarm)
17
- puts alarm_name
18
17
  rows = [
19
18
  ['ResourceId', alarm.resource_id],
20
19
  ['ResourceHash', alarm.resource_hash],
@@ -52,7 +51,7 @@ module CfnGuardian
52
51
 
53
52
  @alarms.each do |alarm|
54
53
  alarm_name = CfnGuardian::CloudWatch.get_alarm_name(alarm)
55
- metric_alarm = metric_alarms.find {|ma| ma.alarm_name == alarm_name}
54
+ metric_alarm = metric_alarms.find {|ma| ma.alarm_name.include? alarm_name}
56
55
  dimensions = metric_alarm.dimensions.map {|dim| {dim.name.to_sym => dim.value}}.inject(:merge)
57
56
 
58
57
  rows = [
@@ -0,0 +1,4 @@
1
+ module CfnGuardian
2
+ class ValidationError < StandardError
3
+ end
4
+ end
@@ -3,7 +3,7 @@ require 'digest/md5'
3
3
 
4
4
  module CfnGuardian
5
5
  module Models
6
- class Alarm
6
+ class BaseAlarm
7
7
 
8
8
  attr_reader :type,
9
9
  :resource_hash
@@ -65,7 +65,7 @@ module CfnGuardian
65
65
  end
66
66
 
67
67
 
68
- class ApiGatewayAlarm < Alarm
68
+ class ApiGatewayAlarm < BaseAlarm
69
69
  def initialize(resource)
70
70
  super(resource)
71
71
  @group = 'ApiGateway'
@@ -74,7 +74,7 @@ module CfnGuardian
74
74
  end
75
75
  end
76
76
 
77
- class ApplicationTargetGroupAlarm < Alarm
77
+ class ApplicationTargetGroupAlarm < BaseAlarm
78
78
  def initialize(resource)
79
79
  super(resource)
80
80
  @group = 'ApplicationTargetGroup'
@@ -86,7 +86,7 @@ module CfnGuardian
86
86
  end
87
87
  end
88
88
 
89
- class AmazonMQBrokerAlarm < Alarm
89
+ class AmazonMQBrokerAlarm < BaseAlarm
90
90
  def initialize(resource)
91
91
  super(resource)
92
92
  @group = 'AmazonMQBroker'
@@ -95,7 +95,7 @@ module CfnGuardian
95
95
  end
96
96
  end
97
97
 
98
- class CloudFrontDistributionAlarm < Alarm
98
+ class CloudFrontDistributionAlarm < BaseAlarm
99
99
  def initialize(resource)
100
100
  super(resource)
101
101
  @group = 'CloudFrontDistribution'
@@ -109,7 +109,7 @@ module CfnGuardian
109
109
  end
110
110
  end
111
111
 
112
- class AutoScalingGroupAlarm < Alarm
112
+ class AutoScalingGroupAlarm < BaseAlarm
113
113
  def initialize(resource)
114
114
  super(resource)
115
115
  @group = 'AutoScalingGroup'
@@ -118,7 +118,7 @@ module CfnGuardian
118
118
  end
119
119
  end
120
120
 
121
- class DomainExpiryAlarm < Alarm
121
+ class DomainExpiryAlarm < BaseAlarm
122
122
  def initialize(resource)
123
123
  super(resource)
124
124
  @group = 'DomainExpiry'
@@ -128,7 +128,7 @@ module CfnGuardian
128
128
  end
129
129
  end
130
130
 
131
- class DynamoDBTableAlarm < Alarm
131
+ class DynamoDBTableAlarm < BaseAlarm
132
132
  def initialize(resource)
133
133
  super(resource)
134
134
  @group = 'DynamoDBTable'
@@ -137,7 +137,7 @@ module CfnGuardian
137
137
  end
138
138
  end
139
139
 
140
- class Ec2InstanceAlarm < Alarm
140
+ class Ec2InstanceAlarm < BaseAlarm
141
141
  def initialize(resource)
142
142
  super(resource)
143
143
  @group = 'Ec2Instance'
@@ -146,7 +146,7 @@ module CfnGuardian
146
146
  end
147
147
  end
148
148
 
149
- class ECSClusterAlarm < Alarm
149
+ class ECSClusterAlarm < BaseAlarm
150
150
  def initialize(resource)
151
151
  super(resource)
152
152
  @group = 'ECSCluster'
@@ -158,7 +158,7 @@ module CfnGuardian
158
158
  end
159
159
  end
160
160
 
161
- class ECSServiceAlarm < Alarm
161
+ class ECSServiceAlarm < BaseAlarm
162
162
  def initialize(resource)
163
163
  super(resource)
164
164
  @group = 'ECSService'
@@ -170,7 +170,7 @@ module CfnGuardian
170
170
  end
171
171
  end
172
172
 
173
- class ElastiCacheReplicationGroupAlarm < Alarm
173
+ class ElastiCacheReplicationGroupAlarm < BaseAlarm
174
174
  def initialize(resource)
175
175
  super(resource)
176
176
  @group = 'ElastiCacheReplicationGroup'
@@ -179,7 +179,7 @@ module CfnGuardian
179
179
  end
180
180
  end
181
181
 
182
- class ElasticLoadBalancerAlarm < Alarm
182
+ class ElasticLoadBalancerAlarm < BaseAlarm
183
183
  def initialize(resource)
184
184
  super(resource)
185
185
  @group = 'ElasticLoadBalancer'
@@ -188,7 +188,7 @@ module CfnGuardian
188
188
  end
189
189
  end
190
190
 
191
- class ElasticFileSystemAlarm < Alarm
191
+ class ElasticFileSystemAlarm < BaseAlarm
192
192
  def initialize(resource)
193
193
  super(resource)
194
194
  @group = 'ElasticFileSystem'
@@ -197,7 +197,7 @@ module CfnGuardian
197
197
  end
198
198
  end
199
199
 
200
- class HttpAlarm < Alarm
200
+ class HttpAlarm < BaseAlarm
201
201
  def initialize(resource)
202
202
  super(resource)
203
203
  @group = 'Http'
@@ -215,7 +215,7 @@ module CfnGuardian
215
215
  end
216
216
  end
217
217
 
218
- class PortAlarm < Alarm
218
+ class PortAlarm < BaseAlarm
219
219
  def initialize(resource)
220
220
  super(resource)
221
221
  @group = 'Port'
@@ -233,7 +233,7 @@ module CfnGuardian
233
233
  end
234
234
  end
235
235
 
236
- class SslAlarm < Alarm
236
+ class SslAlarm < BaseAlarm
237
237
  def initialize(resource)
238
238
  super(resource)
239
239
  @group = 'Ssl'
@@ -249,7 +249,7 @@ module CfnGuardian
249
249
  end
250
250
  end
251
251
 
252
- class NrpeAlarm < Alarm
252
+ class NrpeAlarm < BaseAlarm
253
253
  def initialize(resource,environment)
254
254
  super(resource)
255
255
  @group = 'Nrpe'
@@ -260,7 +260,7 @@ module CfnGuardian
260
260
  end
261
261
  end
262
262
 
263
- class LambdaAlarm < Alarm
263
+ class LambdaAlarm < BaseAlarm
264
264
  def initialize(resource)
265
265
  super(resource)
266
266
  @group = 'Lambda'
@@ -271,7 +271,7 @@ module CfnGuardian
271
271
  end
272
272
  end
273
273
 
274
- class NetworkTargetGroupAlarm < Alarm
274
+ class NetworkTargetGroupAlarm < BaseAlarm
275
275
  def initialize(resource)
276
276
  super(resource)
277
277
  @group = 'NetworkTargetGroup'
@@ -283,7 +283,7 @@ module CfnGuardian
283
283
  end
284
284
  end
285
285
 
286
- class RedshiftClusterAlarm < Alarm
286
+ class RedshiftClusterAlarm < BaseAlarm
287
287
  def initialize(resource)
288
288
  super(resource)
289
289
  @group = 'RedshiftCluster'
@@ -292,7 +292,7 @@ module CfnGuardian
292
292
  end
293
293
  end
294
294
 
295
- class RDSClusterInstanceAlarm < Alarm
295
+ class RDSClusterInstanceAlarm < BaseAlarm
296
296
  def initialize(resource)
297
297
  super(resource)
298
298
  @group = 'RDSClusterInstance'
@@ -301,7 +301,7 @@ module CfnGuardian
301
301
  end
302
302
  end
303
303
 
304
- class RDSInstanceAlarm < Alarm
304
+ class RDSInstanceAlarm < BaseAlarm
305
305
  def initialize(resource)
306
306
  super(resource)
307
307
  @group = 'RDSInstance'
@@ -310,7 +310,7 @@ module CfnGuardian
310
310
  end
311
311
  end
312
312
 
313
- class SqlAlarm < Alarm
313
+ class SqlAlarm < BaseAlarm
314
314
  def initialize(resource)
315
315
  super(resource)
316
316
  @group = 'Sql'
@@ -321,7 +321,7 @@ module CfnGuardian
321
321
  end
322
322
  end
323
323
 
324
- class SQSQueueAlarm < Alarm
324
+ class SQSQueueAlarm < BaseAlarm
325
325
  def initialize(resource)
326
326
  super(resource)
327
327
  @group = 'SQSQueue'
@@ -332,7 +332,7 @@ module CfnGuardian
332
332
  end
333
333
  end
334
334
 
335
- class LogGroupAlarm < Alarm
335
+ class LogGroupAlarm < BaseAlarm
336
336
  def initialize(resource)
337
337
  super(resource)
338
338
  @group = 'LogGroup'
@@ -344,7 +344,7 @@ module CfnGuardian
344
344
  end
345
345
  end
346
346
 
347
- class SFTPAlarm < Alarm
347
+ class SFTPAlarm < BaseAlarm
348
348
  def initialize(resource)
349
349
  super(resource)
350
350
  @group = 'SFTP'
@@ -362,7 +362,7 @@ module CfnGuardian
362
362
  end
363
363
  end
364
364
 
365
- class TLSAlarm < Alarm
365
+ class TLSAlarm < BaseAlarm
366
366
  def initialize(resource)
367
367
  super(resource)
368
368
  @group = 'TLS'
@@ -375,6 +375,18 @@ module CfnGuardian
375
375
  @evaluation_periods = 1
376
376
  end
377
377
  end
378
+
379
+ class AzureFileAlarm < BaseAlarm
380
+ def initialize(resource)
381
+ super(resource)
382
+ @group = 'AzureFile'
383
+ @namespace = 'FileAgeCheck'
384
+ @period = 300
385
+ @comparison_operator = 'GreaterThanThreshold'
386
+ @threshold = 0
387
+ @dimensions = { StorageAccount: resource['Id'], StorageContainer: resource['Container'] }
388
+ end
389
+ end
378
390
 
379
391
  end
380
392
  end