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
@@ -2,7 +2,7 @@ require 'cfnguardian/string'
2
2
 
3
3
  module CfnGuardian
4
4
  module Models
5
- class Check
5
+ class BaseCheck
6
6
 
7
7
  attr_reader :type
8
8
  attr_accessor :group,
@@ -13,7 +13,9 @@ module CfnGuardian
13
13
  :runtime,
14
14
  :environment,
15
15
  :subnets,
16
- :vpc
16
+ :vpc,
17
+ :memory,
18
+ :timeout
17
19
 
18
20
  def initialize(resource)
19
21
  @type = 'Check'
@@ -26,17 +28,19 @@ module CfnGuardian
26
28
  @environment = ''
27
29
  @subnets = nil
28
30
  @vpc = nil
31
+ @memory = 128
32
+ @timeout = 120
29
33
  end
30
34
  end
31
35
 
32
- class HttpCheck < Check
36
+ class HttpCheck < BaseCheck
33
37
  def initialize(resource)
34
38
  super(resource)
35
39
  @group = 'Http'
36
40
  @name = 'HttpCheck'
37
41
  @package = 'http-check'
38
42
  @handler = 'handler.http_check'
39
- @version = '0bc33e51abb1f27729ecb170611bf6b440e71a0e'
43
+ @version = 'f739631de74f1a882163b7e584a8b4710ccbc134'
40
44
  @runtime = 'python3.7'
41
45
  end
42
46
  end
@@ -52,7 +56,7 @@ module CfnGuardian
52
56
  end
53
57
  end
54
58
 
55
- class PortCheck < Check
59
+ class PortCheck < BaseCheck
56
60
  def initialize(resource)
57
61
  super(resource)
58
62
  @group = 'Port'
@@ -75,7 +79,7 @@ module CfnGuardian
75
79
  end
76
80
  end
77
81
 
78
- class NrpeCheck < Check
82
+ class NrpeCheck < BaseCheck
79
83
  def initialize(resource)
80
84
  super(resource)
81
85
  @group = 'Nrpe'
@@ -90,7 +94,7 @@ module CfnGuardian
90
94
  end
91
95
  end
92
96
 
93
- class SslCheck < Check
97
+ class SslCheck < BaseCheck
94
98
  def initialize(resource)
95
99
  super(resource)
96
100
  @group = 'Ssl'
@@ -113,7 +117,7 @@ module CfnGuardian
113
117
  end
114
118
  end
115
119
 
116
- class DomainExpiryCheck < Check
120
+ class DomainExpiryCheck < BaseCheck
117
121
  def initialize(resource)
118
122
  super(resource)
119
123
  @group = 'DomainExpiry'
@@ -125,7 +129,7 @@ module CfnGuardian
125
129
  end
126
130
  end
127
131
 
128
- class SqlCheck < Check
132
+ class SqlCheck < BaseCheck
129
133
  def initialize(resource)
130
134
  super(resource)
131
135
  @group = 'Sql'
@@ -140,7 +144,7 @@ module CfnGuardian
140
144
  end
141
145
  end
142
146
 
143
- class ContainerInstanceCheck < Check
147
+ class ContainerInstanceCheck < BaseCheck
144
148
  def initialize(resource)
145
149
  super(resource)
146
150
  @group = 'ContainerInstance'
@@ -152,7 +156,7 @@ module CfnGuardian
152
156
  end
153
157
  end
154
158
 
155
- class TLSCheck < Check
159
+ class TLSCheck < BaseCheck
156
160
  def initialize(resource)
157
161
  super(resource)
158
162
  @group = 'TLS'
@@ -164,7 +168,7 @@ module CfnGuardian
164
168
  end
165
169
  end
166
170
 
167
- class SFTPCheck < Check
171
+ class SFTPCheck < BaseCheck
168
172
  def initialize(resource)
169
173
  super(resource)
170
174
  @group = 'SFTP'
@@ -187,5 +191,19 @@ module CfnGuardian
187
191
  end
188
192
  end
189
193
 
194
+ class AzureFileCheck < BaseCheck
195
+ def initialize(resource)
196
+ super(resource)
197
+ @group = 'AzureFile'
198
+ @name = 'AzureFileCheck'
199
+ @package = 'azure-file-check'
200
+ @handler = 'handler.file_check'
201
+ @version = 'cc37aa8fe4855570132431611b507274b390f4c1'
202
+ @runtime = 'python3.7'
203
+ @memory = 256
204
+ @timeout = 600
205
+ end
206
+ end
207
+
190
208
  end
