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,17 @@
1
+ module CfnGuardian
2
+ module Resource
3
+ class ElasticFileSystem < Base
4
+
5
+ def default_alarms
6
+ alarm = CfnGuardian::Models::ElasticFileSystemAlarm.new(@resource)
7
+ alarm.name = 'PercentIOLimitHigh'
8
+ alarm.metric_name = 'PercentIOLimit'
9
+ alarm.comparison_operator = 'GreaterThanThreshold'
10
+ alarm.threshold = 90
11
+ alarm.evaluation_periods = 5
12
+ alarm.statistic = 'Minimum'
13
+ @alarms.push(alarm)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ module CfnGuardian::Resource
2
+ class ElasticLoadBalancer < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::ElasticLoadBalancerAlarm.new(@resource)
6
+ alarm.name = 'HealthyHosts'
7
+ alarm.metric_name = 'HealthyHostCount'
8
+ alarm.comparison_operator = 'LessThanThreshold'
9
+ alarm.statistic = 'Minimum'
10
+ alarm.threshold = 2
11
+ alarm.evaluation_periods = 1
12
+ alarm.treat_missing_data = 'notBreaching'
13
+ @alarms.push(alarm)
14
+
15
+ alarm = CfnGuardian::Models::ElasticLoadBalancerAlarm.new(@resource)
16
+ alarm.name = 'UnHealthyHosts'
17
+ alarm.metric_name = 'UnHealthyHostCount'
18
+ alarm.threshold = 0
19
+ alarm.evaluation_periods = 10
20
+ alarm.treat_missing_data = 'notBreaching'
21
+ alarm.alarm_action = 'Warning'
22
+ @alarms.push(alarm)
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,45 @@
1
+ module CfnGuardian
2
+ module Resource
3
+ class ElastiCacheReplicationGroup < Base
4
+
5
+ def default_alarms
6
+ alarm = CfnGuardian::Models::ElastiCacheReplicationGroupAlarm.new(@resource)
7
+ alarm.name = 'FreeableMemoryWarning'
8
+ alarm.metric_name = 'FreeableMemory'
9
+ alarm.comparison_operator = 'LessThanThreshold'
10
+ alarm.threshold = 100000000
11
+ alarm.evaluation_periods = 10
12
+ alarm.alarm_action = 'Warning'
13
+ @alarms.push(alarm)
14
+
15
+ alarm = CfnGuardian::Models::ElastiCacheReplicationGroupAlarm.new(@resource)
16
+ alarm.name = 'CPUUtilizationWarning'
17
+ alarm.metric_name = 'CPUUtilization'
18
+ alarm.comparison_operator = 'GreaterThanThreshold'
19
+ alarm.statistic = 'Minimum'
20
+ alarm.threshold = 75
21
+ alarm.evaluation_periods = 10
22
+ alarm.alarm_action = 'Warning'
23
+ @alarms.push(alarm)
24
+
25
+ alarm = CfnGuardian::Models::ElastiCacheReplicationGroupAlarm.new(@resource)
26
+ alarm.name = 'CurrentConnectionsTask'
27
+ alarm.metric_name = 'CurrConnections'
28
+ alarm.comparison_operator = 'GreaterThanThreshold'
29
+ alarm.threshold = 50000
30
+ alarm.evaluation_periods = 10
31
+ alarm.alarm_action = 'Task'
32
+ @alarms.push(alarm)
33
+
34
+ alarm = CfnGuardian::Models::ElastiCacheReplicationGroupAlarm.new(@resource)
35
+ alarm.name = 'CurrentConnectionsCritical'
36
+ alarm.metric_name = 'CurrConnections'
37
+ alarm.comparison_operator = 'GreaterThanThreshold'
38
+ alarm.threshold = 60000
39
+ alarm.evaluation_periods = 10
40
+ @alarms.push(alarm)
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,49 @@
1
+ require 'digest/md5'
2
+
3
+ module CfnGuardian::Resource
4
+ class Http < Base
5
+
6
+ def default_alarms
7
+ alarm = CfnGuardian::Models::HttpAlarm.new(@resource)
8
+ alarm.name = 'EndpointAvailable'
9
+ alarm.metric_name = 'Available'
10
+ @alarms.push(alarm)
11
+
12
+ alarm = CfnGuardian::Models::HttpAlarm.new(@resource)
13
+ alarm.name = 'EndpointStatusCodeMatch'
14
+ alarm.metric_name = 'StatusCodeMatch'
15
+ @alarms.push(alarm)
16
+
17
+ alarm = CfnGuardian::Models::ElasticLoadBalancerAlarm.new(@resource)
18
+ alarm.name = 'EndpointTimeTaken'
19
+ alarm.metric_name = 'TimeTaken'
20
+ alarm.statistic = 'Minimum'
21
+ alarm.threshold = 1000
22
+ alarm.period = 300
23
+ alarm.evaluation_periods = 1
24
+ @alarms.push(alarm)
25
+
26
+ if @resource.has_key?('BodyRegex')
27
+ alarm = CfnGuardian::Models::HttpAlarm.new(@resource)
28
+ alarm.name = 'EndpointBodyRegexMatch'
29
+ alarm.metric_name = 'ResponseBodyRegexMatch'
30
+ @alarms.push(alarm)
31
+ end
32
+ end
33
+
34
+ def default_events()
35
+ @events.push(CfnGuardian::Models::HttpEvent.new(@resource))
36
+ if @resource.has_key?('Ssl') && @resource['Ssl']
37
+ @events.push(CfnGuardian::Models::SslEvent.new(@resource))
38
+ end
39
+ end
40
+
41
+ def default_checks()
42
+ @checks.push(CfnGuardian::Models::HttpCheck.new(@resource))
43
+ if @resource.has_key?('Ssl') && @resource['Ssl']
44
+ @checks.push(CfnGuardian::Models::SslCheck.new(@resource))
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,38 @@
1
+ module CfnGuardian::Resource
2
+ class Lambda < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::LambdaAlarm.new(@resource)
6
+ alarm.name = 'LambdaErrors'
7
+ alarm.metric_name = 'Errors'
8
+ alarm.threshold = 0.5
9
+ @alarms.push(alarm)
10
+
11
+ alarm = CfnGuardian::Models::LambdaAlarm.new(@resource)
12
+ alarm.name = 'Throttles'
13
+ alarm.metric_name = 'Throttles'
14
+ alarm.threshold = 0.5
15
+ @alarms.push(alarm)
16
+
17
+ alarm = CfnGuardian::Models::LambdaAlarm.new(@resource)
18
+ alarm.name = 'DeadLetterErrors'
19
+ alarm.metric_name = 'DeadLetterErrors'
20
+ alarm.threshold = 0.5
21
+ @alarms.push(alarm)
22
+
23
+ alarm = CfnGuardian::Models::LambdaAlarm.new(@resource)
24
+ alarm.name = 'IteratorAge'
25
+ alarm.metric_name = 'IteratorAge'
26
+ alarm.threshold = 600000
27
+ @alarms.push(alarm)
28
+
29
+ alarm = CfnGuardian::Models::LambdaAlarm.new(@resource)
30
+ alarm.name = 'Duration'
31
+ alarm.metric_name = 'Duration'
32
+ alarm.statistic = 'Average'
33
+ alarm.threshold = 30
34
+ @alarms.push(alarm)
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,31 @@
1
+ module CfnGuardian::Resource
2
+ class NetworkTargetGroup < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::NetworkTargetGroupAlarm.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::NetworkTargetGroupAlarm.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::NetworkTargetGroupAlarm.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,42 @@
1
+ require 'digest/md5'
2
+ require 'cfnguardian/string'
3
+
4
+ module CfnGuardian::Resource
5
+ class Nrpe < Base
6
+
7
+ def initialize(resource)
8
+ super(resource)
9
+ @resource_list = resource['Hosts']
10
+ @environment = resource['Environment']
11
+ end
12
+
13
+ def default_alarms()
14
+ @resource_list.each do |host|
15
+ host['Commands'].each do |command|
16
+ alarm = CfnGuardian::Models::NrpeAlarm.new(host,@environment)
17
+ alarm.name = "#{command.to_camelcase}Warning"
18
+ alarm.metric_name = command
19
+ @alarms.push(alarm)
20
+
21
+ alarm = CfnGuardian::Models::NrpeAlarm.new(host,@environment)
22
+ alarm.name = "#{command.to_camelcase}Critical"
23
+ alarm.metric_name = command
24
+ @alarms.push(alarm)
25
+ end
26
+ end
27
+ end
28
+
29
+ def default_events()
30
+ @resource_list.each do |host|
31
+ host['Commands'].each do |command|
32
+ @events.push(CfnGuardian::Models::NrpeEvent.new(host,@environment,command))
33
+ end
34
+ end
35
+ end
36
+
37
+ def default_checks()
38
+ @checks.push(CfnGuardian::Models::NrpeCheck.new(@resource))
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,30 @@
1
+ module CfnGuardian::Resource
2
+ class RDSClusterInstance < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::RDSClusterInstanceAlarm.new(@resource)
6
+ alarm.name = 'CPUUtilizationHighSpike'
7
+ alarm.metric_name = 'CPUUtilization'
8
+ alarm.threshold = 95
9
+ alarm.evaluation_periods = 10
10
+ @alarms.push(alarm)
11
+
12
+ alarm = CfnGuardian::Models::RDSClusterInstanceAlarm.new(@resource)
13
+ alarm.name = 'CPUUtilizationHighBase'
14
+ alarm.metric_name = 'CPUUtilization'
15
+ alarm.threshold = 75
16
+ alarm.evaluation_periods = 60
17
+ alarm.alarm_action = 'Warning'
18
+ @alarms.push(alarm)
19
+
20
+ alarm = CfnGuardian::Models::RDSClusterInstanceAlarm.new(@resource)
21
+ alarm.name = 'DatabaseConnections'
22
+ alarm.metric_name = 'DatabaseConnections'
23
+ alarm.statistic = 'Minimum'
24
+ alarm.threshold = 45
25
+ alarm.evaluation_periods = 10
26
+ @alarms.push(alarm)
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,45 @@
1
+ module CfnGuardian::Resource
2
+ class RDSInstance < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::RDSInstanceAlarm.new(@resource)
6
+ alarm.name = 'FreeStorageSpaceCritical'
7
+ alarm.metric_name = 'FreeStorageSpace'
8
+ alarm.threshold = 50000000000
9
+ alarm.evaluation_periods = 1
10
+ @alarms.push(alarm)
11
+
12
+ alarm = CfnGuardian::Models::RDSInstanceAlarm.new(@resource)
13
+ alarm.name = 'FreeStorageSpaceTask'
14
+ alarm.metric_name = 'FreeStorageSpace'
15
+ alarm.threshold = 100000000000
16
+ alarm.evaluation_periods = 1
17
+ alarm.alarm_action = 'Task'
18
+ @alarms.push(alarm)
19
+
20
+ alarm = CfnGuardian::Models::RDSInstanceAlarm.new(@resource)
21
+ alarm.name = 'CPUUtilizationHighSpike'
22
+ alarm.metric_name = 'CPUUtilization'
23
+ alarm.threshold = 95
24
+ alarm.evaluation_periods = 10
25
+ @alarms.push(alarm)
26
+
27
+ alarm = CfnGuardian::Models::RDSInstanceAlarm.new(@resource)
28
+ alarm.name = 'CPUUtilizationHighBase'
29
+ alarm.metric_name = 'CPUUtilization'
30
+ alarm.threshold = 75
31
+ alarm.evaluation_periods = 60
32
+ alarm.alarm_action = 'Warning'
33
+ @alarms.push(alarm)
34
+
35
+ alarm = CfnGuardian::Models::RDSInstanceAlarm.new(@resource)
36
+ alarm.name = 'DatabaseConnections'
37
+ alarm.metric_name = 'DatabaseConnections'
38
+ alarm.statistic = 'Minimum'
39
+ alarm.threshold = 45
40
+ alarm.evaluation_periods = 10
41
+ @alarms.push(alarm)
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,30 @@
1
+ module CfnGuardian::Resource
2
+ class RedshiftCluster < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::RedshiftClusterAlarm.new(@resource)
6
+ alarm.name = 'CPUUtilizationHighSpike'
7
+ alarm.metric_name = 'CPUUtilization'
8
+ alarm.threshold = 95
9
+ alarm.evaluation_periods = 10
10
+ @alarms.push(alarm)
11
+
12
+ alarm = CfnGuardian::Models::RedshiftClusterAlarm.new(@resource)
13
+ alarm.name = 'CPUUtilizationHighBase'
14
+ alarm.metric_name = 'CPUUtilization'
15
+ alarm.threshold = 75
16
+ alarm.evaluation_periods = 60
17
+ alarm.alarm_action = 'Warning'
18
+ @alarms.push(alarm)
19
+
20
+ alarm = CfnGuardian::Models::RedshiftClusterAlarm.new(@resource)
21
+ alarm.name = 'UnHealthyCluster'
22
+ alarm.metric_name = 'HealthStatus'
23
+ alarm.threshold = 0
24
+ alarm.evaluation_periods = 10
25
+ alarm.treat_missing_data = 'notBreaching'
26
+ @alarms.push(alarm)
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,37 @@
1
+ require 'digest/md5'
2
+ require 'cfnguardian/string'
3
+
4
+ module CfnGuardian::Resource
5
+ class Sql < Base
6
+
7
+ def initialize(resource)
8
+ super(resource)
9
+ @resource_list = resource['Hosts']
10
+ @environment = resource['Environment']
11
+ end
12
+
13
+ def default_alarms()
14
+ @resource_list.each do |host|
15
+ host['Queries'].each do |query|
16
+ alarm = CfnGuardian::Models::SqlAlarm.new(host)
17
+ alarm.name = query['MetricName']
18
+ alarm.metric_name = query['MetricName']
19
+ @alarms.push(alarm)
20
+ end
21
+ end
22
+ end
23
+
24
+ def default_events()
25
+ @resource_list.each do |host|
26
+ host['Queries'].each do |query|
27
+ @events.push(CfnGuardian::Models::SqlEvent.new(host,query['Query']))
28
+ end
29
+ end
30
+ end
31
+
32
+ def default_checks()
33
+ @checks.push(CfnGuardian::Models::SqlCheck.new(@resource))
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,23 @@
1
+ module CfnGuardian::Resource
2
+ class SQSQueue < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::SQSQueueAlarm.new(@resource)
6
+ alarm.name = 'ApproximateAgeOfOldestMessage'
7
+ alarm.metric_name = 'ApproximateAgeOfOldestMessage'
8
+ alarm.threshold = 0.5
9
+ alarm.evaluation_periods = 5
10
+ alarm.treat_missing_data = 'notBreaching'
11
+ @alarms.push(alarm)
12
+
13
+ alarm = CfnGuardian::Models::SQSQueueAlarm.new(@resource)
14
+ alarm.name = 'ApproximateNumberOfMessagesVisible'
15
+ alarm.metric_name = 'ApproximateNumberOfMessagesVisible'
16
+ alarm.threshold = 0.5
17
+ alarm.evaluation_periods = 5
18
+ alarm.treat_missing_data = 'notBreaching'
19
+ @alarms.push(alarm)
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,35 @@
1
+ require 'aws-sdk-s3'
2
+
3
+ module CfnGuardian
4
+ class S3
5
+ include Logging
6
+
7
+ attr_reader :bucket
8
+
9
+ def initialize(bucket)
10
+ @bucket = set_bucket_name(bucket)
11
+ end
12
+
13
+ def set_bucket_name(bucket)
14
+ if bucket.nil?
15
+ sts = Aws::STS::Client.new
16
+ account_id = sts.get_caller_identity().account
17
+ return "#{account_id}.#{Aws.config[:region]}.guardian.templates"
18
+ end
19
+ return bucket
20
+ end
21
+
22
+ def create_bucket_if_not_exists()
23
+ s3 = Aws::S3::Client.new
24
+ begin
25
+ s3.head_bucket(bucket: @bucket)
26
+ logger.info("Found bucket #{@bucket}")
27
+ rescue
28
+ logger.info("Creating bucket #{@bucket}")
29
+ s3.create_bucket(bucket: @bucket)
30
+ end
31
+ return bucket
32
+ end
33
+
34
+ end
35
+ end