cfn-guardian 0.1.0 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.dockerignore +1 -0
- data/Dockerfile +19 -0
- data/Gemfile.lock +31 -13
- data/README.md +441 -42
- data/cfn-guardian.gemspec +6 -2
- data/lib/cfnguardian.rb +301 -27
- data/lib/cfnguardian/cloudwatch.rb +121 -0
- data/lib/cfnguardian/codecommit.rb +54 -0
- data/lib/cfnguardian/codepipeline.rb +138 -0
- data/lib/cfnguardian/compile.rb +58 -17
- data/lib/cfnguardian/config/defaults.yaml +94 -0
- data/lib/cfnguardian/display_formatter.rb +164 -0
- data/lib/cfnguardian/drift.rb +79 -0
- data/lib/cfnguardian/log.rb +0 -1
- data/lib/cfnguardian/models/alarm.rb +98 -36
- data/lib/cfnguardian/models/check.rb +103 -26
- data/lib/cfnguardian/models/composite.rb +21 -0
- data/lib/cfnguardian/models/event.rb +164 -40
- data/lib/cfnguardian/models/metric_filter.rb +28 -0
- data/lib/cfnguardian/resources/application_targetgroup.rb +2 -0
- data/lib/cfnguardian/resources/base.rb +38 -16
- data/lib/cfnguardian/resources/ecs_service.rb +2 -2
- data/lib/cfnguardian/resources/http.rb +16 -1
- data/lib/cfnguardian/resources/internal_http.rb +74 -0
- data/lib/cfnguardian/resources/internal_port.rb +33 -0
- data/lib/cfnguardian/resources/internal_sftp.rb +58 -0
- data/lib/cfnguardian/resources/log_group.rb +26 -0
- data/lib/cfnguardian/resources/network_targetgroup.rb +1 -0
- data/lib/cfnguardian/resources/port.rb +25 -0
- data/lib/cfnguardian/resources/rds_instance.rb +2 -0
- data/lib/cfnguardian/resources/sftp.rb +50 -0
- data/lib/cfnguardian/resources/sql.rb +1 -1
- data/lib/cfnguardian/resources/tls.rb +66 -0
- data/lib/cfnguardian/s3.rb +3 -2
- data/lib/cfnguardian/stacks/main.rb +86 -65
- data/lib/cfnguardian/stacks/resources.rb +81 -42
- data/lib/cfnguardian/string.rb +12 -0
- data/lib/cfnguardian/version.rb +1 -1
- metadata +102 -5
@@ -8,7 +8,7 @@ module CfnGuardian
|
|
8
8
|
alarm.metric_name = 'MemoryUtilization'
|
9
9
|
alarm.comparison_operator = 'LessThanOrEqualToThreshold'
|
10
10
|
alarm.statistic = 'SampleCount'
|
11
|
-
alarm.threshold =
|
11
|
+
alarm.threshold = 0
|
12
12
|
alarm.evaluation_periods = 10
|
13
13
|
alarm.treat_missing_data = 'breaching'
|
14
14
|
alarm.datapoints_to_alarm = 8
|
@@ -19,7 +19,7 @@ module CfnGuardian
|
|
19
19
|
alarm.metric_name = 'MemoryUtilization'
|
20
20
|
alarm.comparison_operator = 'LessThanOrEqualToThreshold'
|
21
21
|
alarm.statistic = 'SampleCount'
|
22
|
-
alarm.threshold =
|
22
|
+
alarm.threshold = 1
|
23
23
|
alarm.evaluation_periods = 10
|
24
24
|
alarm.treat_missing_data = 'breaching'
|
25
25
|
alarm.datapoints_to_alarm = 8
|
@@ -14,8 +14,9 @@ module CfnGuardian::Resource
|
|
14
14
|
alarm.metric_name = 'StatusCodeMatch'
|
15
15
|
@alarms.push(alarm)
|
16
16
|
|
17
|
-
alarm = CfnGuardian::Models::
|
17
|
+
alarm = CfnGuardian::Models::HttpAlarm.new(@resource)
|
18
18
|
alarm.name = 'EndpointTimeTaken'
|
19
|
+
alarm.comparison_operator = 'GreaterThanThreshold'
|
19
20
|
alarm.metric_name = 'TimeTaken'
|
20
21
|
alarm.statistic = 'Minimum'
|
21
22
|
alarm.threshold = 1000
|
@@ -29,6 +30,20 @@ module CfnGuardian::Resource
|
|
29
30
|
alarm.metric_name = 'ResponseBodyRegexMatch'
|
30
31
|
@alarms.push(alarm)
|
31
32
|
end
|
33
|
+
|
34
|
+
if @resource.has_key?('Ssl') && @resource['Ssl']
|
35
|
+
alarm = CfnGuardian::Models::SslAlarm.new(@resource)
|
36
|
+
alarm.name = 'ExpiresInDaysCritical'
|
37
|
+
alarm.metric_name = 'ExpiresInDays'
|
38
|
+
alarm.threshold = 5
|
39
|
+
@alarms.push(alarm)
|
40
|
+
|
41
|
+
alarm = CfnGuardian::Models::SslAlarm.new(@resource)
|
42
|
+
alarm.name = 'ExpiresInDaysTask'
|
43
|
+
alarm.metric_name = 'ExpiresInDays'
|
44
|
+
alarm.threshold = 30
|
45
|
+
@alarms.push(alarm)
|
46
|
+
end
|
32
47
|
end
|
33
48
|
|
34
49
|
def default_events()
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
|
3
|
+
module CfnGuardian::Resource
|
4
|
+
class InternalHttp < Base
|
5
|
+
|
6
|
+
def initialize(resource)
|
7
|
+
super(resource)
|
8
|
+
@resource_list = resource['Hosts']
|
9
|
+
@environment = resource['Environment']
|
10
|
+
end
|
11
|
+
|
12
|
+
def default_alarms
|
13
|
+
@resource_list.each do |host|
|
14
|
+
alarm = CfnGuardian::Models::HttpAlarm.new(host)
|
15
|
+
alarm.name = 'EndpointAvailable'
|
16
|
+
alarm.metric_name = 'Available'
|
17
|
+
@alarms.push(alarm)
|
18
|
+
|
19
|
+
alarm = CfnGuardian::Models::HttpAlarm.new(host)
|
20
|
+
alarm.name = 'EndpointStatusCodeMatch'
|
21
|
+
alarm.metric_name = 'StatusCodeMatch'
|
22
|
+
@alarms.push(alarm)
|
23
|
+
|
24
|
+
alarm = CfnGuardian::Models::HttpAlarm.new(host)
|
25
|
+
alarm.name = 'EndpointTimeTaken'
|
26
|
+
alarm.comparison_operator = 'GreaterThanThreshold'
|
27
|
+
alarm.metric_name = 'TimeTaken'
|
28
|
+
alarm.statistic = 'Minimum'
|
29
|
+
alarm.threshold = 1000
|
30
|
+
alarm.period = 300
|
31
|
+
alarm.evaluation_periods = 1
|
32
|
+
@alarms.push(alarm)
|
33
|
+
|
34
|
+
if host.has_key?('BodyRegex')
|
35
|
+
alarm = CfnGuardian::Models::HttpAlarm.new(host)
|
36
|
+
alarm.name = 'EndpointBodyRegexMatch'
|
37
|
+
alarm.metric_name = 'ResponseBodyRegexMatch'
|
38
|
+
@alarms.push(alarm)
|
39
|
+
end
|
40
|
+
|
41
|
+
if host.has_key?('Ssl') && host['Ssl']
|
42
|
+
alarm = CfnGuardian::Models::SslAlarm.new(host)
|
43
|
+
alarm.name = 'ExpiresInDaysCritical'
|
44
|
+
alarm.metric_name = 'ExpiresInDays'
|
45
|
+
alarm.threshold = 5
|
46
|
+
@alarms.push(alarm)
|
47
|
+
|
48
|
+
alarm = CfnGuardian::Models::SslAlarm.new(host)
|
49
|
+
alarm.name = 'ExpiresInDaysTask'
|
50
|
+
alarm.metric_name = 'ExpiresInDays'
|
51
|
+
alarm.threshold = 30
|
52
|
+
@alarms.push(alarm)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def default_events()
|
58
|
+
@resource_list.each do |host|
|
59
|
+
@events.push(CfnGuardian::Models::InternalHttpEvent.new(host,@environment))
|
60
|
+
if host.has_key?('Ssl') && host['Ssl']
|
61
|
+
@events.push(CfnGuardian::Models::InternalSslEvent.new(host,@environment))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def default_checks()
|
67
|
+
@checks.push(CfnGuardian::Models::InternalHttpCheck.new(@resource))
|
68
|
+
if @resource_list.any? {|host| host.has_key?('Ssl') && host['Ssl'] }
|
69
|
+
@checks.push(CfnGuardian::Models::InternalSslCheck.new(@resource))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module CfnGuardian::Resource
|
2
|
+
class InternalPort < Base
|
3
|
+
|
4
|
+
def initialize(resource)
|
5
|
+
super(resource)
|
6
|
+
@resource_list = resource['Hosts']
|
7
|
+
@environment = resource['Environment']
|
8
|
+
end
|
9
|
+
|
10
|
+
def default_alarms
|
11
|
+
@resource_list.each do |host|
|
12
|
+
alarm = CfnGuardian::Models::PortAlarm.new(host)
|
13
|
+
alarm.name = 'EndpointAvailable'
|
14
|
+
alarm.metric_name = 'Available'
|
15
|
+
@alarms.push(alarm)
|
16
|
+
|
17
|
+
alarm = CfnGuardian::Models::PortAlarm.new(host)
|
18
|
+
alarm.name = 'EndpointTimeTaken'
|
19
|
+
alarm.metric_name = 'TimeTaken'
|
20
|
+
@alarms.push(alarm)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_events()
|
25
|
+
@resource_list.each {|host| @events.push(CfnGuardian::Models::InternalPortEvent.new(host,@environment))}
|
26
|
+
end
|
27
|
+
|
28
|
+
def default_checks()
|
29
|
+
@checks.push(CfnGuardian::Models::InternalPortCheck.new(@resource))
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module CfnGuardian::Resource
|
2
|
+
class InternalSFTP < Base
|
3
|
+
|
4
|
+
def initialize(resource)
|
5
|
+
super(resource)
|
6
|
+
@resource_list = resource['Hosts']
|
7
|
+
@environment = resource['Environment']
|
8
|
+
end
|
9
|
+
|
10
|
+
def default_alarms
|
11
|
+
@resource_list.each do |host|
|
12
|
+
alarm = CfnGuardian::Models::SFTPAlarm.new(host)
|
13
|
+
alarm.name = 'Available'
|
14
|
+
alarm.metric_name = 'Available'
|
15
|
+
@alarms.push(alarm)
|
16
|
+
|
17
|
+
alarm = CfnGuardian::Models::SFTPAlarm.new(host)
|
18
|
+
alarm.name = 'ConnectionTime'
|
19
|
+
alarm.metric_name = 'ConnectionTime'
|
20
|
+
alarm.comparison_operator = 'GreaterThanThreshold'
|
21
|
+
alarm.statistic = 'Minimum'
|
22
|
+
alarm.threshold = 1000
|
23
|
+
@alarms.push(alarm)
|
24
|
+
|
25
|
+
if host.has_key?('File')
|
26
|
+
alarm = CfnGuardian::Models::SFTPAlarm.new(host)
|
27
|
+
alarm.name = 'FileExists'
|
28
|
+
alarm.metric_name = 'FileExists'
|
29
|
+
@alarms.push(alarm)
|
30
|
+
|
31
|
+
alarm = CfnGuardian::Models::SFTPAlarm.new(host)
|
32
|
+
alarm.name = 'FileGetTime'
|
33
|
+
alarm.metric_name = 'FileGetTime'
|
34
|
+
alarm.comparison_operator = 'GreaterThanThreshold'
|
35
|
+
alarm.statistic = 'Minimum'
|
36
|
+
alarm.threshold = 1000
|
37
|
+
@alarms.push(alarm)
|
38
|
+
|
39
|
+
if host.has_key?('FileRegexMatch')
|
40
|
+
alarm = CfnGuardian::Models::SFTPAlarm.new(host)
|
41
|
+
alarm.name = 'FileBodyMatch'
|
42
|
+
alarm.metric_name = 'FileBodyMatch'
|
43
|
+
@alarms.push(alarm)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def default_events
|
50
|
+
@resource_list.each {|host| @events.push(CfnGuardian::Models::InternalSFTPEvent.new(host,@environment)) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def default_checks
|
54
|
+
@checks.push(CfnGuardian::Models::InternalSFTPCheck.new(@resource))
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module CfnGuardian::Resource
|
2
|
+
class LogGroup < Base
|
3
|
+
|
4
|
+
def initialize(resource)
|
5
|
+
super(resource)
|
6
|
+
@resource_list = resource['MetricFilters']
|
7
|
+
end
|
8
|
+
|
9
|
+
def default_alarms()
|
10
|
+
@resource_list.each do |filter|
|
11
|
+
alarm = CfnGuardian::Models::LogGroupAlarm.new(@resource)
|
12
|
+
alarm.name = filter['MetricName']
|
13
|
+
alarm.metric_name = filter['MetricName']
|
14
|
+
@alarms.push(alarm)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def default_metric_filters()
|
19
|
+
@resource_list.each do |filter|
|
20
|
+
metric_filter = CfnGuardian::Models::MetricFilter.new(@resource['Id'],filter)
|
21
|
+
@metric_filters.push(metric_filter)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -5,6 +5,7 @@ module CfnGuardian::Resource
|
|
5
5
|
alarm = CfnGuardian::Models::NetworkTargetGroupAlarm.new(@resource)
|
6
6
|
alarm.name = 'HealthyHosts'
|
7
7
|
alarm.metric_name = 'HealthyHostCount'
|
8
|
+
alarm.comparison_operator = 'LessThanThreshold'
|
8
9
|
alarm.statistic = 'Minimum'
|
9
10
|
alarm.threshold = 2
|
10
11
|
alarm.evaluation_periods = 1
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module CfnGuardian::Resource
|
2
|
+
class Port < Base
|
3
|
+
|
4
|
+
def default_alarms
|
5
|
+
alarm = CfnGuardian::Models::PortAlarm.new(@resource)
|
6
|
+
alarm.name = 'EndpointAvailable'
|
7
|
+
alarm.metric_name = 'Available'
|
8
|
+
@alarms.push(alarm)
|
9
|
+
|
10
|
+
alarm = CfnGuardian::Models::PortAlarm.new(@resource)
|
11
|
+
alarm.name = 'EndpointTimeTaken'
|
12
|
+
alarm.metric_name = 'TimeTaken'
|
13
|
+
@alarms.push(alarm)
|
14
|
+
end
|
15
|
+
|
16
|
+
def default_events()
|
17
|
+
@events.push(CfnGuardian::Models::PortEvent.new(@resource))
|
18
|
+
end
|
19
|
+
|
20
|
+
def default_checks()
|
21
|
+
@checks.push(CfnGuardian::Models::PortCheck.new(@resource))
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -7,6 +7,7 @@ module CfnGuardian::Resource
|
|
7
7
|
alarm.metric_name = 'FreeStorageSpace'
|
8
8
|
alarm.threshold = 50000000000
|
9
9
|
alarm.evaluation_periods = 1
|
10
|
+
alarm.comparison_operator = 'LessThanThreshold'
|
10
11
|
@alarms.push(alarm)
|
11
12
|
|
12
13
|
alarm = CfnGuardian::Models::RDSInstanceAlarm.new(@resource)
|
@@ -14,6 +15,7 @@ module CfnGuardian::Resource
|
|
14
15
|
alarm.metric_name = 'FreeStorageSpace'
|
15
16
|
alarm.threshold = 100000000000
|
16
17
|
alarm.evaluation_periods = 1
|
18
|
+
alarm.comparison_operator = 'LessThanThreshold'
|
17
19
|
alarm.alarm_action = 'Task'
|
18
20
|
@alarms.push(alarm)
|
19
21
|
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module CfnGuardian::Resource
|
2
|
+
class SFTP < Base
|
3
|
+
|
4
|
+
def default_alarms
|
5
|
+
alarm = CfnGuardian::Models::SFTPAlarm.new(@resource)
|
6
|
+
alarm.name = 'Available'
|
7
|
+
alarm.metric_name = 'Available'
|
8
|
+
@alarms.push(alarm)
|
9
|
+
|
10
|
+
alarm = CfnGuardian::Models::SFTPAlarm.new(@resource)
|
11
|
+
alarm.name = 'ConnectionTime'
|
12
|
+
alarm.metric_name = 'ConnectionTime'
|
13
|
+
alarm.comparison_operator = 'GreaterThanThreshold'
|
14
|
+
alarm.statistic = 'Minimum'
|
15
|
+
alarm.threshold = 1000
|
16
|
+
@alarms.push(alarm)
|
17
|
+
|
18
|
+
if @resource.has_key?('File')
|
19
|
+
alarm = CfnGuardian::Models::SFTPAlarm.new(@resource)
|
20
|
+
alarm.name = 'FileExists'
|
21
|
+
alarm.metric_name = 'FileExists'
|
22
|
+
@alarms.push(alarm)
|
23
|
+
|
24
|
+
alarm = CfnGuardian::Models::SFTPAlarm.new(@resource)
|
25
|
+
alarm.name = 'FileGetTime'
|
26
|
+
alarm.metric_name = 'FileGetTime'
|
27
|
+
alarm.comparison_operator = 'GreaterThanThreshold'
|
28
|
+
alarm.statistic = 'Minimum'
|
29
|
+
alarm.threshold = 1000
|
30
|
+
@alarms.push(alarm)
|
31
|
+
|
32
|
+
if @resource.has_key?('FileRegexMatch')
|
33
|
+
alarm = CfnGuardian::Models::SFTPAlarm.new(@resource)
|
34
|
+
alarm.name = 'FileBodyMatch'
|
35
|
+
alarm.metric_name = 'FileBodyMatch'
|
36
|
+
@alarms.push(alarm)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def default_events
|
42
|
+
@events.push(CfnGuardian::Models::SFTPEvent.new(@resource))
|
43
|
+
end
|
44
|
+
|
45
|
+
def default_checks
|
46
|
+
@checks.push(CfnGuardian::Models::SFTPCheck.new(@resource))
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -24,7 +24,7 @@ module CfnGuardian::Resource
|
|
24
24
|
def default_events()
|
25
25
|
@resource_list.each do |host|
|
26
26
|
host['Queries'].each do |query|
|
27
|
-
@events.push(CfnGuardian::Models::SqlEvent.new(host,query['Query']))
|
27
|
+
@events.push(CfnGuardian::Models::SqlEvent.new(host,query['Query'],@environment))
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module CfnGuardian::Resource
|
2
|
+
class TLS < Base
|
3
|
+
|
4
|
+
def default_alarms
|
5
|
+
|
6
|
+
versions = @resource.fetch('Versions',['SSLv2','SSLv3','TLSv1','TLSv1.1','TLSv1.2'])
|
7
|
+
|
8
|
+
if versions.include? "SSLv2"
|
9
|
+
alarm = CfnGuardian::Models::TLSAlarm.new(@resource)
|
10
|
+
alarm.name = "TLSVersionSSLv2"
|
11
|
+
alarm.metric_name = "SSLv2"
|
12
|
+
alarm.comparison_operator = 'GreaterThanThreshold'
|
13
|
+
alarm.threshold = 0
|
14
|
+
@alarms.push(alarm)
|
15
|
+
end
|
16
|
+
|
17
|
+
if versions.include? "SSLv3"
|
18
|
+
alarm = CfnGuardian::Models::TLSAlarm.new(@resource)
|
19
|
+
alarm.name = "TLSVersionSSLv3"
|
20
|
+
alarm.metric_name = "SSLv3"
|
21
|
+
alarm.comparison_operator = 'GreaterThanThreshold'
|
22
|
+
alarm.threshold = 0
|
23
|
+
@alarms.push(alarm)
|
24
|
+
end
|
25
|
+
|
26
|
+
if versions.include? "SSLv3"
|
27
|
+
alarm = CfnGuardian::Models::TLSAlarm.new(@resource)
|
28
|
+
alarm.name = "TLSVersionTLSv1"
|
29
|
+
alarm.metric_name = "TLSv1"
|
30
|
+
@alarms.push(alarm)
|
31
|
+
end
|
32
|
+
|
33
|
+
if versions.include? "SSLv3"
|
34
|
+
alarm = CfnGuardian::Models::TLSAlarm.new(@resource)
|
35
|
+
alarm.name = "TLSVersionTLSv1.1"
|
36
|
+
alarm.metric_name = "TLSv1.1"
|
37
|
+
@alarms.push(alarm)
|
38
|
+
end
|
39
|
+
|
40
|
+
if versions.include? "SSLv3"
|
41
|
+
alarm = CfnGuardian::Models::TLSAlarm.new(@resource)
|
42
|
+
alarm.name = "TLSVersionTLSv1.2"
|
43
|
+
alarm.metric_name = "TLSv1.2"
|
44
|
+
@alarms.push(alarm)
|
45
|
+
end
|
46
|
+
|
47
|
+
if @resource.has_key?('CheckMax')
|
48
|
+
alarm = CfnGuardian::Models::TLSAlarm.new(@resource)
|
49
|
+
alarm.name = "TLSVersionMax"
|
50
|
+
alarm.metric_name = 'MaxVersion'
|
51
|
+
alarm.threshold = 3
|
52
|
+
alarm.evaluation_periods = 2
|
53
|
+
@alarms.push(alarm)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def default_events
|
58
|
+
@events.push(CfnGuardian::Models::TLSEvent.new(@resource))
|
59
|
+
end
|
60
|
+
|
61
|
+
def default_checks
|
62
|
+
@checks.push(CfnGuardian::Models::TLSCheck.new(@resource))
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
data/lib/cfnguardian/s3.rb
CHANGED
@@ -4,10 +4,11 @@ module CfnGuardian
|
|
4
4
|
class S3
|
5
5
|
include Logging
|
6
6
|
|
7
|
-
attr_reader :bucket
|
7
|
+
attr_reader :bucket, :path
|
8
8
|
|
9
|
-
def initialize(bucket)
|
9
|
+
def initialize(bucket,path='')
|
10
10
|
@bucket = set_bucket_name(bucket)
|
11
|
+
@path = path
|
11
12
|
end
|
12
13
|
|
13
14
|
def set_bucket_name(bucket)
|
@@ -5,31 +5,87 @@ module CfnGuardian
|
|
5
5
|
class Main
|
6
6
|
include CfnDsl::CloudFormation
|
7
7
|
|
8
|
-
|
8
|
+
attr_reader :parameters, :template
|
9
|
+
|
10
|
+
def initialize()
|
11
|
+
@parameters = []
|
9
12
|
@template = CloudFormation("Guardian main stack")
|
10
|
-
|
13
|
+
end
|
14
|
+
|
15
|
+
def build_template(stacks,checks,topics,maintenance_groups,ssm_parameters)
|
16
|
+
parameters = {}
|
17
|
+
|
11
18
|
%w(Critical Warning Task Informational).each do |name|
|
12
19
|
parameter = @template.Parameter(name)
|
13
20
|
parameter.Type 'String'
|
14
21
|
parameter.Description "SNS topic ARN for #{name} notifications"
|
22
|
+
parameter.Default topics[name] if topics.has_key?(name)
|
23
|
+
parameters[name] = Ref(name)
|
15
24
|
end
|
16
25
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
26
|
+
maintenance_groups.each do |group|
|
27
|
+
topic = @template.SNS_Topic(group)
|
28
|
+
topic.TopicName group
|
29
|
+
topic.Tags([{ Key: 'Environment', Value: 'guardian' }])
|
30
|
+
parameters[group] = Ref(group)
|
31
|
+
end
|
23
32
|
|
24
|
-
|
33
|
+
add_iam_role(ssm_parameters)
|
25
34
|
|
26
|
-
checks.each {|check| parameters["#{check
|
35
|
+
checks.each {|check| parameters["#{check.name}Function#{check.environment}"] = add_lambda(check)}
|
27
36
|
stacks.each {|stack| add_stack(stack['Name'],stack['TemplateURL'],parameters)}
|
28
37
|
|
29
|
-
|
38
|
+
@parameters = parameters.keys
|
30
39
|
end
|
31
40
|
|
32
|
-
def
|
41
|
+
def add_iam_role(ssm_parameters)
|
42
|
+
policies = []
|
43
|
+
policies << {
|
44
|
+
PolicyName: 'logging',
|
45
|
+
PolicyDocument: {
|
46
|
+
Version: '2012-10-17',
|
47
|
+
Statement: [{
|
48
|
+
Effect: 'Allow',
|
49
|
+
Action: [ 'logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents' ],
|
50
|
+
Resource: 'arn:aws:logs:*:*:*'
|
51
|
+
}]
|
52
|
+
}
|
53
|
+
}
|
54
|
+
policies << {
|
55
|
+
PolicyName: 'metrics',
|
56
|
+
PolicyDocument: {
|
57
|
+
Version: '2012-10-17',
|
58
|
+
Statement: [{
|
59
|
+
Effect: 'Allow',
|
60
|
+
Action: [ 'cloudwatch:PutMetricData' ],
|
61
|
+
Resource: '*'
|
62
|
+
}]
|
63
|
+
}
|
64
|
+
}
|
65
|
+
policies << {
|
66
|
+
PolicyName: 'attach-network-interface',
|
67
|
+
PolicyDocument: {
|
68
|
+
Version: '2012-10-17',
|
69
|
+
Statement: [{
|
70
|
+
Effect: 'Allow',
|
71
|
+
Action: [ 'ec2:CreateNetworkInterface', 'ec2:DescribeNetworkInterfaces', 'ec2:DeleteNetworkInterface' ],
|
72
|
+
Resource: '*'
|
73
|
+
}]
|
74
|
+
}
|
75
|
+
}
|
76
|
+
if ssm_parameters.any?
|
77
|
+
policies << {
|
78
|
+
PolicyName: 'ssm-parameters',
|
79
|
+
PolicyDocument: {
|
80
|
+
Version: '2012-10-17',
|
81
|
+
Statement: [{
|
82
|
+
Effect: 'Allow',
|
83
|
+
Action: [ 'ssm:GetParameter', 'ssm:GetParametersByPath', 'ssm:GetParameters' ],
|
84
|
+
Resource: ssm_parameters.map {|param| FnSub("arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter#{param}") }
|
85
|
+
}]
|
86
|
+
}
|
87
|
+
}
|
88
|
+
end
|
33
89
|
@template.declare do
|
34
90
|
IAM_Role(:LambdaExecutionRole) do
|
35
91
|
AssumeRolePolicyDocument({
|
@@ -40,42 +96,8 @@ module CfnGuardian
|
|
40
96
|
Action: [ 'sts:AssumeRole' ]
|
41
97
|
}]
|
42
98
|
})
|
43
|
-
Path '/'
|
44
|
-
Policies(
|
45
|
-
{
|
46
|
-
PolicyName: 'logging',
|
47
|
-
PolicyDocument: {
|
48
|
-
Version: '2012-10-17',
|
49
|
-
Statement: [{
|
50
|
-
Effect: 'Allow',
|
51
|
-
Action: [ 'logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents' ],
|
52
|
-
Resource: 'arn:aws:logs:*:*:*'
|
53
|
-
}]
|
54
|
-
}
|
55
|
-
},
|
56
|
-
{
|
57
|
-
PolicyName: 'metrics',
|
58
|
-
PolicyDocument: {
|
59
|
-
Version: '2012-10-17',
|
60
|
-
Statement: [{
|
61
|
-
Effect: 'Allow',
|
62
|
-
Action: [ 'cloudwatch:PutMetricData' ],
|
63
|
-
Resource: '*'
|
64
|
-
}]
|
65
|
-
}
|
66
|
-
},
|
67
|
-
{
|
68
|
-
PolicyName: 'attach-network-interface',
|
69
|
-
PolicyDocument: {
|
70
|
-
Version: '2012-10-17',
|
71
|
-
Statement: [{
|
72
|
-
Effect: 'Allow',
|
73
|
-
Action: [ 'ec2:CreateNetworkInterface', 'ec2:DescribeNetworkInterfaces', 'ec2:DeleteNetworkInterface' ],
|
74
|
-
Resource: '*'
|
75
|
-
}]
|
76
|
-
}
|
77
|
-
}
|
78
|
-
])
|
99
|
+
Path '/guardian/'
|
100
|
+
Policies(policies)
|
79
101
|
Tags([
|
80
102
|
{ Key: 'Name', Value: 'guardian-lambda-role' },
|
81
103
|
{ Key: 'Environment', Value: 'guardian' }
|
@@ -86,49 +108,48 @@ module CfnGuardian
|
|
86
108
|
|
87
109
|
def add_lambda(check)
|
88
110
|
vpc_config = {}
|
89
|
-
|
90
|
-
if check.has_key?(:vpc)
|
111
|
+
if !check.vpc.nil?
|
91
112
|
@template.declare do
|
92
|
-
EC2_SecurityGroup("#{check
|
93
|
-
VpcId check
|
94
|
-
GroupDescription "Guardian lambda function #{check
|
113
|
+
EC2_SecurityGroup("#{check.name}SecurityGroup#{check.environment}") do
|
114
|
+
VpcId check.vpc
|
115
|
+
GroupDescription "Guardian lambda function #{check.group} check"
|
95
116
|
Tags([
|
96
|
-
{ Key: 'Name', Value: "guardian-#{check
|
117
|
+
{ Key: 'Name', Value: "guardian-#{check.name}-#{check.environment}" },
|
97
118
|
{ Key: 'Environment', Value: 'guardian' }
|
98
119
|
])
|
99
120
|
end
|
100
121
|
end
|
101
122
|
|
102
|
-
vpc_config[:SecurityGroupIds] = Ref("#{check
|
103
|
-
vpc_config[:SubnetIds] = check
|
123
|
+
vpc_config[:SecurityGroupIds] = [Ref("#{check.name}SecurityGroup#{check.environment}")]
|
124
|
+
vpc_config[:SubnetIds] = check.subnets
|
104
125
|
end
|
105
126
|
|
106
127
|
@template.declare do
|
107
|
-
Lambda_Function("#{check
|
128
|
+
Lambda_Function("#{check.name}Function#{check.environment}") do
|
108
129
|
Code({
|
109
|
-
S3Bucket: FnSub("base2.lambda.${AWS::Region}"),
|
110
|
-
S3Key: "#{check
|
130
|
+
S3Bucket: FnSub("base2.guardian.lambda.checks.${AWS::Region}"),
|
131
|
+
S3Key: "#{check.package}/master/#{check.version}.zip"
|
111
132
|
})
|
112
|
-
Handler check
|
133
|
+
Handler check.handler
|
113
134
|
MemorySize 128
|
114
|
-
Runtime check
|
135
|
+
Runtime check.runtime
|
115
136
|
Timeout 120
|
116
137
|
Role FnGetAtt(:LambdaExecutionRole, :Arn)
|
117
138
|
VpcConfig vpc_config unless vpc_config.empty?
|
118
139
|
Tags([
|
119
|
-
{ Key: 'Name', Value: "guardian-#{check
|
140
|
+
{ Key: 'Name', Value: "guardian-#{check.name}-#{check.group}" },
|
120
141
|
{ Key: 'Environment', Value: 'guardian' }
|
121
142
|
])
|
122
143
|
end
|
123
144
|
|
124
|
-
Lambda_Permission("#{check
|
125
|
-
FunctionName Ref("#{check
|
145
|
+
Lambda_Permission("#{check.name}Permissions#{check.environment}") do
|
146
|
+
FunctionName Ref("#{check.name}Function#{check.environment}")
|
126
147
|
Action 'lambda:InvokeFunction'
|
127
148
|
Principal 'events.amazonaws.com'
|
128
149
|
end
|
129
150
|
end
|
130
151
|
|
131
|
-
return FnGetAtt("#{check
|
152
|
+
return FnGetAtt("#{check.name}Function#{check.environment}", :Arn)
|
132
153
|
end
|
133
154
|
|
134
155
|
def add_stack(name,url,stack_parameters)
|