cfn-guardian 0.4.0 → 0.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) 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 +4 -820
  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 +84 -66
  29. data/lib/cfnguardian/cloudwatch.rb +43 -32
  30. data/lib/cfnguardian/codecommit.rb +11 -2
  31. data/lib/cfnguardian/compile.rb +86 -5
  32. data/lib/cfnguardian/config/defaults.yaml +9 -0
  33. data/lib/cfnguardian/deploy.rb +2 -16
  34. data/lib/cfnguardian/display_formatter.rb +1 -2
  35. data/lib/cfnguardian/error.rb +4 -0
  36. data/lib/cfnguardian/models/alarm.rb +99 -29
  37. data/lib/cfnguardian/models/check.rb +30 -12
  38. data/lib/cfnguardian/models/event.rb +43 -15
  39. data/lib/cfnguardian/models/event_subscription.rb +111 -0
  40. data/lib/cfnguardian/resources/amazonmq_rabbitmq.rb +136 -0
  41. data/lib/cfnguardian/resources/azure_file.rb +20 -0
  42. data/lib/cfnguardian/resources/base.rb +111 -26
  43. data/lib/cfnguardian/resources/batch.rb +14 -0
  44. data/lib/cfnguardian/resources/ec2_instance.rb +11 -0
  45. data/lib/cfnguardian/resources/glue.rb +23 -0
  46. data/lib/cfnguardian/resources/http.rb +1 -0
  47. data/lib/cfnguardian/resources/rds_cluster.rb +14 -0
  48. data/lib/cfnguardian/resources/rds_instance.rb +80 -0
  49. data/lib/cfnguardian/resources/redshift_cluster.rb +2 -2
  50. data/lib/cfnguardian/resources/step_functions.rb +41 -0
  51. data/lib/cfnguardian/stacks/main.rb +7 -6
  52. data/lib/cfnguardian/stacks/resources.rb +34 -5
  53. data/lib/cfnguardian/version.rb +1 -1
  54. metadata +39 -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}"
@@ -19,9 +19,18 @@ module CfnGuardian
19
19
  return resp.branch.commit_id
20
20
  end
21
21
 
22
- def get_commit_history(branch='master',count=10)
22
+ def get_commit_history(branch,count)
23
23
  history = []
24
- commit = get_last_commit(branch)
24
+
25
+ begin
26
+ commit = get_last_commit(branch)
27
+ rescue Aws::CodeCommit::Errors::BranchDoesNotExistException => e
28
+ logger.error "Branch #{branch} does not exist in the #{@repo_name} repository"
29
+ return []
30
+ rescue Aws::CodeCommit::Errors::RepositoryDoesNotExistException => e
31
+ logger.error "Respository #{@repo_name} does not exist in this AWS account or region"
32
+ return []
33
+ end
25
34
 
26
35
  count.times do
27
36
 
@@ -35,6 +35,13 @@ 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/resources/amazonmq_rabbitmq'
40
+ require 'cfnguardian/resources/batch'
41
+ require 'cfnguardian/resources/glue'
42
+ require 'cfnguardian/resources/step_functions'
43
+ require 'cfnguardian/version'
44
+ require 'cfnguardian/error'
38
45
 
39
46
  module CfnGuardian
40
47
  class Compile
@@ -50,9 +57,10 @@ module CfnGuardian
50
57
  @templates = config.fetch('Templates',{})
51
58
  @topics = config.fetch('Topics',{})
52
59
  @maintenance_groups = config.fetch('MaintenaceGroups', {})
60
+ @event_subscriptions = config.fetch('EventSubscriptions', {})
53
61
 
54
62
  # Make sure the default topics exist if they aren't supplied in the alarms.yaml
55
- %w(Critical Warning Task Informational).each do |topic|
63
+ %w(Critical Warning Task Informational Events).each do |topic|
56
64
  @topics[topic] = '' unless @topics.has_key?(topic)
57
65
  end
58
66
 
@@ -86,10 +94,15 @@ module CfnGuardian
86
94
  end
87
95
  end
88
96
 
