cfn-guardian 0.1.0

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 (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +52 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +412 -0
  7. data/Rakefile +2 -0
  8. data/cfn-guardian.gemspec +39 -0
  9. data/exe/cfn-guardian +4 -0
  10. data/lib/cfnguardian.rb +146 -0
  11. data/lib/cfnguardian/compile.rb +116 -0
  12. data/lib/cfnguardian/deploy.rb +144 -0
  13. data/lib/cfnguardian/log.rb +40 -0
  14. data/lib/cfnguardian/models/alarm.rb +292 -0
  15. data/lib/cfnguardian/models/check.rb +114 -0
  16. data/lib/cfnguardian/models/event.rb +192 -0
  17. data/lib/cfnguardian/resources/amazonmq_broker.rb +45 -0
  18. data/lib/cfnguardian/resources/apigateway.rb +34 -0
  19. data/lib/cfnguardian/resources/application_targetgroup.rb +31 -0
  20. data/lib/cfnguardian/resources/autoscaling_group.rb +22 -0
  21. data/lib/cfnguardian/resources/base.rb +116 -0
  22. data/lib/cfnguardian/resources/cloudfront_distribution.rb +26 -0
  23. data/lib/cfnguardian/resources/domain_expiry.rb +30 -0
  24. data/lib/cfnguardian/resources/dynamodb_table.rb +48 -0
  25. data/lib/cfnguardian/resources/ec2_instance.rb +24 -0
  26. data/lib/cfnguardian/resources/ecs_cluster.rb +44 -0
  27. data/lib/cfnguardian/resources/ecs_service.rb +32 -0
  28. data/lib/cfnguardian/resources/elastic_file_system.rb +17 -0
  29. data/lib/cfnguardian/resources/elastic_loadbalancer.rb +26 -0
  30. data/lib/cfnguardian/resources/elasticache_replication_group.rb +45 -0
  31. data/lib/cfnguardian/resources/http.rb +49 -0
  32. data/lib/cfnguardian/resources/lambda.rb +38 -0
  33. data/lib/cfnguardian/resources/network_targetgroup.rb +31 -0
  34. data/lib/cfnguardian/resources/nrpe.rb +42 -0
  35. data/lib/cfnguardian/resources/rds_cluster_instance.rb +30 -0
  36. data/lib/cfnguardian/resources/rds_instance.rb +45 -0
  37. data/lib/cfnguardian/resources/redshift_cluster.rb +30 -0
  38. data/lib/cfnguardian/resources/sql.rb +37 -0
  39. data/lib/cfnguardian/resources/sqs_queue.rb +23 -0
  40. data/lib/cfnguardian/s3.rb +35 -0
  41. data/lib/cfnguardian/stacks/main.rb +149 -0
  42. data/lib/cfnguardian/stacks/resources.rb +80 -0
  43. data/lib/cfnguardian/string.rb +19 -0
  44. data/lib/cfnguardian/validate.rb +80 -0
  45. data/lib/cfnguardian/version.rb +4 -0
  46. metadata +215 -0
@@ -0,0 +1,45 @@
1
+ module CfnGuardian::Resource
2
+ class AmazonMQBroker < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::AmazonMQBrokerAlarm.new(@resource)
6
+ alarm.name = 'CpuCreditBalanceCritical'
7
+ alarm.metric_name = 'CpuCreditBalance'
8
+ alarm.comparison_operator = 'LessThanThreshold'
9
+ alarm.statistic = 'Minimum'
10
+ alarm.threshold = 15
11
+ alarm.evaluation_periods = 1
12
+ alarm.treat_missing_data = 'notBreaching'
13
+ @alarms.push(alarm)
14
+
15
+ alarm = CfnGuardian::Models::AmazonMQBrokerAlarm.new(@resource)
16
+ alarm.name = 'CpuCreditBalanceCritical'
17
+ alarm.metric_name = 'CpuCreditBalance'
18
+ alarm.comparison_operator = 'LessThanThreshold'
19
+ alarm.statistic = 'Minimum'
20
+ alarm.threshold = 30
21
+ alarm.evaluation_periods = 1
22
+ alarm.treat_missing_data = 'notBreaching'
23
+ alarm.alarm_action = 'Warning'
24
+ @alarms.push(alarm)
25
+
26
+ alarm = CfnGuardian::Models::AmazonMQBrokerAlarm.new(@resource)
27
+ alarm.name = 'CpuUtilizationCritical'
28
+ alarm.metric_name = 'CpuUtilization'
29
+ alarm.threshold = 95
30
+ alarm.evaluation_periods = 3
31
+ alarm.treat_missing_data = 'notBreaching'
32
+ @alarms.push(alarm)
33
+
34
+ alarm = CfnGuardian::Models::AmazonMQBrokerAlarm.new(@resource)
35
+ alarm.name = 'CpuUtilizationWarning'
36
+ alarm.metric_name = 'CpuUtilization'
37
+ alarm.threshold = 80
38
+ alarm.evaluation_periods = 3
39
+ alarm.treat_missing_data = 'notBreaching'
40
+ alarm.alarm_action = 'Warning'
41
+ @alarms.push(alarm)
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,34 @@
1
+ module CfnGuardian::Resource
2
+ class ApiGateway < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::ApiGatewayAlarm.new(@resource)
6
+ alarm.name = 'ApiEndpoint5xx'
7
+ alarm.metric_name = '5XXError'
8
+ alarm.statistic = 'Sum'
9
+ alarm.threshold = 5
10
+ alarm.evaluation_periods = 2
11
+ alarm.treat_missing_data = 'notBreaching'
12
+ @alarms.push(alarm)
13
+
14
+ alarm = CfnGuardian::Models::ApiGatewayAlarm.new(@resource)
15
+ alarm.name = 'ApiEndpoint4xx'
16
+ alarm.metric_name = '4XXError'
17
+ alarm.statistic = 'Sum'
18
+ alarm.threshold = 5
19
+ alarm.evaluation_periods = 2
20
+ alarm.treat_missing_data = 'notBreaching'
21
+ @alarms.push(alarm)
22
+
23
+ alarm = CfnGuardian::Models::ApiGatewayAlarm.new(@resource)
24
+ alarm.name = 'Latency'
25
+ alarm.metric_name = 'Latency'
26
+ alarm.statistic = 'Average'
27
+ alarm.threshold = 1000
28
+ alarm.evaluation_periods = 2
29
+ @alarms.push(alarm)
30
+ end
31
+
32
+ end
33
+ end
34
+
@@ -0,0 +1,31 @@
1
+ module CfnGuardian::Resource
2
+ class ApplicationTargetGroup < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::ApplicationTargetGroupAlarm.new(@resource)
6
+ alarm.name = 'HealthyHosts'
7
+ alarm.metric_name = 'HealthyHostCount'
8
+ alarm.statistic = 'Minimum'
9
+ alarm.threshold = 2
10
+ alarm.evaluation_periods = 1
11
+ @alarms.push(alarm)
12
+
13
+ alarm = CfnGuardian::Models::ApplicationTargetGroupAlarm.new(@resource)
14
+ alarm.name = 'UnHealthyHosts'
15
+ alarm.metric_name = 'UnHealthyHostCount'
16
+ alarm.threshold = 0
17
+ alarm.evaluation_periods = 10
18
+ alarm.treat_missing_data = 'notBreaching'
19
+ @alarms.push(alarm)
20
+
21
+ alarm = CfnGuardian::Models::ApplicationTargetGroupAlarm.new(@resource)
22
+ alarm.name = 'TargetResponseTime'
23
+ alarm.metric_name = 'TargetResponseTime'
24
+ alarm.threshold = 5
25
+ alarm.evaluation_periods = 5
26
+ alarm.treat_missing_data = 'notBreaching'
27
+ @alarms.push(alarm)
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,22 @@
1
+ module CfnGuardian::Resource
2
+ class AutoScalingGroup < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::AutoScalingGroupAlarm.new(@resource)
6
+ alarm.name = 'CPUUtilizationHighBase'
7
+ alarm.metric_name = 'CPUUtilization'
8
+ alarm.statistic = 'Minimum'
9
+ alarm.threshold = 90
10
+ alarm.evaluation_periods = 10
11
+ @alarms.push(alarm)
12
+
13
+ alarm = CfnGuardian::Models::AutoScalingGroupAlarm.new(@resource)
14
+ alarm.name = 'StatusCheckFailed'
15
+ alarm.metric_name = 'StatusCheckFailed'
16
+ alarm.threshold = 0
17
+ alarm.evaluation_periods = 10
18
+ @alarms.push(alarm)
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,116 @@
1
+ require 'cfnguardian/string'
2
+ require 'cfnguardian/models/alarm'
3
+ require 'cfnguardian/models/event'
4
+ require 'cfnguardian/models/check'
5
+
6
+ module CfnGuardian::Resource
7
+ class Base
8
+ include Logging
9
+
10
+ def initialize(resource)
11
+ @resource = resource
12
+ @alarms = []
13
+ @events = []
14
+ @checks = []
15
+ end
16
+
17
+ def default_alarms()
18
+ return @alarms
19
+ end
20
+
21
+ def get_alarms(overides={})
22
+ # generate default alarms
23
+ default_alarms()
24
+
25
+ # loop over each override template for the service
26
+ overides.each do |name,properties|
27
+
28
+ # disable default alarms
29
+ if [false].include?(properties)
30
+ alarm = find_alarm(name)
31
+
32
+ if !alarm.nil?
33
+ alarm.enabled = false
34
+ logger.debug "Disabling alarm '#{name}' for resource #{alarm.resource}"
35
+ next
36
+ end
37
+ end
38
+
39
+ unless properties.is_a?(Hash)
40
+ if name != 'Inherit'
41
+ logger.warn "Incorrect format for alarm '#{name}'. Should be of type 'Hash', instead got type '#{properties.class}'"
42
+ end
43
+ next
44
+ end
45
+
46
+ if properties.has_key?('Inherit')
47
+ alarm = find_alarm(properties['Inherit'])
48
+ if !alarm.nil?
49
+ inheritited_alarm = alarm.clone
50
+ alarm.name = name
51
+ properties.each {|attr,value| update_alarm(inheritited_alarm,attr,value)}
52
+ @alarms.push(inheritited_alarm)
53
+ else
54
+ logger.warn "Alarm '#{properties['Inherit']}' doesn't exists and cannot be inherited"
55
+ end
56
+ next
57
+ end
58
+
59
+ alarm = find_alarm(name)
60
+
61
+ if alarm.nil?
62
+ alarm = Kernel.const_get("CfnGuardian::Models::#{self.class.to_s.split('::').last}Alarm").new(properties)
63
+ end
64
+
65
+ if alarm.name.nil?
66
+ alarm.name = name
67
+ end
68
+
69
+ properties.each {|attr,value| update_alarm(alarm,attr,value)}
70
+ @alarms.push(alarm)
71
+
72
+ end
73
+
74
+ return @alarms.select{|a| a.enabled}.map {|a| a.to_h}
75
+ end
76
+
77
+ def default_events()
78
+ return @events
79
+ end
80
+
81
+ def get_events()
82
+ default_events()
83
+ return @events.select{|e| e.enabled}.map {|e| e.to_h}
84
+ end
85
+
86
+ def default_checks()
87
+ return @checks
88
+ end
89
+
90
+ def get_checks()
91
+ default_checks()
92
+ return @checks.map {|c| c.to_h}
93
+ end
94
+
95
+ def get_cost()
96
+ return @alarms.length * 0.10
97
+ end
98
+
99
+ private
100
+
101
+ def find_alarm(name)
102
+ @alarms.detect {|alarm| alarm.name == name}
103
+ end
104
+
105
+ def update_alarm(alarm,attr,value)
106
+ begin
107
+ alarm.send("#{attr.to_underscore}=",value)
108
+ rescue NoMethodError => e
109
+ if !e.message.match?(/inherit/)
110
+ logger.warn "Unknown key '#{attr}' for #{alarm.resource} alarm #{alarm.name}"
111
+ end
112
+ end
113
+ end
114
+
115
+ end
116
+ end
@@ -0,0 +1,26 @@
1
+ module CfnGuardian::Resource
2
+ class CloudFrontDistribution < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::CloudFrontDistributionAlarm.new(@resource)
6
+ alarm.name = '4xxErrorRate'
7
+ alarm.metric_name = '4xxErrorRate'
8
+ alarm.threshold = 2
9
+ alarm.statistic = 'Sum'
10
+ @alarms.push(alarm)
11
+
12
+ alarm = CfnGuardian::Models::CloudFrontDistributionAlarm.new(@resource)
13
+ alarm.name = '5xxErrorRate'
14
+ alarm.metric_name = '5xxErrorRate'
15
+ alarm.threshold = 5
16
+ @alarms.push(alarm)
17
+
18
+ alarm = CfnGuardian::Models::CloudFrontDistributionAlarm.new(@resource)
19
+ alarm.name = 'TotalErrorRate'
20
+ alarm.metric_name = 'TotalErrorRate'
21
+ alarm.threshold = 5
22
+ @alarms.push(alarm)
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ require 'digest/md5'
2
+
3
+ module CfnGuardian::Resource
4
+ class DomainExpiry < Base
5
+
6
+ def default_alarms
7
+ alarm = CfnGuardian::Models::DomainExpiryAlarm.new(@resource)
8
+ alarm.name = 'ExpiresInDaysCritical'
9
+ alarm.metric_name = 'ExpiresInDays'
10
+ alarm.threshold = 7
11
+ @alarms.push(alarm)
12
+
13
+ alarm = CfnGuardian::Models::DomainExpiryAlarm.new(@resource)
14
+ alarm.name = 'ExpiresInDaysWarning'
15
+ alarm.metric_name = 'ExpiresInDays'
16
+ alarm.threshold = 30
17
+ alarm.alarm_action = 'Warning'
18
+ @alarms.push(alarm)
19
+ end
20
+
21
+ def default_events()
22
+ @events.push(CfnGuardian::Models::DomainExpiryEvent.new(@resource))
23
+ end
24
+
25
+ def default_checks()
26
+ @checks.push(CfnGuardian::Models::DomainExpiryCheck.new(@resource))
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,48 @@
1
+ module CfnGuardian::Resource
2
+ class DynamoDBTable < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::DynamoDBTableAlarm.new(@resource)
6
+ alarm.name = 'DynamoDBReadUsage'
7
+ alarm.metric_name = 'ConsumedReadCapacityUnits'
8
+ alarm.statistic = 'Sum'
9
+ alarm.threshold = 80
10
+ alarm.evaluation_periods = 2
11
+ alarm.alarm_action = 'Warning'
12
+ @alarms.push(alarm)
13
+
14
+ alarm = CfnGuardian::Models::DynamoDBTableAlarm.new(@resource)
15
+ alarm.name = 'DynamoDBWriteUsage'
16
+ alarm.metric_name = 'ConsumedWriteCapacityUnits'
17
+ alarm.statistic = 'Sum'
18
+ alarm.threshold = 80
19
+ alarm.evaluation_periods = 2
20
+ alarm.alarm_action = 'Warning'
21
+ @alarms.push(alarm)
22
+
23
+ alarm = CfnGuardian::Models::DynamoDBTableAlarm.new(@resource)
24
+ alarm.name = 'DynamoDBReadThrottleEvents'
25
+ alarm.metric_name = 'ReadThrottleEvents'
26
+ alarm.comparison_operator = 'GreaterThanOrEqualToThreshold'
27
+ alarm.statistic = 'Sum'
28
+ alarm.threshold = 1
29
+ alarm.evaluation_periods = 2
30
+ alarm.alarm_action = 'Warning'
31
+ alarm.treat_missing_data = 'notBreaching'
32
+ @alarms.push(alarm)
33
+
34
+ alarm = CfnGuardian::Models::DynamoDBTableAlarm.new(@resource)
35
+ alarm.name = 'DynamoDBWriteThrottleEvents'
36
+ alarm.metric_name = 'WriteThrottleEvents'
37
+ alarm.comparison_operator = 'GreaterThanOrEqualToThreshold'
38
+ alarm.statistic = 'Sum'
39
+ alarm.threshold = 1
40
+ alarm.evaluation_periods = 2
41
+ alarm.alarm_action = 'Warning'
42
+ alarm.treat_missing_data = 'notBreaching'
43
+ @alarms.push(alarm)
44
+ end
45
+
46
+ end
47
+ end
48
+
@@ -0,0 +1,24 @@
1
+ module CfnGuardian
2
+ module Resource
3
+ class Ec2Instance < Base
4
+
5
+ def default_alarms
6
+ alarm = CfnGuardian::Models::Ec2InstanceAlarm.new(@resource)
7
+ alarm.name = 'CPUUtilizationHigh'
8
+ alarm.metric_name = 'CPUUtilization'
9
+ alarm.statistic = 'Minimum'
10
+ alarm.threshold = 90
11
+ alarm.evaluation_periods = 10
12
+ @alarms.push(alarm)
13
+
14
+ alarm = CfnGuardian::Models::Ec2InstanceAlarm.new(@resource)
15
+ alarm.name = 'StatusCheckFailed'
16
+ alarm.metric_name = 'StatusCheckFailed'
17
+ alarm.threshold = 90
18
+ alarm.evaluation_periods = 10
19
+ @alarms.push(alarm)
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,44 @@
1
+ module CfnGuardian::Resource
2
+ class ECSCluster < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::ECSClusterAlarm.new(@resource)
6
+ alarm.name = 'CPUUtilizationWarning'
7
+ alarm.metric_name = 'CPUUtilization'
8
+ alarm.alarm_action = 'Warning'
9
+ alarm.statistic = 'Minimum'
10
+ @alarms.push(alarm)
11
+
12
+ alarm = CfnGuardian::Models::ECSClusterAlarm.new(@resource)
13
+ alarm.name = 'MemoryUtilizationWarning'
14
+ alarm.metric_name = 'MemoryUtilization'
15
+ alarm.alarm_action = 'Warning'
16
+ @alarms.push(alarm)
17
+
18
+ alarm = CfnGuardian::Models::ECSClusterAlarm.new(@resource)
19
+ alarm.name = 'MemoryUtilizationCritical'
20
+ alarm.metric_name = 'MemoryUtilization'
21
+ alarm.threshold = 90
22
+ @alarms.push(alarm)
23
+
24
+ alarm = CfnGuardian::Models::ECSClusterAlarm.new(@resource)
25
+ alarm.namespace = 'EcsCICheck'
26
+ alarm.name = 'ECSContianerInstancesDisconnected'
27
+ alarm.metric_name = 'ECSContianerInstancesDisconnected'
28
+ alarm.alarm_action = 'Critical'
29
+ alarm.threshold = 0
30
+ alarm.period = 300
31
+ alarm.evaluation_periods = 2
32
+ @alarms.push(alarm)
33
+ end
34
+
35
+ def default_events
36
+ @events.push(CfnGuardian::Models::ContainerInstanceEvent.new(@resource))
37
+ end
38
+
39
+ def default_checks
40
+ @checks.push(CfnGuardian::Models::ContainerInstanceCheck.new(@resource))
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,32 @@
1
+ module CfnGuardian
2
+ module Resource
3
+ class ECSService < Base
4
+
5
+ def default_alarms
6
+ alarm = CfnGuardian::Models::ECSServiceAlarm.new(@resource)
7
+ alarm.name = 'UnhealthyTaskCritical'
8
+ alarm.metric_name = 'MemoryUtilization'
9
+ alarm.comparison_operator = 'LessThanOrEqualToThreshold'
10
+ alarm.statistic = 'SampleCount'
11
+ alarm.threshold = 15
12
+ alarm.evaluation_periods = 10
13
+ alarm.treat_missing_data = 'breaching'
14
+ alarm.datapoints_to_alarm = 8
15
+ @alarms.push(alarm)
16
+
17
+ alarm = CfnGuardian::Models::ECSServiceAlarm.new(@resource)
18
+ alarm.name = 'UnhealthyTaskWarning'
19
+ alarm.metric_name = 'MemoryUtilization'
20
+ alarm.comparison_operator = 'LessThanOrEqualToThreshold'
21
+ alarm.statistic = 'SampleCount'
22
+ alarm.threshold = 15
23
+ alarm.evaluation_periods = 10
24
+ alarm.treat_missing_data = 'breaching'
25
+ alarm.datapoints_to_alarm = 8
26
+ alarm.alarm_action = 'Warning'
27
+ @alarms.push(alarm)
28
+ end
29
+
30
+ end
31
+ end
32
+ end