191
209
  end
@@ -2,7 +2,7 @@ require 'cfnguardian/string'
2
2
 
3
3
  module CfnGuardian
4
4
  module Models
5
- class Event
5
+ class BaseEvent
6
6
 
7
7
  attr_reader :type
8
8
  attr_accessor :group,
@@ -31,7 +31,7 @@ module CfnGuardian
31
31
  end
32
32
  end
33
33
 
34
- class HttpEvent < Event
34
+ class HttpEvent < BaseEvent
35
35
 
36
36
  attr_accessor :endpoint,
37
37
  :method,
@@ -81,7 +81,7 @@ module CfnGuardian
81
81
  end
82
82
  end
83
83
 
84
- class PortEvent < Event
84
+ class PortEvent < BaseEvent
85
85
  def initialize(resource)
86
86
  super(resource)
87
87
  @group = 'Port'
@@ -112,7 +112,7 @@ module CfnGuardian
112
112
  end
113
113
  end
114
114
 
115
- class NrpeEvent < Event
115
+ class NrpeEvent < BaseEvent
116
116
  def initialize(resource,environment,command)
117
117
  super(resource)
118
118
  @group = 'Nrpe'
@@ -121,6 +121,7 @@ module CfnGuardian
121
121
  @host = resource['Id']
122
122
  @environment = environment
123
123
  @region = resource.fetch('Region',"${AWS::Region}")
124
+ @hash = Digest::MD5.hexdigest "#{resource['Id']}#{command}"
124
125
  @command = command
125
126
  end
126
127
 
@@ -134,13 +135,13 @@ module CfnGuardian
134
135
  end
135
136
  end
136
137
 
137
- class SslEvent < Event
138
+ class SslEvent < BaseEvent
138
139
  def initialize(resource)
139
140
  super(resource)
140
141
  @group = 'Ssl'
141
142
  @name = 'SslEvent'
142
143
  @target = 'SslCheckFunction'
143
- @cron = "0 12 * * ? *"
144
+ @cron = resource.fetch('Schedule', "0 12 * * ? *")
144
145
  @url = resource['Id']
145
146
  @region = resource.fetch('Region',"${AWS::Region}")
146
147
  end
@@ -163,7 +164,7 @@ module CfnGuardian
163
164
  end
164
165
  end
165
166
 
166
- class DomainExpiryEvent < Event
167
+ class DomainExpiryEvent < BaseEvent
167
168
 
168
169
  attr_accessor :domain,
169
170
  :region
@@ -173,7 +174,7 @@ module CfnGuardian
173
174
  @group = 'DomainExpiry'
174
175
  @name = 'DomainExpiryEvent'
175
176
  @target = 'DomainExpiryCheckFunction'
176
- @cron = "0 12 * * ? *"
177
+ @cron = resource.fetch('Schedule', "0 12 * * ? *")
177
178
  @domain = resource['Id']
178
179
  @region = resource.fetch('Region',"${AWS::Region}")
179
180
  end
@@ -183,7 +184,7 @@ module CfnGuardian
183
184
  end
184
185
  end
185
186
 
186
- class SqlEvent < Event
187
+ class SqlEvent < BaseEvent
187
188
  def initialize(resource,query,environment)
188
189
  super(resource)
189
190
  @group = 'Sql'
@@ -221,13 +222,13 @@ module CfnGuardian
221
222
  end
222
223
  end
223
224
 
224
- class ContainerInstanceEvent < Event
225
+ class ContainerInstanceEvent < BaseEvent
225
226
  def initialize(resource)
226
227
  super(resource)
227
228
  @group = 'ContainerInstance'
228
229
  @name = 'ContainerInstanceEvent'
229
230
  @target = 'ContainerInstanceCheckFunction'
230
- @cron = "0/5 * * * ? *"
231
+ @cron = resource.fetch('Schedule', "0/5 * * * ? *")
231
232
  @cluster = resource['Id']
232
233
  end
233
234
 
@@ -236,13 +237,13 @@ module CfnGuardian
236
237
  end
237
238
  end
238
239
 
239
- class SFTPEvent < Event
240
+ class SFTPEvent < BaseEvent
240
241
  def initialize(resource)
241
242
  super(resource)
242
243
  @group = 'SFTP'
243
244
  @name = 'SFTPEvent'