89
- overides = @templates.has_key?(group) ? @templates[group] : {}
90
- @resources.concat resource_class.get_alarms(resource,group,overides)
97
+ template_overides = @templates.has_key?(group) ? @templates[group] : {}
98
+ @resources.concat resource_class.get_alarms(group,template_overides)
99
+
91
100
  @resources.concat resource_class.get_metric_filters()
92
101
  @resources.concat resource_class.get_events()
102
+
103
+ event_subscriptions = @event_subscriptions.has_key?(group) ? @event_subscriptions[group] : {}
104
+ @resources.concat resource_class.get_event_subscriptions(group,event_subscriptions)
105
+
93
106
  @checks.concat resource_class.get_checks()
94
107
 
95
108
  @cost += resource_class.get_cost
@@ -100,13 +113,16 @@ module CfnGuardian
100
113
  resource_groups.each do |group, alarms|
101
114
  alarms.each do |alarm, resources|
102
115
  resources.each do |resource|
116
+
103
117
  res = @resources.find {|r|
104
118
  (r.type == 'Alarm') &&
105
- (r.class == group && r.name == alarm) &&
119
+ (r.group == group && r.name == alarm) &&
106
120
  (r.resource_id == resource['Id'] || r.resource_name == resource['Name'])}
121
+
107
122
  unless res.nil?
108
123
  res.maintenance_groups.append("#{maintenance_group}MaintenanceGroup")
109
124
  end
125
+
110
126
  end
111
127
  end
112
128
  end
@@ -118,11 +134,39 @@ module CfnGuardian
118
134
  end
119
135
 
120
136
  @ssm_parameters = @resources.select {|resource| resource.type == 'Event'}.map {|event| event.ssm_parameters}.flatten.uniq
137
+
138
+ validate_resources()
121
139
  end
122
140
 
123
141
  def alarms
124
142
  @resources.select {|resource| resource.type == 'Alarm'}
125
143
  end
144
+
145
+ def validate_resources()
146
+ errors = []
147
+ @resources.each do |resource|
148
+ case resource.type
149
+ when 'Alarm'
150
+ %w(metric_name namespace).each do |property|
151
+ if resource.send(property).nil?
152
+ errors << "Alarm #{resource.name} for resource #{resource.resource_id} has nil value for property #{property.to_camelcase}"
153
+ end
154
+ end
155
+ when 'Check'
156
+ # no validation check yet
157
+ when 'Event'
158
+ # no validation check yet
159
+ when 'Composite'
160
+ # no validation check yet
161
+ when 'EventSubscription'
162
+ # no validation check yet
163
+ when 'MetricFilter'
164
+ # no validation check yet
165
+ end
166
+ end
167
+
168
+ raise CfnGuardian::ValidationError, "#{errors.size} errors found\n[*] #{errors.join("\n[*] ")}" if errors.any?
169
+ end
126
170
 
127
171
  def split_resources(bucket,path)
128
172
  split = @resources.each_slice(200).to_a
@@ -147,7 +191,7 @@ module CfnGuardian
147
191
  File.write("out/guardian.compiled.yaml", JSON.parse(valid.to_json).to_yaml)
148
192
 
149
193
  resources.each_with_index do |resources,index|
150
- stack = CfnGuardian::Stacks::Resources.new(main_stack.parameters)
194
+ stack = CfnGuardian::Stacks::Resources.new(main_stack.parameters,index)
151
195
  stack.build_template(resources)
152
196
  valid = stack.template.validate
153
197
  File.write("out/guardian-stack-#{index}.compiled.yaml", JSON.parse(valid.to_json).to_yaml)
@@ -157,6 +201,43 @@ module CfnGuardian
157
201
  def clean_out_directory
158
202
  Dir["out/*.yaml"].each {|file| File.delete(file)}
159
203
  end
