cfn-guardian 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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