244
245
  @target = 'SFTPCheckFunction'
245
- @cron = "0/5 * * * ? *"
246
+ @cron = resource.fetch('Schedule', "0/5 * * * ? *")
246
247
  @host = resource['Id']
247
248
  @user = resource['User']
248
249
  @port = resource.fetch('Port', nil)
@@ -288,13 +289,13 @@ module CfnGuardian
288
289
  end
289
290
  end
290
291
 
291
- class TLSEvent < Event
292
+ class TLSEvent < BaseEvent
292
293
  def initialize(resource)
293
294
  super(resource)
294
295
  @group = 'TLS'
295
296
  @name = 'TLSEvent'
296
297
  @target = 'TLSCheckFunction'
297
- @cron = "0/5 * * * ? *"
298
+ @cron = resource.fetch('Schedule', "0/5 * * * ? *")
298
299
  @host = resource['Id']
299
300
  @port = resource.fetch('Port', 443)
300
301
  @check_max = resource.fetch('MaxSupported', nil)
@@ -312,5 +313,32 @@ module CfnGuardian
312
313
  end
313
314
  end
314
315
 
316
+ class AzureFileEvent < BaseEvent
317
+ def initialize(resource)
318
+ super(resource)
319
+ @group = 'AzureFile'
320
+ @name = 'AzureFileEvent'
321
+ @target = 'AzureFileCheckFunction'
322
+ @cron = resource.fetch('Schedule', "0/5 * * * ? *")
323
+ @storage_account = resource['Id']
324
+ @container = resource['Container']
325
+ @connection_string = resource['ConnectionString']
326
+ @search = resource['Search']
327
+ end
328
+
329
+ def payload
330
+ return {
331
+ 'STORAGE_ACCOUNT' => @storage_account,
332
+ 'CONTAINER' => @container,
333
+ 'CONNECTION_STRING' => @connection_string,
334
+ 'SEARCH' => @search
335
+ }.to_json
336
+ end
337
+
338
+ def ssm_parameters
339
+ return [@connection_string]
340
+ end
341
+ end
342
+
315
343
  end
316
344
  end