204
+
205
+ def load_parameters(options)
206
+ parameters = {}
207
+ # Load sns topic parameters in order of preference
208
+ @topics.each do |key, value|
209
+ # if parameter is passed in as a command line option
210
+ if options.has_key?("sns_#{key.downcase}")
211
+ parameters[key.to_sym] = options["sns_#{key.downcase}"]
212
+ # if parameter is in config
213
+ elsif !value.empty?
214
+ parameters[key.to_sym] = value
215
+ # if parameter is set as environment variable
216
+ elsif ENV.has_key?("GUARDIAN_TOPIC_#{key.upcase}")
217
+ parameters[key.to_sym] = ENV["GUARDIAN_TOPIC_#{key.upcase}"]
218
+ end
219
+ end
220
+
221
+ return parameters
222
+ end
223
+
224
+ def genrate_template_config(parameters)
225
+ template = {
226
+ Tags: {
227
+ 'guardian:version': CfnGuardian::VERSION
228
+ }
229
+ }
230
+
231
+ if ENV.has_key?('CODEBUILD_RESOLVED_SOURCE_VERSION')
232
+ template[:Tags][:'guardian:config:commit'] = ENV['CODEBUILD_RESOLVED_SOURCE_VERSION']
233
+ end
234
+
235
+ unless parameters.empty?
236
+ template[:Parameters] = parameters
237
+ end
238
+
239
+ File.write("out/template-config.guardian.json", template.to_json)
240
+ end
160
241
 
161
242
  end
162
243
  end
@@ -1,6 +1,15 @@
1
1
  Resources:
2
2
  AmazonMQBroker:
3
3
  - Id: Default
4
+ AmazonMQRabbitMQBroker:
5
+ - Id: Default
6
+ AmazonMQRabbitMQNode:
7
+ - Id: Default
8
+ Node: Default
9
+ AmazonMQRabbitMQQueue:
10
+ - Id: Default
11
+ Queue: Default
12
+ Vhost: Default
4
13
  ApiGateway:
5
14
  - Id: Default
6
15
  ApplicationTargetGroup:
@@ -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'
@@ -94,8 +94,42 @@ module CfnGuardian
94
94
  @dimensions = { Broker: resource['Id'] }
95
95
  end
96
96
  end
97
+
98
+ class AmazonMQRabbitMQBrokerAlarm < BaseAlarm
99
+ def initialize(resource)
100
+ super(resource)
101
+ @group = 'AmazonMQRabbitMQBroker'
102
+ @namespace = 'AWS/AmazonMQ'
103
+ @dimensions = { Broker: resource['Id'] }
104
+ end
105
+ end
106
+
107
+ class AmazonMQRabbitMQNodeAlarm < BaseAlarm
108
+ def initialize(resource)
109
+ super(resource)
110
+ @group = 'AmazonMQRabbitMQNode'
111
+ @namespace = 'AWS/AmazonMQ'
112
+ @dimensions = {
113
+ Broker: resource['Id'],
114
+ Node: resource['Node']
115
+ }
116
+ end
117
+ end
118
+
119
+ class AmazonMQRabbitMQQueueAlarm < BaseAlarm
120
+ def initialize(resource)
121
+ super(resource)
122
+ @group = 'AmazonMQRabbitMQQueue'
123
+ @namespace = 'AWS/AmazonMQ'
124
+ @dimensions = {
125
+ Broker: resource['Id'],
126
+ Queue: resource['Queue'],
127
+ VirtualHost: resource['Vhost']
128
+ }
129
+ end
130
+ end
97
131
 
98
- class CloudFrontDistributionAlarm < Alarm
132
+ class CloudFrontDistributionAlarm < BaseAlarm
99
133
  def initialize(resource)
100
134
  super(resource)
101
135
  @group = 'CloudFrontDistribution'
@@ -109,7 +143,7 @@ module CfnGuardian
109
143
  end
110
144
  end
111
145
 
112
- class AutoScalingGroupAlarm < Alarm
146
+ class AutoScalingGroupAlarm < BaseAlarm
113
147
  def initialize(resource)
114
148
  super(resource)
115
149
  @group = 'AutoScalingGroup'
@@ -118,7 +152,7 @@ module CfnGuardian
118
152
  end
119
153
  end
120
154
 
121
- class DomainExpiryAlarm < Alarm
155
+ class DomainExpiryAlarm < BaseAlarm
122
156
  def initialize(resource)
123
157
  super(resource)
124
158
  @group = 'DomainExpiry'
@@ -128,7 +162,7 @@ module CfnGuardian
128
162
  end
129
163
  end
130
164
 
131
- class DynamoDBTableAlarm < Alarm
165
+ class DynamoDBTableAlarm < BaseAlarm
132
166
  def initialize(resource)
