cfn-guardian 0.4.0 → 0.6.2

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 (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
@@ -19,6 +19,17 @@ module CfnGuardian
19
19
  @alarms.push(alarm)
20
20
  end
21
21
 
22
+ def default_event_subscriptions()
23
+ event_subscription = CfnGuardian::Models::Ec2InstanceEventSubscription.new(@resource)
24
+ event_subscription.name = 'InstanceTerminated'
25
+ event_subscription.detail_type = 'EC2 Instance State-change Notification'
26
+ event_subscription.detail = {
27
+ 'instance-id' => [@resource['Id']],
28
+ 'state' => ['terminated']
29
+ }
30
+ @event_subscriptions.push(event_subscription)
31
+ end
32
+
22
33
  end
23
34
  end
24
35
  end
@@ -41,6 +41,7 @@ module CfnGuardian::Resource
41
41
  alarm = CfnGuardian::Models::SslAlarm.new(@resource)
42
42
  alarm.name = 'ExpiresInDaysTask'
43
43
  alarm.metric_name = 'ExpiresInDays'
44
+ alarm.alarm_action = 'Task'
44
45
  alarm.threshold = 30
45
46
  @alarms.push(alarm)
46
47
  end
@@ -0,0 +1,14 @@
1
+ module CfnGuardian::Resource
2
+ class RDSCluster < Base
3
+
4
+ def default_event_subscriptions()
5
+ event_subscription = CfnGuardian::Models::RDSClusterEventSubscription.new(@resource)
6
+ event_subscription.name = 'FailoverFailed'
7
+ event_subscription.rds_event_category = 'failover'
8
+ event_subscription.message = 'A failover for the DB cluster has failed.'
9
+ @event_subscriptions.push(event_subscription)
10
+ end
11
+
12
+ end
13
+ end
14
+
@@ -43,5 +43,76 @@ module CfnGuardian::Resource
43
43
  @alarms.push(alarm)
44
44
  end
45
45
 
46
+ def default_event_subscriptions()
47
+ event_subscription = CfnGuardian::Models::RDSInstanceEventSubscription.new(@resource)
48
+ event_subscription.name = 'MasterPasswordReset'
49
+ event_subscription.rds_event_category = 'configuration change'
50
+ event_subscription.message = 'The master password for the DB instance has been reset.'
51
+ @event_subscriptions.push(event_subscription)
52
+
53
+ event_subscription = CfnGuardian::Models::RDSInstanceEventSubscription.new(@resource)
54
+ event_subscription.name = 'MasterPasswordResetFailure'
55
+ event_subscription.rds_event_category = 'configuration change'
56
+ event_subscription.message = 'An attempt to reset the master password for the DB instance has failed.'
57
+ @event_subscriptions.push(event_subscription)
58
+
59
+ event_subscription = CfnGuardian::Models::RDSInstanceEventSubscription.new(@resource)
60
+ event_subscription.name = 'Deletion'
61
+ event_subscription.rds_event_category = 'deletion'
62
+ event_subscription.message = 'The DB instance has been deleted.'
63
+ @event_subscriptions.push(event_subscription)
64
+
65
+ event_subscription = CfnGuardian::Models::RDSInstanceEventSubscription.new(@resource)
66
+ event_subscription.name = 'MultiAZFailoverStarted'
67
+ event_subscription.rds_event_category = 'failover'
68
+ event_subscription.message = 'A Multi-AZ failover that resulted in the promotion of a standby instance has started.'
69
+ @event_subscriptions.push(event_subscription)
70
+
71
+ event_subscription = CfnGuardian::Models::RDSInstanceEventSubscription.new(@resource)
72
+ event_subscription.name = 'MultiAZFailoverComplete'
73
+ event_subscription.rds_event_category = 'failover'
74
+ event_subscription.message = 'A Multi-AZ failover has completed.'
75
+ @event_subscriptions.push(event_subscription)
76
+
77
+ event_subscription = CfnGuardian::Models::RDSInstanceEventSubscription.new(@resource)
78
+ event_subscription.name = 'DBFailure'
79
+ event_subscription.rds_event_category = 'failure'
80
+ event_subscription.message = 'The DB instance has failed due to an incompatible configuration or an underlying storage issue. Begin a point-in-time-restore for the DB instance.'
81
+ @event_subscriptions.push(event_subscription)
82
+
83
+ event_subscription = CfnGuardian::Models::RDSInstanceEventSubscription.new(@resource)
84
+ event_subscription.name = 'TableCountExceedsRecommended'
85
+ event_subscription.rds_event_category = 'notification'
86
+ event_subscription.message = 'The number of tables you have for your DB instance exceeds the recommended best practices for Amazon RDS.'
87
+ @event_subscriptions.push(event_subscription)
88
+
89
+ event_subscription = CfnGuardian::Models::RDSInstanceEventSubscription.new(@resource)
90
+ event_subscription.name = 'DatabasesCountExceedsRecommended'
91
+ event_subscription.rds_event_category = 'notification'
92
+ event_subscription.message = 'The number of databases you have for your DB instance exceeds the recommended best practices for Amazon RDS.'
93
+ @event_subscriptions.push(event_subscription)
94
+
95
+ event_subscription = CfnGuardian::Models::RDSInstanceEventSubscription.new(@resource)
96
+ event_subscription.name = 'ReplicationFailure'
97
+ event_subscription.enabled = false
98
+ event_subscription.rds_event_category = 'read replica'
99
+ event_subscription.message = 'An error has occurred in the read replication process.'
100
+ @event_subscriptions.push(event_subscription)
101
+
102
+ event_subscription = CfnGuardian::Models::RDSInstanceEventSubscription.new(@resource)
103
+ event_subscription.name = 'ReplicationTerminated'
104
+ event_subscription.enabled = false
105
+ event_subscription.rds_event_category = 'read replica'
106
+ event_subscription.message = 'Replication on the read replica was terminated.'
107
+ @event_subscriptions.push(event_subscription)
108
+
109
+ event_subscription = CfnGuardian::Models::RDSInstanceEventSubscription.new(@resource)
110
+ event_subscription.name = 'ReplicationStopped'
111
+ event_subscription.enabled = false
112
+ event_subscription.rds_event_category = 'read replica'
113
+ event_subscription.message = 'Replication on the read replica was manually stopped.'
114
+ @event_subscriptions.push(event_subscription)
115
+ end
116
+
46
117
  end
47
118
  end
@@ -31,9 +31,9 @@ module CfnGuardian
31
31
  end
32
32
 
33
33
  add_iam_role(ssm_parameters)
34
-
34
+
35
35
  checks.each {|check| parameters["#{check.name}Function#{check.environment}"] = add_lambda(check)}
36
- stacks.each {|stack| add_stack(stack['Name'],stack['TemplateURL'],parameters)}
36
+ stacks.each {|stack| add_stack(stack['Name'],stack['TemplateURL'],parameters,stack['Reference'])}
37
37
 
38
38
  @parameters = parameters.keys
39
39
  end
@@ -131,9 +131,9 @@ module CfnGuardian
131
131
  S3Key: "#{check.package}/master/#{check.version}.zip"
132
132
  })
