cfn-guardian 0.3.3 → 0.6.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/build-gem.yml +25 -0
- data/.github/workflows/release-gem.yml +25 -0
- data/.github/workflows/release-image.yml +33 -0
- data/.rspec +1 -0
- data/Gemfile.lock +24 -24
- data/README.md +4 -772
- data/cfn-guardian.gemspec +1 -3
- data/docs/alarm_templates.md +130 -0
- data/docs/cli.md +182 -0
- data/docs/composite_alarms.md +24 -0
- data/docs/custom_checks/azure_file_check.md +28 -0
- data/docs/custom_checks/domain_expiry.md +10 -0
- data/docs/custom_checks/http.md +59 -0
- data/docs/custom_checks/log_group_metric_filters.md +27 -0
- data/docs/custom_checks/nrpe.md +29 -0
- data/docs/custom_checks/port.md +40 -0
- data/docs/custom_checks/sftp.md +73 -0
- data/docs/custom_checks/sql.md +44 -0
- data/docs/custom_checks/tls.md +25 -0
- data/docs/custom_metrics.md +71 -0
- data/docs/event_subscriptions.md +67 -0
- data/docs/maintenance_mode.md +85 -0
- data/docs/notifiers.md +33 -0
- data/docs/overview.md +22 -0
- data/docs/resources.md +93 -0
- data/docs/variables.md +58 -0
- data/lib/cfnguardian.rb +76 -62
- data/lib/cfnguardian/cloudwatch.rb +43 -32
- data/lib/cfnguardian/compile.rb +87 -4
- data/lib/cfnguardian/config/defaults.yaml +9 -0
- data/lib/cfnguardian/deploy.rb +2 -16
- data/lib/cfnguardian/display_formatter.rb +1 -2
- data/lib/cfnguardian/error.rb +4 -0
- data/lib/cfnguardian/models/alarm.rb +101 -29
- data/lib/cfnguardian/models/check.rb +30 -12
- data/lib/cfnguardian/models/event.rb +43 -15
- data/lib/cfnguardian/models/event_subscription.rb +96 -0
- data/lib/cfnguardian/resources/amazonmq_rabbitmq.rb +136 -0
- data/lib/cfnguardian/resources/azure_file.rb +20 -0
- data/lib/cfnguardian/resources/base.rb +126 -26
- data/lib/cfnguardian/resources/ec2_instance.rb +11 -0
- data/lib/cfnguardian/resources/http.rb +1 -0
- data/lib/cfnguardian/resources/internal_http.rb +8 -8
- data/lib/cfnguardian/resources/internal_port.rb +4 -4
- data/lib/cfnguardian/resources/internal_sftp.rb +8 -8
- data/lib/cfnguardian/resources/log_group.rb +2 -2
- data/lib/cfnguardian/resources/rds_cluster.rb +14 -0
- data/lib/cfnguardian/resources/rds_instance.rb +80 -0
- data/lib/cfnguardian/resources/redshift_cluster.rb +2 -2
- data/lib/cfnguardian/resources/sftp.rb +1 -1
- data/lib/cfnguardian/resources/sql.rb +2 -2
- data/lib/cfnguardian/stacks/main.rb +9 -8
- data/lib/cfnguardian/stacks/resources.rb +35 -6
- data/lib/cfnguardian/version.rb +1 -1
- metadata +33 -7
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 "
|
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 "
|
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
|
71
|
-
method_option :sns_warning, type: :string, desc: "sns topic arn for the warning
|
72
|
-
method_option :sns_task, type: :string, desc: "sns topic arn for the task
|
73
|
-
method_option :sns_informational, type: :string, desc: "sns topic arn for the informational
|
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
|
-
|
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 "
|
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 :
|
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 =
|
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.
|
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: "
|
204
|
-
method_option :alarm_prefix, type: :string, desc: "
|
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
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
metric_alarms = CfnGuardian::CloudWatch.
|
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
|
-
|
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 :
|
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
|
256
|
-
|
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
|
-
|
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
|
-
|
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,7 +297,6 @@ 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"
|
299
302
|
|
@@ -405,16 +408,27 @@ module CfnGuardian
|
|
405
408
|
logger.level = debug ? Logger::DEBUG : Logger::INFO
|
406
409
|
end
|
407
410
|
|
408
|
-
def
|
409
|
-
|
410
|
-
alarms.select! {|alarm| alarm.
|
411
|
-
alarms.select! {|alarm| alarm.
|
411
|
+
def filter_compiled_alarms(alarms,filters)
|
412
|
+
filters = filters.slice('group', 'resource', 'alarm', 'topic', 'maintenance-group')
|
413
|
+
alarms.select! {|alarm| alarm.group.downcase == filters['group'].downcase} if filters.has_key?('group')
|
414
|
+
alarms.select! {|alarm| alarm.resource_id.downcase == filters['resource'].downcase} if filters.has_key?('resource')
|
415
|
+
alarms.select! {|alarm| alarm.name.downcase.include? filters['alarm'].downcase} if filters.has_key?('alarm')
|
416
|
+
alarms.select! {|alarm| alarm.alarm_action.include? filters['topic']} if filters.has_key?('topic')
|
417
|
+
alarms.select! {|alarm| alarm.maintenance_groups.include? "#{filters['maintenance-group']}MaintenanceGroup"} if filters.has_key?('maintenance-group')
|
412
418
|
return alarms
|
413
419
|
end
|
414
420
|
|
415
421
|
def default_config()
|
416
422
|
return "#{File.expand_path(File.dirname(__FILE__))}/cfnguardian/config/defaults.yaml"
|
417
423
|
end
|
424
|
+
|
425
|
+
def get_topic_arn_from_stack(topic)
|
426
|
+
client = Aws::CloudFormation::Client.new()
|
427
|
+
resp = client.describe_stacks({ stack_name: @stack_name })
|
428
|
+
stack = resp.stacks.first
|
429
|
+
parameter = stack.parameters.find {|p| p.parameter_key == topic}
|
430
|
+
return !parameter.nil? ? parameter.parameter_value : nil
|
431
|
+
end
|
418
432
|
|
419
433
|
end
|
420
434
|
end
|