133
167
  super(resource)
134
168
  @group = 'DynamoDBTable'
@@ -137,7 +171,7 @@ module CfnGuardian
137
171
  end
138
172
  end
139
173
 
140
- class Ec2InstanceAlarm < Alarm
174
+ class Ec2InstanceAlarm < BaseAlarm
141
175
  def initialize(resource)
142
176
  super(resource)
143
177
  @group = 'Ec2Instance'
@@ -146,7 +180,7 @@ module CfnGuardian
146
180
  end
147
181
  end
148
182
 
149
- class ECSClusterAlarm < Alarm
183
+ class ECSClusterAlarm < BaseAlarm
150
184
  def initialize(resource)
151
185
  super(resource)
152
186
  @group = 'ECSCluster'
@@ -158,7 +192,7 @@ module CfnGuardian
158
192
  end
159
193
  end
160
194
 
161
- class ECSServiceAlarm < Alarm
195
+ class ECSServiceAlarm < BaseAlarm
162
196
  def initialize(resource)
163
197
  super(resource)
164
198
  @group = 'ECSService'
@@ -170,7 +204,7 @@ module CfnGuardian
170
204
  end
171
205
  end
172
206
 
173
- class ElastiCacheReplicationGroupAlarm < Alarm
207
+ class ElastiCacheReplicationGroupAlarm < BaseAlarm
174
208
  def initialize(resource)
175
209
  super(resource)
176
210
  @group = 'ElastiCacheReplicationGroup'
@@ -179,7 +213,7 @@ module CfnGuardian
179
213
  end
180
214
  end
181
215
 
182
- class ElasticLoadBalancerAlarm < Alarm
216
+ class ElasticLoadBalancerAlarm < BaseAlarm
183
217
  def initialize(resource)
184
218
  super(resource)
185
219
  @group = 'ElasticLoadBalancer'
@@ -188,7 +222,7 @@ module CfnGuardian
188
222
  end
189
223
  end
190
224
 
191
- class ElasticFileSystemAlarm < Alarm
225
+ class ElasticFileSystemAlarm < BaseAlarm
192
226
  def initialize(resource)
193
227
  super(resource)
194
228
  @group = 'ElasticFileSystem'
@@ -197,7 +231,7 @@ module CfnGuardian
197
231
  end
198
232
  end
199
233
 
200
- class HttpAlarm < Alarm
234
+ class HttpAlarm < BaseAlarm
201
235
  def initialize(resource)
202
236
  super(resource)
203
237
  @group = 'Http'
@@ -215,7 +249,7 @@ module CfnGuardian
215
249
  end
216
250
  end
217
251
 
218
- class PortAlarm < Alarm
252
+ class PortAlarm < BaseAlarm
219
253
  def initialize(resource)
220
254
  super(resource)
221
255
  @group = 'Port'
@@ -233,7 +267,7 @@ module CfnGuardian
233
267
  end
234
268
  end
235
269
 
236
- class SslAlarm < Alarm
270
+ class SslAlarm < BaseAlarm
237
271
  def initialize(resource)
238
272
  super(resource)
239
273
  @group = 'Ssl'
@@ -249,7 +283,7 @@ module CfnGuardian
249
283
  end
250
284
  end
251
285
 
252
- class NrpeAlarm < Alarm
286
+ class NrpeAlarm < BaseAlarm
253
287
  def initialize(resource,environment)
254
288
  super(resource)
255
289
  @group = 'Nrpe'
@@ -260,7 +294,7 @@ module CfnGuardian
260
294
  end
261
295
  end
262
296
 
263
- class LambdaAlarm < Alarm
297
+ class LambdaAlarm < BaseAlarm
264
298
  def initialize(resource)
265
299
  super(resource)
266
300
  @group = 'Lambda'
@@ -271,7 +305,7 @@ module CfnGuardian
271
305
  end
272
306
  end
273
307
 
274
- class NetworkTargetGroupAlarm < Alarm
308
+ class NetworkTargetGroupAlarm < BaseAlarm
275
309
  def initialize(resource)
276
310
  super(resource)
277
311
  @group = 'NetworkTargetGroup'
@@ -283,7 +317,7 @@ module CfnGuardian
283
317
  end