133
133
  Handler check.handler
134
- MemorySize 128
134
+ MemorySize check.memory
135
135
  Runtime check.runtime
136
- Timeout 120
136
+ Timeout check.timeout
137
137
  Role FnGetAtt(:LambdaExecutionRole, :Arn)
138
138
  VpcConfig vpc_config unless vpc_config.empty?
139
139
  Tags([
@@ -152,14 +152,15 @@ module CfnGuardian
152
152
  return FnGetAtt("#{check.name}Function#{check.environment}", :Arn)
153
153
  end
154
154
 
155
- def add_stack(name,url,stack_parameters)
155
+ def add_stack(name,url,stack_parameters,stack_id)
156
156
  @template.declare do
157
157
  CloudFormation_Stack(name) do
158
158
  Parameters stack_parameters
159
159
  TemplateURL url
160
160
  TimeoutInMinutes 15
161
161
  Tags([
162
- { Key: 'Name', Value: "guardian-stack-#{name}" }
162
+ { Key: 'Name', Value: "guardian-stack-#{name}" },
163
+ { Key: 'guardian:stack-id', Value: "stk#{stack_id}"}
163
164
  ])
164
165
  end
165
166
  end
@@ -9,8 +9,10 @@ module CfnGuardian
9
9
 
10
10
  attr_reader :template
11
11
 
12
- def initialize(parameters)
13
- @template = CloudFormation("Guardian nested stack")
12
+ def initialize(parameters,stack_id)
13
+ @stack_id = stack_id
14
+
15
+ @template = CloudFormation("Guardian nested - stack-id:stk#{@stack_id}")
14
16
  parameters.each do |name|
15
17
  parameter = @template.Parameter(name)
16
18
  parameter.Type 'String'
@@ -28,6 +30,8 @@ module CfnGuardian
28
30
  add_composite_alarm(resource)
29
31
  when 'MetricFilter'
30
32
  add_metric_filter(resource)
33
+ when 'EventSubscription'
34
+ add_event_subscription(resource)
31
35
  else
32
36
  puts "Warn: #{resource.type} is a unsuported resource type"
33
37
  end
@@ -37,16 +41,17 @@ module CfnGuardian
37
41
  def add_alarm(alarm)
38
42
  actions = alarm.alarm_action.kind_of?(Array) ? alarm.alarm_action.map{|action| Ref(action)} : [Ref(alarm.alarm_action)]
39
43
  actions.concat alarm.maintenance_groups.map {|mg| Ref(mg)} if alarm.maintenance_groups.any?
44
+ stack_id = @stack_id
40
45
 
41
46
  @template.declare do
42
47
  CloudWatch_Alarm("#{alarm.resource_hash}#{alarm.group}#{alarm.name.gsub(/[^0-9a-zA-Z]/i, '')}#{alarm.type}"[0..255]) do
43
48
  ActionsEnabled true
44
49
  AlarmDescription "Guardian alarm #{alarm.name} for the resource #{alarm.resource_id} in alarm group #{alarm.group}"
45
- AlarmName CfnGuardian::CloudWatch.get_alarm_name(alarm)
50
+ AlarmName CfnGuardian::CloudWatch.get_alarm_name(alarm) + "-stk#{stack_id}"
46
51
  ComparisonOperator alarm.comparison_operator
47
52
  Dimensions alarm.dimensions.map {|k,v| {Name: k, Value: v}} unless alarm.dimensions.nil?
48
53
  EvaluationPeriods alarm.evaluation_periods
49
- Statistic alarm.statistic
54
+ Statistic alarm.statistic if alarm.extended_statistic.nil?
50
55
  Period alarm.period
51
56
  Threshold alarm.threshold
52
57
  MetricName alarm.metric_name
@@ -80,11 +85,13 @@ module CfnGuardian
80
85
  end
81
86
 
82
87
  def add_composite_alarm(alarm)
88
+ stack_id = @stack_id
89
+
83
90
  @template.declare do
84
91
  CloudWatch_CompositeAlarm(alarm.name.gsub(/[^0-9a-zA-Z]/i, '')) do
85
92
 
86
93
  AlarmDescription alarm.description
87
- AlarmName "guardian-#{alarm.name}"
94
+ AlarmName "guardian-#{alarm.name}-stk#{stack_id}"
88
95
  AlarmRule alarm.rule
89
96
 
90
97
  unless alarm.alarm_action.nil?
@@ -113,6 +120,28 @@ module CfnGuardian
113
120
  end
114
121
  end
115
122
  end
123
+
124
+ def add_event_subscription(subscription)
125
+ event_pattern = {}
126
+ event_pattern['detail-type'] = [subscription.detail_type]
127
+ event_pattern['source'] = [subscription.source]
128
+ event_pattern['resources'] = [subscription.resource_arn] unless subscription.resource_arn.empty?
129
+ event_pattern['detail'] = subscription.detail unless subscription.detail.empty?
130
+
131
+ @template.declare do
132
+ Events_Rule("#{subscription.group}#{subscription.name}#{subscription.hash}"[0..255]) do
133
+ State subscription.enabled ? 'ENABLED' : 'DISABLED'
134
+ Description "Guardian event subscription #{subscription.group} #{subscription.name} for resource #{subscription.resource_id}"
135
+ EventPattern event_pattern
136
+ Targets [
137
+ {
138
+ Arn: Ref(subscription.topic),
139
+ Id: "#{subscription.topic}Notifier"
140
+ }
141
+ ]
142
+ end
143
+ end
144
+ end
116
145
 
117
146
  end
118
147
  end
@@ -1,4 +1,4 @@
1
1
  module CfnGuardian
2
- VERSION = "0.4.0"
2
+ VERSION = "0.6.2"
3
3
  CHANGE_SET_VERSION = VERSION.gsub('.', '-').freeze
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cfn-guardian
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guslington
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-06 00:00:00.000000000 Z
11
+ date: 2021-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -204,14 +204,14 @@ dependencies:
204
204
  requirements:
205
205
  - - "~>"
206
206
  - !ruby/object:Gem::Version
207
- version: '10.0'
207
+ version: '13.0'
208
208
  type: :development
209
209
  prerelease: false
210
210
  version_requirements: !ruby/object:Gem::Requirement
211
211
  requirements:
212
212
  - - "~>"
213
213
  - !ruby/object:Gem::Version
214
- version: '10.0'
214
+ version: '13.0'
215
215
  description: Manages AWS cloudwatch alarms with default templates using cloudformation
216
216
  email:
217
217
  - itsupport@base2services.com
@@ -221,7 +221,11 @@ extensions: []
221
221
  extra_rdoc_files: []
222
222
  files:
223
223
  - ".dockerignore"
224
+ - ".github/workflows/build-gem.yml"
225
+ - ".github/workflows/release-gem.yml"
226
+ - ".github/workflows/release-image.yml"
224
227
  - ".gitignore"
228
+ - ".rspec"
225
229
  - Dockerfile
226
230
  - Gemfile
227
231
  - Gemfile.lock
@@ -229,6 +233,25 @@ files:
229
233
  - README.md
230
234
  - Rakefile
231
235
  - cfn-guardian.gemspec
236
+ - docs/alarm_templates.md
237
+ - docs/cli.md
238
+ - docs/composite_alarms.md
239
+ - docs/custom_checks/azure_file_check.md
240
+ - docs/custom_checks/domain_expiry.md
241
+ - docs/custom_checks/http.md
242
+ - docs/custom_checks/log_group_metric_filters.md
243
+ - docs/custom_checks/nrpe.md
244
+ - docs/custom_checks/port.md
245
+ - docs/custom_checks/sftp.md
246
+ - docs/custom_checks/sql.md
247
+ - docs/custom_checks/tls.md
248
+ - docs/custom_metrics.md
249
+ - docs/event_subscriptions.md
250
+ - docs/maintenance_mode.md
251
+ - docs/notifiers.md
252
+ - docs/overview.md
253
+ - docs/resources.md
254
+ - docs/variables.md
232
255
  - exe/cfn-guardian
233
256
  - lib/cfnguardian.rb
234
257
  - lib/cfnguardian/cloudwatch.rb
@@ -239,16 +262,19 @@ files:
239
262
  - lib/cfnguardian/deploy.rb
240
263
  - lib/cfnguardian/display_formatter.rb
241
264
  - lib/cfnguardian/drift.rb
265
+ - lib/cfnguardian/error.rb
242
266
  - lib/cfnguardian/log.rb
243
267
  - lib/cfnguardian/models/alarm.rb
244
268
  - lib/cfnguardian/models/check.rb
245
269
  - lib/cfnguardian/models/composite.rb
246
270
  - lib/cfnguardian/models/event.rb
271
+ - lib/cfnguardian/models/event_subscription.rb
247
272
  - lib/cfnguardian/models/metric_filter.rb
248
273
  - lib/cfnguardian/resources/amazonmq_broker.rb
249
274
  - lib/cfnguardian/resources/apigateway.rb
250
275
  - lib/cfnguardian/resources/application_targetgroup.rb
251
276
  - lib/cfnguardian/resources/autoscaling_group.rb
277
+ - lib/cfnguardian/resources/azure_file.rb
252
278
  - lib/cfnguardian/resources/base.rb
253
279
  - lib/cfnguardian/resources/cloudfront_distribution.rb
254
280
  - lib/cfnguardian/resources/domain_expiry.rb
@@ -268,6 +294,7 @@ files:
268
294
  - lib/cfnguardian/resources/network_targetgroup.rb
269
295
  - lib/cfnguardian/resources/nrpe.rb
270
296
  - lib/cfnguardian/resources/port.rb
297
+ - lib/cfnguardian/resources/rds_cluster.rb
271
298
  - lib/cfnguardian/resources/rds_cluster_instance.rb
272
299
  - lib/cfnguardian/resources/rds_instance.rb
273
300
  - lib/cfnguardian/resources/redshift_cluster.rb
@@ -285,11 +312,10 @@ homepage: https://github.com/base2Services/cfn-guardian
285
312
  licenses:
286
313
  - MIT
287
314
  metadata:
288
- allowed_push_host: https://rubygems.org
289
315
  homepage_uri: https://github.com/base2Services/cfn-guardian
290
316
  source_code_uri: https://github.com/base2Services/cfn-guardian
291
317
  changelog_uri: https://github.com/base2Services/cfn-guardian
292
- post_install_message:
318
+ post_install_message:
293
319
  rdoc_options: []
294
320
  require_paths:
295
321
  - lib
@@ -304,9 +330,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
304
330
  - !ruby/object:Gem::Version
305
331
  version: '0'
306
332
  requirements: []
307
- rubyforge_project:
308
- rubygems_version: 2.7.6
309
- signing_key:
333
+ rubygems_version: 3.1.4
334
+ signing_key:
310
335
  specification_version: 4
311
336
  summary: Manages AWS cloudwatch alarms with default templates using cloudformation
312
337
  test_files: []