cfn-guardian 0.4.0 → 0.6.6

Sign up to get free protection for your applications and to get access to all the features.
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
data/docs/notifiers.md ADDED
@@ -0,0 +1,33 @@
1
+ # Guardian Notifiers
2
+
3
+ ## SNS Notification
4
+
5
+ There are 4 default notification levels used by Guardian Critical, Warning, Task, Informational. If you wish to recieve notifications for each of these you need to supply an sns topic arn in the alarms.yaml
6
+
7
+ ```yaml
8
+ Topics:
9
+ Critical: arn:aws:sns:ap-southeast-2:123456789012:Critical
10
+ Warning: arn:aws:sns:ap-southeast-2:123456789012:Warning
11
+ Task: arn:aws:sns:ap-southeast-2:123456789012:Task
12
+ Informational: arn:aws:sns:ap-southeast-2:123456789012:Informational
13
+ ```
14
+
15
+ Each alarm has a default notification level but can be overriden in the config using the `AlarmAction` property at either the alarm group or alarm level. See the [Overriding Defaults](#overriding-defaults) section on how to do that.
16
+
17
+ You can add your own notification topics to the topics section and combine them with the existing topics. `AlarmAction` property will accept both a string and array of notication topics.
18
+
19
+ ```yaml
20
+ Topics:
21
+ Critical: arn:aws:sns:ap-southeast-2:123456789012:Critical
22
+ Warning: arn:aws:sns:ap-southeast-2:123456789012:Warning
23
+ Task: arn:aws:sns:ap-southeast-2:123456789012:Task
24
+ Informational: arn:aws:sns:ap-southeast-2:123456789012:Informational
25
+ Custom: arn:aws:sns:ap-southeast-2:123456789012:Custom
26
+
27
+ Template:
28
+ Ec2Instance:
29
+ GroupOverrides:
30
+ AlarmActions:
31
+ - Critical
32
+ - Custom
33
+ ```
data/docs/overview.md ADDED
@@ -0,0 +1,22 @@
1
+ # Guardian Documentation
2
+
3
+ ## Table of Contents
4
+ 1. [CLI Commands](cli.md)
5
+ 2. [Resources](resources.md)
6
+ 3. [Alarm Templates](alarm_templates.md)
7
+ 4. Custom Checks
8
+ 1. [HTTP](custom_checks/http.md)
9
+ 2. [Domain Expirey](custom_checks/domain_expirey.md)
10
+ 3. [LogGroup Metric Filters](custom_checks/log_group_metric_filters.md)
11
+ 4. [NRPE](custom_checks/nrpe.md)
12
+ 5. [Port](custom_checks/port.md)
13
+ 6. [SFTP](custom_checks/sftp.md)
14
+ 7. [SQL](custom_checks/sql.md)
15
+ 8. [TLS](custom_checks/tls.md)
16
+ 9. [Azure File Check](custom_checks/azure_file_check.md)
17
+ 5. [Event Subscriptions](event_subscriptions.md)
18
+ 6. [Notifiers](notifiers.md)
19
+ 7. [Maintenance Mode](maintenance_mode.md)
20
+ 8. [Composite Alarms](composite_alarms.md)
21
+ 9. [Alarms for Custom Metrics](custom_metrics.md)
22
+ 10. [Dimension Variables](variables.md)
data/docs/resources.md ADDED
@@ -0,0 +1,93 @@
1
+ # Resources
2
+
3
+ Resources are AWS resources grouped by the resource type such as `RDSInstance`, `Ec2Instance`, `ApplicationTargetGroup` etc. These are defined under the top level key `Resources` in the yaml config file. The resource group is then used to generate standard set of alarms.
4
+
5
+ Custom resource groups can be created however matching alarm templates must be created to create alarms.
6
+
7
+ ## Resource lookup
8
+
9
+ Resources can be looked up within an account using the tool [monitorable](https://github.com/base2Services/monitorable). This tool will scan every region within an account for AWS resources that can be monitored and return a valid Guardian yaml config using the `--format cfn-guardian` flag.
10
+
11
+ ```sh
12
+ ./monitorable.py --format cfn-guardian
13
+ ```
14
+
15
+ ## YAML Configuration
16
+
17
+ The resources key is where the resources are defined.
18
+
19
+ ```yaml
20
+ Resources:
21
+ # resource group
22
+ Ec2Instance:
23
+ # Array of resources defining the resource id with the Id: key
24
+ - Id: i-1a2b3c4d5e
25
+ ```
26
+
27
+ There are some resources that require more that the resource id to generate the alarm, for these cases addition key:values are required.
28
+
29
+ ```yaml
30
+ Resources:
31
+ ApplicationTargetGroup:
32
+ - Id: target-group-id
33
+ # Target group requires the loadbalancer id for the alarm
34
+ Loadbalancer: app/application-loadbalancer-id
35
+ ```
36
+
37
+ | Resource Group | Require Keys |
38
+ | --------------------------- | ---------------- |
39
+ | ApiGateway | Id |
40
+ | AmazonMQBroker | Id |
41
+ | AutoScalingGroup | Id |
42
+ | DynamoDBTable | Id |
43
+ | ElastiCacheReplicationGroup | Id |
44
+ | ElasticFileSystem | Id |
45
+ | Ec2Instance | Id |
46
+ | EcsCluster | Id |
47
+ | EcsService | Id, Cluster |
48
+ | NetworkTargetGroup | Id, LoadBalancer |
49
+ | ApplicationTargetGroup | Id, LoadBalancer |
50
+ | ElasticLoadBalancer | Id |
51
+ | RDSInstance | Id |
52
+ | RDSClusterInstance | Id |
53
+ | RedshiftCluster | Id |
54
+ | Lambda | Id |
55
+ | CloudFrontDistribution | Id |
56
+ | SQSQueue | Id |
57
+
58
+
59
+ ## Custom Resource Groups
60
+
61
+ You may want to create a custom resource group if some of the resources require differewnt alarm configurations. To create a custom resource group create new name for the group and add the resources, then create the alarm template and inherit the desired alarms.
62
+
63
+ ```yaml
64
+ Resources:
65
+ # default resource group
66
+ Ec2Instance:
67
+ - Id: i-1a2b3c4d5e
68
+ - Id: i-9z8y7x6w5v
69
+ # custom resource group
70
+ CustomEc2Instance:
71
+ - Id: i-6fefg5qe4e
72
+
73
+ Templates:
74
+ # create a new alarm template with the same group name
75
+ CustomEc2Instance:
76
+ # inherit the ec2 alarms
77
+ Inherit: Ec2Instance
78
+ # alter the alarms
79
+ CPUUtilizationHigh: false
80
+ ```
81
+
82
+ ## Friendly Resource Names
83
+
84
+ You can set a friendly name which will replace the resource id in the alarm name.
85
+ The resource id will still be available in the alarm description.
86
+
87
+ ```yaml
88
+ Resources:
89
+ ApplicationTargetGroup:
90
+ - Id: target-group-id
91
+ Loadbalancer: app/application-loadbalancer-id
92
+ Name: webapp
93
+ ```
data/docs/variables.md ADDED
@@ -0,0 +1,58 @@
1
+ ## Dimension Variables
2
+
3
+ variables can be used to reference resource group values such as the resource Id within the dimensions section of an alarm template.
4
+
5
+ For example here we are creating an alarm for a disk usage metric for a group of EC2 instances.
6
+
7
+ ```yaml
8
+ Templates:
9
+ Ec2Instance:
10
+ LowDiskSpaceRootVolume:
11
+ Namespace: CWAgent
12
+ MetricName: DiskSpaceUsedPercent
13
+ Dimensions:
14
+ path: '/'
15
+ # Reference the resource Id from the resource group
16
+ host: ${Resource::Id}
17
+ device: 'xvda1'
18
+ fstype: 'ext4'
19
+ Statistic: Maximum
20
+ Threshold: 85
21
+ Period: 60
22
+ EvaluationPeriods: 1
23
+ TreatMissingData: breaching
24
+
25
+ Resources:
26
+ Ec2Instance:
27
+ - Id: i-12345678
28
+ - Id: i-abcdefgh
29
+ ```
30
+
31
+ custom variables can be referenced if you have different dimensions for each resource. using the example above, you may have different file system types on each instance.
32
+
33
+ ```yaml
34
+ Templates:
35
+ Ec2Instance:
36
+ LowDiskSpaceRootVolume:
37
+ Namespace: CWAgent
38
+ MetricName: DiskSpaceUsedPercent
39
+ Dimensions:
40
+ path: '/'
41
+ # Reference the resource Id from the resource group
42
+ host: ${Resource::Id}
43
+ device: 'xvda1'
44
+ # Reference the resource FileSystemType from the resource group
45
+ fstype: ${Resource::FileSystemType}
46
+ Statistic: Maximum
47
+ Threshold: 85
48
+ Period: 60
49
+ EvaluationPeriods: 1
50
+ TreatMissingData: breaching
51
+
52
+ Resources:
53
+ Ec2Instance:
54
+ - Id: i-12345678
55
+ FileSystemType: ext4
56
+ - Id: i-abcdefgh
57
+ FileSystemType: ext4
58
+ ```
data/lib/cfnguardian.rb CHANGED
@@ -33,6 +33,13 @@ module CfnGuardian
33
33
  method_option :bucket, type: :string, desc: "provide custom bucket name, will create a default bucket if not provided"
34
34
  method_option :path, type: :string, default: "guardian", desc: "S3 path location for nested stacks"
35
35
  method_option :region, aliases: :r, type: :string, desc: "set the AWS region"
36
+ method_option :template_config, type: :boolean, default: false, desc: "Genrates an AWS CodePipeline cloudformation template configuration file to override parameters"
37
+ method_option :sns_critical, type: :string, desc: "sns topic arn for the critical alarms"
38
+ method_option :sns_warning, type: :string, desc: "sns topic arn for the warning alarms"
39
+ method_option :sns_task, type: :string, desc: "sns topic arn for the task alarms"
40
+ method_option :sns_informational, type: :string, desc: "sns topic arn for the informational alarms"
41
+ method_option :sns_events, type: :string, desc: "sns topic arn for the informational alarms"
42
+
36
43
 
37
44
  def compile
38
45
  set_log_level(options[:debug])
@@ -43,7 +50,7 @@ module CfnGuardian
43
50
  compiler = CfnGuardian::Compile.new(options[:config])
44
51
  compiler.get_resources
45
52
  compiler.compile_templates(s3.bucket,s3.path)
46
- logger.info "Clouformation templates compiled successfully in out/ directory"
53
+ logger.info "Cloudformation templates compiled successfully in out/ directory"
47
54
  if options[:validate]
48
55
  s3.create_bucket_if_not_exists()
49
56
  validator = CfnGuardian::Validate.new(s3.bucket)
@@ -51,10 +58,16 @@ module CfnGuardian
51
58
  logger.error("One or more templates failed to validate")
52
59
  exit(1)
53
60
  else
54
- logger.info "Clouformation templates were validated successfully"
61
+ logger.info "Cloudformation templates were validated successfully"
55
62
  end
56
63
  end
57
64
  logger.warn "AWS cloudwatch alarms defined in the templates will cost roughly $#{'%.2f' % compiler.cost} per month"
65
+
66
+ if options[:template_config]
67
+ logger.info "Generating a AWS CodePipeline template configuration file template-config.guardian.json"
68
+ parameters = compiler.load_parameters(options)
69
+ compiler.genrate_template_config(parameters)
70
+ end
58
71
  end
59
72
 
60
73
  desc "deploy", "Generates and deploys monitoring CloudFormation templates"
@@ -67,10 +80,11 @@ module CfnGuardian
67
80
  method_option :path, type: :string, default: "guardian", desc: "S3 path location for nested stacks"
68
81
  method_option :region, aliases: :r, type: :string, desc: "set the AWS region"
69
82
  method_option :stack_name, aliases: :s, type: :string, desc: "set the Cloudformation stack name. Defaults to `guardian`"
70
- method_option :sns_critical, type: :string, desc: "sns topic arn for the critical alamrs"
71
- method_option :sns_warning, type: :string, desc: "sns topic arn for the warning alamrs"
72
- method_option :sns_task, type: :string, desc: "sns topic arn for the task alamrs"
73
- method_option :sns_informational, type: :string, desc: "sns topic arn for the informational alamrs"
83
+ method_option :sns_critical, type: :string, desc: "sns topic arn for the critical alarms"
84
+ method_option :sns_warning, type: :string, desc: "sns topic arn for the warning alarms"
85
+ method_option :sns_task, type: :string, desc: "sns topic arn for the task alarms"
86
+ method_option :sns_informational, type: :string, desc: "sns topic arn for the informational alarms"
87
+ method_option :sns_events, type: :string, desc: "sns topic arn for the informational alarms"
74
88
 
75
89
  def deploy
76
90
  set_log_level(options[:debug])
@@ -81,7 +95,8 @@ module CfnGuardian
81
95
  compiler = CfnGuardian::Compile.new(options[:config])
82
96
  compiler.get_resources
83
97
  compiler.compile_templates(s3.bucket,s3.path)
84
- logger.info "Clouformation templates compiled successfully in out/ directory"
98
+ parameters = compiler.load_parameters(options)
99
+ logger.info "Cloudformation templates compiled successfully in out/ directory"
85
100
 
86
101
  s3.create_bucket_if_not_exists
87
102
  validator = CfnGuardian::Validate.new(s3.bucket)
@@ -89,10 +104,10 @@ module CfnGuardian
89
104
  logger.error("One or more templates failed to validate")
90
105
  exit(1)
91
106
  else
92
- logger.info "Clouformation templates were validated successfully"
107
+ logger.info "Cloudformation templates were validated successfully"
93
108
  end
94
109
 
95
- deployer = CfnGuardian::Deploy.new(options,s3.bucket)
110
+ deployer = CfnGuardian::Deploy.new(options,s3.bucket,parameters)
96
111
  deployer.upload_templates
97
112
  change_set, change_set_type = deployer.create_change_set()
98
113
  deployer.wait_for_changeset(change_set.id)
@@ -135,14 +150,11 @@ module CfnGuardian
135
150
  method_option :config, aliases: :c, type: :string, desc: "yaml config file"
136
151
  method_option :defaults, type: :boolean, desc: "display default alarms and properties"
137
152
  method_option :region, aliases: :r, type: :string, desc: "set the AWS region"
138
- method_option :group, aliases: :g, type: :string, desc: "resource group"
139
- method_option :alarm, aliases: :a, type: :string, desc: "alarm name"
140
- method_option :id, type: :string, desc: "resource id"
153
+ method_option :filter, type: :hash, default: {}, desc: "filter the displayed alarms by [group, resource-id, alarm, stack-id, topic, maintenance-group]"
141
154
  method_option :compare, type: :boolean, default: false, desc: "compare config to deployed alarms"
142
155
 
143
156
  def show_alarms
144
157
  set_log_level(options[:debug])
145
-
146
158
  set_region(options[:region],options[:compare])
147
159
 
148
160
  if options[:config]
@@ -156,7 +168,7 @@ module CfnGuardian
156
168
 
157
169
  compiler = CfnGuardian::Compile.new(config_file)
158
170
  compiler.get_resources
159
- alarms = filter_alarms(compiler.alarms,options)
171
+ alarms = filter_compiled_alarms(compiler.alarms,options[:filter])
160
172
 
161
173
  if alarms.empty?
162
174
  logger.error "No matches found"
@@ -167,13 +179,15 @@ module CfnGuardian
167
179
  formatter = CfnGuardian::DisplayFormatter.new(alarms)
168
180
 
169
181
  if options[:compare] && !options[:defaults]
170
- metric_alarms = CfnGuardian::CloudWatch.get_alarms(alarms)
182
+ metric_alarms = CfnGuardian::CloudWatch.get_alarms_by_prefix(prefix: 'guardian')
183
+ metric_alarms = CfnGuardian::CloudWatch.filter_alarms(filters: options[:filter], alarms: metric_alarms)
184
+
171
185
  formatted_alarms = formatter.compare_alarms(metric_alarms)
172
186
  headings.push('Deployed')
173
187
  else
174
188
  formatted_alarms = formatter.alarms()
175
189
  end
176
-
190
+
177
191
  if formatted_alarms.any?
178
192
  formatted_alarms.each do |fa|
179
193
  puts Terminal::Table.new(
@@ -192,37 +206,34 @@ module CfnGuardian
192
206
 
193
207
  desc "show-state", "Shows alarm state in cloudwatch"
194
208
  long_desc <<-LONG
195
- Displays the current cloudwatch alarm state
209
+ Displays the current cloudwatch alarm state. By default it will return all the guardian alarms.
196
210
  LONG
197
- method_option :config, aliases: :c, type: :string, desc: "yaml config file"
198
211
  method_option :region, aliases: :r, type: :string, desc: "set the AWS region"
199
- method_option :group, aliases: :g, type: :string, desc: "resource group"
200
- method_option :alarm, aliases: :a, type: :string, desc: "alarm name"
201
- method_option :id, type: :string, desc: "resource id"
202
212
  method_option :state, aliases: :s, type: :string, enum: %w(OK ALARM INSUFFICIENT_DATA), desc: "filter by alarm state"
203
- method_option :alarm_names, type: :array, desc: "CloudWatch alarm name if not providing config"
204
- method_option :alarm_prefix, type: :string, desc: "CloudWatch alarm name prefix if not providing config"
205
-
213
+ method_option :alarm_names, type: :array, desc: "list of cloudwatch alarm names"
214
+ method_option :alarm_prefix, type: :string, default: "guardian", desc: "cloudwatch alarm name prefix"
215
+ method_option :filter, type: :hash, default: {}, desc: "filter the displayed alarms by [group, resource-id, alarm, stack-id, topic, maintenance-group]"
216
+
206
217
  def show_state
207
218
  set_log_level(options[:debug])
208
219
  set_region(options[:region],true)
209
-
210
- formatter = CfnGuardian::DisplayFormatter.new()
211
-
212
- if !options[:config].nil?
213
- compiler = CfnGuardian::Compile.new(options[:config])
214
- compiler.get_resources
215
- alarms = filter_alarms(compiler.alarms,options)
216
- metric_alarms = CfnGuardian::CloudWatch.get_alarm_state(config_alarms: alarms, state: options[:state])
217
- elsif !options[:alarm_names].nil?
218
- metric_alarms = CfnGuardian::CloudWatch.get_alarm_state(alarm_names: options[:alarm_names], state: options[:state])
219
- elsif !options[:alarm_prefix].nil?
220
- metric_alarms = CfnGuardian::CloudWatch.get_alarm_state(alarm_prefix: options[:alarm_prefix], state: options[:state])
220
+ action_prefix = nil
221
+
222
+ if options[:filter].has_key?('topic')
223
+ action_prefix = get_topic_arn_from_stack(options[:filter]['topic'])
224
+ elsif options[:filter].has_key?('maintenance-group')
225
+ action_prefix = "arn:aws:sns:#{Aws.config[:region]}:#{CfnGuardian::CloudWatch.aws_account_id()}:#{options[:filter]['maintenance-group']}MaintenanceGroup"
226
+ end
227
+
228
+ if options[:alarm_names]
229
+ metric_alarms = CfnGuardian::CloudWatch.get_alarms_by_name(alarm_names: options[:alarm_names], state: options[:state], action_prefix: action_prefix)
221
230
  else
222
- logger.error "one of `--config` `--alarm-prefix` `--alarm-names` must be supplied"
223
- exit 1
231
+ metric_alarms = CfnGuardian::CloudWatch.get_alarms_by_prefix(prefix: options[:alarm_prefix], state: options[:state], action_prefix: action_prefix)
224
232
  end
225
-
233
+
234
+ metric_alarms = CfnGuardian::CloudWatch.filter_alarms(filters: options[:filter], alarms: metric_alarms)
235
+
236
+ formatter = CfnGuardian::DisplayFormatter.new()
226
237
  rows = formatter.alarm_state(metric_alarms)
227
238
 
228
239
  if rows.any?
@@ -239,31 +250,24 @@ module CfnGuardian
239
250
  long_desc <<-LONG
240
251
  Displays the alarm state or config history for the last 7 days
241
252
  LONG
242
- method_option :config, aliases: :c, type: :string, desc: "yaml config file"
243
253
  method_option :region, aliases: :r, type: :string, desc: "set the AWS region"
244
- method_option :group, aliases: :g, type: :string, desc: "resource group"
245
- method_option :alarm, aliases: :a, type: :string, desc: "alarm name"
246
- method_option :alarm_names, type: :array, desc: "CloudWatch alarm name if not providing config"
247
- method_option :id, type: :string, desc: "resource id"
254
+ method_option :alarm_names, type: :array, desc: "list of cloudwatch alarm names"
248
255
  method_option :type, aliases: :t, type: :string,
249
256
  enum: %w(state config), default: 'state', desc: "filter by alarm state"
257
+ method_option :alarm_prefix, type: :string, default: "guardian", desc: "cloudwatch alarm name prefix"
258
+ method_option :filter, type: :hash, desc: "filter the displayed alarms by [group, resource-id, alarm, stack-id]"
250
259
 
251
260
  def show_history
252
261
  set_log_level(options[:debug])
253
262
  set_region(options[:region],true)
254
263
 
255
- if !options[:config].nil?
256
- compiler = CfnGuardian::Compile.new(options[:config])
257
- compiler.get_resources
258
- config_alarms = filter_alarms(compiler.alarms,options)
259
- alarms = config_alarms.map {|alarm| CfnGuardian::CloudWatch.get_alarm_name(alarm)}
260
- elsif !options[:alarm_names].nil?
261
- alarms = options[:alarm_names]
264
+ if options[:alarm_names]
265
+ metric_alarms = CfnGuardian::CloudWatch.get_alarms_by_name(alarm_names: options[:alarm_names], state: options[:state])
262
266
  else
263
- logger.error "one of `--config` `--alarm-names` must be supplied"
264
- exit 1
267
+ metric_alarms = CfnGuardian::CloudWatch.get_alarms_by_prefix(prefix: options[:alarm_prefix], state: options[:state])
265
268
  end
266
-
269
+
270
+ metric_alarms = CfnGuardian::CloudWatch.filter_alarms(filters: options[:filter], alarms: metric_alarms)
267
271
 
268
272
  case options[:type]
269
273
  when 'state'
@@ -276,12 +280,12 @@ module CfnGuardian
276
280
 
277
281
  formatter = CfnGuardian::DisplayFormatter.new()
278
282
 
279
- alarms.each do |alarm|
280
- history = CfnGuardian::CloudWatch.get_alarm_history(alarm,type)
283
+ metric_alarms.each do |alarm|
284
+ history = CfnGuardian::CloudWatch.get_alarm_history(alarm.alarm_name,type)
281
285
  rows = formatter.alarm_history(history,type)
282
286
  if rows.any?
283
287
  puts Terminal::Table.new(
284
- :title => alarm.green,
288
+ :title => alarm.alarm_name.green,
285
289
  :headings => headings,
286
290
  :rows => rows)
287
291
  puts "\n"
@@ -293,17 +297,20 @@ module CfnGuardian
293
297
  long_desc <<-LONG
294
298
  Shows the last 10 commits made to the codecommit repo
295
299
  LONG
296
- method_option :config, aliases: :c, type: :string, desc: "yaml config file"
297
300
  method_option :region, aliases: :r, type: :string, desc: "set the AWS region"
298
301
  method_option :repository, type: :string, default: 'guardian', desc: "codecommit repository name"
302
+ method_option :branch, type: :string, default: 'master', desc: "codecommit branch"
303
+ method_option :count, type: :numeric, default: 10, desc: "number of last commits to retrieve"
299
304
 
300
305
  def show_config_history
301
306
  set_region(options[:region],true)
302
307
 
303
- history = CfnGuardian::CodeCommit.new(options[:repository]).get_commit_history()
304
- puts Terminal::Table.new(
305
- :headings => history.first.keys.map{|h| h.to_s.to_heading},
306
- :rows => history.map(&:values))
308
+ history = CfnGuardian::CodeCommit.new(options[:repository]).get_commit_history(options[:branch], options[:count])
309
+ if history.any?
310
+ puts Terminal::Table.new(
311
+ :headings => history.first.keys.map{|h| h.to_s.to_heading},
312
+ :rows => history.map(&:values))
313
+ end
307
314
  end
308
315
 
309
316
  desc "show-pipeline", "Shows the current state of the AWS code pipeline"
@@ -405,16 +412,27 @@ module CfnGuardian
405
412
  logger.level = debug ? Logger::DEBUG : Logger::INFO
406
413
  end
407
414
 
408
- def filter_alarms(alarms,options)
409
- alarms.select! {|alarm| alarm.group.downcase == options[:group].downcase} if options[:group]
410
- alarms.select! {|alarm| alarm.resource_id.downcase == options[:id].downcase} if options[:id]
411
- alarms.select! {|alarm| alarm.name.downcase.include? options[:alarm].downcase} if options[:alarm]
415
+ def filter_compiled_alarms(alarms,filters)
416
+ filters = filters.slice('group', 'resource', 'alarm', 'topic', 'maintenance-group')
417
+ alarms.select! {|alarm| alarm.group.downcase == filters['group'].downcase} if filters.has_key?('group')
418
+ alarms.select! {|alarm| alarm.resource_id.downcase == filters['resource'].downcase} if filters.has_key?('resource')
419
+ alarms.select! {|alarm| alarm.name.downcase.include? filters['alarm'].downcase} if filters.has_key?('alarm')
420
+ alarms.select! {|alarm| alarm.alarm_action.include? filters['topic']} if filters.has_key?('topic')
421
+ alarms.select! {|alarm| alarm.maintenance_groups.include? "#{filters['maintenance-group']}MaintenanceGroup"} if filters.has_key?('maintenance-group')
412
422
  return alarms
413
423
  end
414
424
 
415
425
  def default_config()
416
426
  return "#{File.expand_path(File.dirname(__FILE__))}/cfnguardian/config/defaults.yaml"
417
427
  end
428
+
429
+ def get_topic_arn_from_stack(topic)
430
+ client = Aws::CloudFormation::Client.new()
431
+ resp = client.describe_stacks({ stack_name: @stack_name })
432
+ stack = resp.stacks.first
433
+ parameter = stack.parameters.find {|p| p.parameter_key == topic}
434
+ return !parameter.nil? ? parameter.parameter_value : nil
435
+ end
418
436
 
419
437
  end
420
438
  end