284
318
  end
285
319
 
286
- class RedshiftClusterAlarm < Alarm
320
+ class RedshiftClusterAlarm < BaseAlarm
287
321
  def initialize(resource)
288
322
  super(resource)
289
323
  @group = 'RedshiftCluster'
@@ -292,7 +326,7 @@ module CfnGuardian
292
326
  end
293
327
  end
294
328
 
295
- class RDSClusterInstanceAlarm < Alarm
329
+ class RDSClusterInstanceAlarm < BaseAlarm
296
330
  def initialize(resource)
297
331
  super(resource)
298
332
  @group = 'RDSClusterInstance'
@@ -301,7 +335,7 @@ module CfnGuardian
301
335
  end
302
336
  end
303
337
 
304
- class RDSInstanceAlarm < Alarm
338
+ class RDSInstanceAlarm < BaseAlarm
305
339
  def initialize(resource)
306
340
  super(resource)
307
341
  @group = 'RDSInstance'
@@ -309,8 +343,32 @@ module CfnGuardian
309
343
  @dimensions = { DBInstanceIdentifier: resource['Id'] }
310
344
  end
311
345
  end
312
-
313
- class SqlAlarm < Alarm
346
+
347
+ class StepFunctionsAlarm < BaseAlarm
348
+ def initialize(resource)
349
+ super(resource)
350
+ @group = 'StepFunctions'
351
+ @namespace = 'AWS/States'
352
+ @dimensions = { StateMachineArn: { "Fn::Sub" => "arn:aws:states:${AWS::Region}:${AWS::AccountId}:stateMachine:#{resource['Id']}"} }
353
+ end
354
+ end
355
+
356
+ class BatchAlarm < BaseAlarm
357
+ def initialize(resource)
358
+ super(resource)
359
+ @group = 'Batch'
360
+ end
361
+ end
362
+
363
+ class GlueAlarm < BaseAlarm
364
+ def initialize(resource)
365
+ super(resource)
366
+ @group = 'Batch'
367
+ @namespace = 'Glue'
368
+ end
369
+ end
370
+
371
+ class SqlAlarm < BaseAlarm
314
372
  def initialize(resource)
315
373
  super(resource)
316
374
  @group = 'Sql'
@@ -321,7 +379,7 @@ module CfnGuardian
321
379
  end
322
380
  end
323
381
 
324
- class SQSQueueAlarm < Alarm
382
+ class SQSQueueAlarm < BaseAlarm
325
383
  def initialize(resource)
326
384
  super(resource)
327
385
  @group = 'SQSQueue'
@@ -332,7 +390,7 @@ module CfnGuardian
332
390
  end
333
391
  end
334
392
 
335
- class LogGroupAlarm < Alarm
393
+ class LogGroupAlarm < BaseAlarm
336
394
  def initialize(resource)
337
395
  super(resource)
338
396
  @group = 'LogGroup'
@@ -344,7 +402,7 @@ module CfnGuardian
344
402
  end
345
403
  end
346
404
 
347
- class SFTPAlarm < Alarm
405
+ class SFTPAlarm < BaseAlarm
348
406
  def initialize(resource)
349
407
  super(resource)
350
408
  @group = 'SFTP'
@@ -362,7 +420,7 @@ module CfnGuardian
362
420
  end
363
421
  end
364
422
 
365
- class TLSAlarm < Alarm
423
+ class TLSAlarm < BaseAlarm
366
424
  def initialize(resource)
367
425
  super(resource)
368
426
  @group = 'TLS'
@@ -375,6 +433,18 @@ module CfnGuardian
375
433
  @evaluation_periods = 1
376
434
  end
377
435
  end
436
+
437
+ class AzureFileAlarm < BaseAlarm
438
+ def initialize(resource)
439
+ super(resource)
440
+ @group = 'AzureFile'
441
+ @namespace = 'FileAgeCheck'
442
+ @period = 300
443
+ @comparison_operator = 'GreaterThanThreshold'
444
+ @threshold = 0
445
+ @dimensions = { StorageAccount: resource['Id'], StorageContainer: resource['Container'] }
446
+ end
447
+ end
378
448
 
379
449
  end
380
450
  end