@@ -0,0 +1,111 @@
1
+ module CfnGuardian
2
+ module Models
3
+ class BaseEventSubscription
4
+
5
+ attr_reader :type, :group
6
+ attr_writer :detail
7
+ attr_accessor :name,
8
+ :enabled,
9
+ :hash,
10
+ :topic,
11
+ :resource_id,
12
+ :resource_arn,
13
+ :source,
14
+ :detail_type,
15
+ :detail
16
+
17
+ def initialize(resource)
18
+ @type = 'EventSubscription'
19
+ @group = self.class.name.split('::').last
20
+ @name = ''
21
+ @hash = Digest::MD5.hexdigest resource['Id']
22
+ @enabled = true
23
+ @events = []
24
+ @topic = 'Events'
25
+ @resource_id = resource['Id']
26
+ @resource_arn = ''
27
+ @source = ''
28
+ @detail_type = ''
29
+ @detail = {}
30
+ end
31
+
32
+ def detail
33
+ return @detail
34
+ end
35
+ end
36
+
37
+ class RDSEventSubscription < BaseEventSubscription
38
+ attr_accessor :source_id, :rds_event_category, :message
39
+
40
+ def initialize(resource)
41
+ super(resource)
42
+ @source = 'aws.rds'
43
+ @detail_type = 'RDS DB Instance Event'
44
+ @source_id = ''
45
+ @rds_event_category = ''
46
+ @message = ''
47
+ end
48
+
49
+ def detail
50
+ return {
51
+ EventCategories: [@rds_event_category],
52
+ SourceType: [@source_type],
53
+ SourceIdentifier: ["rds:#{@resource_id}"],
54
+ Message: [@message]
55
+ }
56
+ end
57
+ end
58
+
59
+ class RDSInstanceEventSubscription < RDSEventSubscription
60
+ def initialize(resource)
61
+ super(resource)
62
+ @source_type = 'DB_INSTANCE'
63
+ end
64
+ end
65
+
66
+ class RDSClusterEventSubscription < RDSEventSubscription
67
+ def initialize(resource)
68
+ super(resource)
69
+ @source_type = 'DB_CLUSTER'
70
+ end
71
+ end
72
+
73
+ class Ec2InstanceEventSubscription < BaseEventSubscription
74
+ def initialize(resource)
75
+ super(resource)
76
+ @source = 'aws.ec2'
77
+ end
78
+ end
79
+
80
+ class BatchEventSubscription < BaseEventSubscription
81
+ def initialize(resource)
82
+ super(resource)
83
+ @source = 'aws.batch'
84
+ end
85
+ end
86
+
87
+ class GlueEventSubscription < BaseEventSubscription
88
+ def initialize(resource)
89
+ super(resource)
90
+ @source = 'aws.glue'
91
+ end
92
+ end
93
+
94
+ class ApiGatewayEventSubscription < BaseEventSubscription; end
95
+ class ApplicationTargetGroupEventSubscription < BaseEventSubscription; end
96
+ class AmazonMQBrokerEventSubscription < BaseEventSubscription; end
97
+ class CloudFrontDistributionEventSubscription < BaseEventSubscription; end
98
+ class AutoScalingGroupEventSubscription < BaseEventSubscription; end
99
+ class DynamoDBTableEventSubscription < BaseEventSubscription; end
100
+ class Ec2InstanceEventSubscription < BaseEventSubscription; end
101
+ class ECSClusterEventSubscription < BaseEventSubscription; end
102
+ class ECSServiceEventSubscription < BaseEventSubscription; end
103
+ class ElastiCacheReplicationGroupEventSubscription < BaseEventSubscription; end
104
+ class ElasticLoadBalancerEventSubscription < BaseEventSubscription; end
105
+ class ElasticFileSystemEventSubscription < BaseEventSubscription; end
106
+ class LambdaEventSubscription < BaseEventSubscription; end
107
+ class NetworkTargetGroupEventSubscription < BaseEventSubscription; end
108
+ class RedshiftClusterEventSubscription < BaseEventSubscription; end
109
+ class StepFunctionsSubscription < BaseEventSubscription; end
110
+ end
111
+ end
@@ -0,0 +1,136 @@
1
+ module CfnGuardian::Resource
2
+ class AmazonMQRabbitMQBroker < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::AmazonMQRabbitMQBrokerAlarm.new(@resource)
6
+ alarm.name = 'ConnectionCountCritical'
7
+ alarm.metric_name = 'ConnectionCount'
8
+ alarm.comparison_operator = 'GreaterThanThreshold'
9
+ alarm.statistic = 'Maximum'
10
+ alarm.threshold = 50
11
+ alarm.evaluation_periods = 5
12
+ alarm.treat_missing_data = 'notBreaching'
13
+ @alarms.push(alarm)
14
+
15
+ alarm = CfnGuardian::Models::AmazonMQRabbitMQBrokerAlarm.new(@resource)
16
+ alarm.name = 'ConnectionCountWarn'
17
+ alarm.metric_name = 'ConnectionCount'
18
+ alarm.comparison_operator = 'GreaterThanThreshold'
19
+ alarm.statistic = 'Maximum'
20
+ alarm.threshold = 25
21
+ alarm.evaluation_periods = 5
22
+ alarm.treat_missing_data = 'notBreaching'
23
+ alarm.alarm_action = 'Warning'
24
+ @alarms.push(alarm)
25
+
26
+ alarm = CfnGuardian::Models::AmazonMQRabbitMQBrokerAlarm.new(@resource)
27
+ alarm.name = 'MessageCountCritical'
28
+ alarm.metric_name = 'MessageCount'
29
+ alarm.comparison_operator = 'GreaterThanThreshold'
30
+ alarm.statistic = 'Maximum'
31
+ alarm.threshold = 500
32
+ alarm.evaluation_periods = 5
33
+ alarm.treat_missing_data = 'notBreaching'
34
+ @alarms.push(alarm)
35
+
36
+ alarm = CfnGuardian::Models::AmazonMQRabbitMQBrokerAlarm.new(@resource)
37
+ alarm.name = 'MessageCountWarn'
38
+ alarm.metric_name = 'MessageCount'
39
+ alarm.comparison_operator = 'GreaterThanThreshold'
40
+ alarm.statistic = 'Maximum'
41
+ alarm.threshold = 250
42
+ alarm.evaluation_periods = 5
43
+ alarm.treat_missing_data = 'notBreaching'
44
+ alarm.alarm_action = 'Warning'
45
+ @alarms.push(alarm)
46
+
47
+ end
48
+ end
49
+
50
+ class AmazonMQRabbitMQQueue < Base
51
+
52
+ def default_alarms
53
+
54
+ alarm = CfnGuardian::Models::AmazonMQRabbitMQQueueAlarm.new(@resource)
55
+ alarm.name = 'MessageCountHighWarn'
56
+ alarm.metric_name = 'MessageCount'
57
+ alarm.comparison_operator = 'GreaterThanThreshold'
58
+ alarm.statistic = 'Maximum'
59
+ alarm.threshold = 100
60
+ alarm.evaluation_periods = 5
61
+ alarm.treat_missing_data = 'notBreaching'
62
+ alarm.alarm_action = 'Warning'
63
+ @alarms.push(alarm)
64
+
65
+ end
66
+ end
67
+
68
+ class AmazonMQRabbitMQNode < Base
69
+
70
+ def default_alarms
71
+ alarm = CfnGuardian::Models::AmazonMQRabbitMQNodeAlarm.new(@resource)
72
+ alarm.name = 'SystemCpuUtilizationCritical'
73
+ alarm.metric_name = 'SystemCpuUtilization'
74
+ alarm.comparison_operator = 'GreaterThanThreshold'
75
+ alarm.statistic = 'Maximum'
76
+ alarm.threshold = 95
77
+ alarm.evaluation_periods = 10
78
+ alarm.treat_missing_data = 'notBreaching'
79
+ @alarms.push(alarm)
80
+
81
+ alarm = CfnGuardian::Models::AmazonMQRabbitMQNodeAlarm.new(@resource)
82
+ alarm.name = 'SystemCpuUtilizationHighBase'
83
+ alarm.metric_name = 'SystemCpuUtilization'
84
+ alarm.comparison_operator = 'GreaterThanThreshold'
85
+ alarm.statistic = 'Maximum'
86
+ alarm.threshold = 75
87
+ alarm.evaluation_periods = 30
88
+ alarm.treat_missing_data = 'notBreaching'
89
+ alarm.alarm_action = 'Warning'
90
+ @alarms.push(alarm)
91
+
92
+ alarm = CfnGuardian::Models::AmazonMQRabbitMQNodeAlarm.new(@resource)
93
+ alarm.name = 'RabbitMQMemUsedCritical'
94
+ alarm.metric_name = 'RabbitMQMemUsed'
95
+ alarm.comparison_operator = 'GreaterThanThreshold'
96
+ alarm.statistic = 'Maximum'
97
+ alarm.threshold = 390000000
98
+ alarm.evaluation_periods = 5
99
+ alarm.treat_missing_data = 'notBreaching'
100
+ @alarms.push(alarm)
101
+
102
+ alarm = CfnGuardian::Models::AmazonMQRabbitMQNodeAlarm.new(@resource)
103
+ alarm.name = 'RabbitMQMemUsedWarn'
104
+ alarm.metric_name = 'RabbitMQMemUsed'
105
+ alarm.comparison_operator = 'GreaterThanThreshold'
106
+ alarm.statistic = 'Maximum'
107
+ alarm.threshold = 350000000
108
+ alarm.evaluation_periods = 5
109
+ alarm.treat_missing_data = 'notBreaching'
110
+ alarm.alarm_action = 'Warning'
111
+ @alarms.push(alarm)
112
+
113
+ alarm = CfnGuardian::Models::AmazonMQRabbitMQNodeAlarm.new(@resource)
114
+ alarm.name = 'RabbitMQDiskFreeLimitCritical'
115
+ alarm.metric_name = 'RabbitMQDiskFreeLimit'
116
+ alarm.comparison_operator = 'LessThanThreshold'
117
+ alarm.statistic = 'Maximum'
118
+ alarm.threshold = 1200000000
119
+ alarm.evaluation_periods = 5
120
+ alarm.treat_missing_data = 'notBreaching'
121
+ @alarms.push(alarm)
122
+
123
+ alarm = CfnGuardian::Models::AmazonMQRabbitMQNodeAlarm.new(@resource)
124
+ alarm.name = 'RabbitMQDiskFreeLimitWarn'
125
+ alarm.metric_name = 'RabbitMQDiskFreeLimit'
126
+ alarm.comparison_operator = 'LessThanThreshold'
127
+ alarm.statistic = 'Maximum'
128
+ alarm.threshold = 1200000000
129
+ alarm.evaluation_periods = 5
130
+ alarm.treat_missing_data = 'notBreaching'
131
+ alarm.alarm_action = 'Warning'
132
+ @alarms.push(alarm)
133
+
134
+ end
135
+ end
136
+ end