cfn-guardian 0.1.0 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +1 -0
  3. data/.github/workflows/build-gem.yml +25 -0
  4. data/.github/workflows/release-gem.yml +25 -0
  5. data/.github/workflows/release-image.yml +33 -0
  6. data/.rspec +1 -0
  7. data/Dockerfile +19 -0
  8. data/Gemfile.lock +39 -21
  9. data/README.md +9 -378
  10. data/cfn-guardian.gemspec +7 -5
  11. data/docs/alarm_templates.md +130 -0
  12. data/docs/cli.md +182 -0
  13. data/docs/composite_alarms.md +24 -0
  14. data/docs/custom_checks/azure_file_check.md +28 -0
  15. data/docs/custom_checks/domain_expiry.md +10 -0
  16. data/docs/custom_checks/http.md +59 -0
  17. data/docs/custom_checks/log_group_metric_filters.md +27 -0
  18. data/docs/custom_checks/nrpe.md +29 -0
  19. data/docs/custom_checks/port.md +40 -0
  20. data/docs/custom_checks/sftp.md +73 -0
  21. data/docs/custom_checks/sql.md +44 -0
  22. data/docs/custom_checks/tls.md +25 -0
  23. data/docs/custom_metrics.md +71 -0
  24. data/docs/event_subscriptions.md +67 -0
  25. data/docs/maintenance_mode.md +85 -0
  26. data/docs/notifiers.md +33 -0
  27. data/docs/overview.md +22 -0
  28. data/docs/resources.md +93 -0
  29. data/docs/variables.md +58 -0
  30. data/lib/cfnguardian.rb +325 -37
  31. data/lib/cfnguardian/cloudwatch.rb +132 -0
  32. data/lib/cfnguardian/codecommit.rb +54 -0
  33. data/lib/cfnguardian/codepipeline.rb +138 -0
  34. data/lib/cfnguardian/compile.rb +142 -18
  35. data/lib/cfnguardian/config/defaults.yaml +103 -0
  36. data/lib/cfnguardian/deploy.rb +2 -16
  37. data/lib/cfnguardian/display_formatter.rb +163 -0
  38. data/lib/cfnguardian/drift.rb +79 -0
  39. data/lib/cfnguardian/error.rb +4 -0
  40. data/lib/cfnguardian/log.rb +0 -1
  41. data/lib/cfnguardian/models/alarm.rb +193 -59
  42. data/lib/cfnguardian/models/check.rb +128 -33
  43. data/lib/cfnguardian/models/composite.rb +21 -0
  44. data/lib/cfnguardian/models/event.rb +201 -49
  45. data/lib/cfnguardian/models/event_subscription.rb +96 -0
  46. data/lib/cfnguardian/models/metric_filter.rb +28 -0
  47. data/lib/cfnguardian/resources/amazonmq_rabbitmq.rb +136 -0
  48. data/lib/cfnguardian/resources/application_targetgroup.rb +2 -0
  49. data/lib/cfnguardian/resources/azure_file.rb +20 -0
  50. data/lib/cfnguardian/resources/base.rb +155 -33
  51. data/lib/cfnguardian/resources/ec2_instance.rb +11 -0
  52. data/lib/cfnguardian/resources/ecs_service.rb +2 -2
  53. data/lib/cfnguardian/resources/http.rb +17 -1
  54. data/lib/cfnguardian/resources/internal_http.rb +74 -0
  55. data/lib/cfnguardian/resources/internal_port.rb +33 -0
  56. data/lib/cfnguardian/resources/internal_sftp.rb +58 -0
  57. data/lib/cfnguardian/resources/log_group.rb +26 -0
  58. data/lib/cfnguardian/resources/network_targetgroup.rb +1 -0
  59. data/lib/cfnguardian/resources/port.rb +25 -0
  60. data/lib/cfnguardian/resources/rds_cluster.rb +14 -0
  61. data/lib/cfnguardian/resources/rds_instance.rb +73 -0
  62. data/lib/cfnguardian/resources/redshift_cluster.rb +2 -2
  63. data/lib/cfnguardian/resources/sftp.rb +50 -0
  64. data/lib/cfnguardian/resources/sql.rb +3 -3
  65. data/lib/cfnguardian/resources/tls.rb +66 -0
  66. data/lib/cfnguardian/s3.rb +3 -2
  67. data/lib/cfnguardian/stacks/main.rb +94 -72
  68. data/lib/cfnguardian/stacks/resources.rb +111 -43
  69. data/lib/cfnguardian/string.rb +12 -0
  70. data/lib/cfnguardian/version.rb +1 -1
  71. metadata +133 -10
@@ -4,8 +4,8 @@ require 'cfnguardian/string'
4
4
  module CfnGuardian::Resource
5
5
  class Sql < Base
6
6
 
7
- def initialize(resource)
8
- super(resource)
7
+ def initialize(resource, override_group = nil)
8
+ super(resource, override_group)
9
9
  @resource_list = resource['Hosts']
10
10
  @environment = resource['Environment']
11
11
  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
@@ -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
- def build_template(stacks,checks)
8
+ attr_reader :parameters, :template
9
+
10
+ def initialize()
11
+ @parameters = []
9
12
  @template = CloudFormation("Guardian main stack")
10
-
11
- %w(Critical Warning Task Informational).each do |name|
13
+ end
14
+
15
+ def build_template(stacks,checks,topics,maintenance_groups,ssm_parameters)
16
+ parameters = {}
17
+
18
+ topics.each do |name, sns|
12
19
  parameter = @template.Parameter(name)
13
20
  parameter.Type 'String'
14
21
  parameter.Description "SNS topic ARN for #{name} notifications"
22
+ parameter.Default sns
23
+ parameters[name] = Ref(name)
15
24
  end
16
25
 
17
- parameters = {
18
- Critical: Ref(:Critical),
19
- Warning: Ref(:Warning),
20
- Task: Ref(:Task),
21
- Informational: Ref(:Informational)
22
- }
23
-
24
- build_iam_role()
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
25
32
 
26
- checks.each {|check| parameters["#{check[:name]}Function#{check[:environment]}"] = add_lambda(check)}
27
- stacks.each {|stack| add_stack(stack['Name'],stack['TemplateURL'],parameters)}
33
+ add_iam_role(ssm_parameters)
34
+
35
+ checks.each {|check| parameters["#{check.name}Function#{check.environment}"] = add_lambda(check)}
36
+ stacks.each {|stack| add_stack(stack['Name'],stack['TemplateURL'],parameters,stack['Reference'])}
28
37
 
29
- return @template
38
+ @parameters = parameters.keys
30
39
  end
31
40
 
32
- def build_iam_role()
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,59 +108,59 @@ 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[:name]}SecurityGroup#{check[:environment]}") do
93
- VpcId check[:vpc]
94
- GroupDescription "Guardian lambda function #{check[:class]} 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[:name]}-#{check[:environment]}" },
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[:name]}SecurityGroup#{check[:environment]}")
103
- vpc_config[:SubnetIds] = check[:subnets]
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[:name]}Function#{check[:environment]}") do
128
+ Lambda_Function("#{check.name}Function#{check.environment}") do
108
129
  Code({
109
- S3Bucket: FnSub("base2.lambda.${AWS::Region}"),
110
- S3Key: "#{check[:package]}/#{check[:version]}/handler.zip"
130
+ S3Bucket: FnSub("base2.guardian.lambda.checks.${AWS::Region}"),
131
+ S3Key: "#{check.package}/master/#{check.version}.zip"
111
132
  })
112
- Handler check[:handler]
113
- MemorySize 128
114
- Runtime check[:runtime]
115
- Timeout 120
133
+ Handler check.handler
134
+ MemorySize check.memory
135
+ Runtime check.runtime
136
+ Timeout check.timeout
116
137
  Role FnGetAtt(:LambdaExecutionRole, :Arn)
117
138
  VpcConfig vpc_config unless vpc_config.empty?
118
139
  Tags([
119
- { Key: 'Name', Value: "guardian-#{check[:name]}-#{check[:class]}" },
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[:name]}Permissions#{check[:environment]}") do
125
- FunctionName Ref("#{check[:name]}Function#{check[:environment]}")
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[:name]}Function#{check[:environment]}", :Arn)
152
+ return FnGetAtt("#{check.name}Function#{check.environment}", :Arn)
132
153
  end
133
154
 
134
- def add_stack(name,url,stack_parameters)
155
+ def add_stack(name,url,stack_parameters,stack_id)
135
156
  @template.declare do
136
157
  CloudFormation_Stack(name) do
137
158
  Parameters stack_parameters
138
159
  TemplateURL url
139
160
  TimeoutInMinutes 15
140
161
  Tags([
141
- { Key: 'Name', Value: "guardian-stack-#{name}" }
162
+ { Key: 'Name', Value: "guardian-stack-#{name}" },
163
+ { Key: 'guardian:stack-id', Value: "stk#{stack_id}"}
142
164
  ])
143
165
  end
144
166
  end
@@ -1,80 +1,148 @@
1
1
  require 'cfndsl'
2
+ require 'digest/md5'
3
+ require 'cfnguardian/cloudwatch'
2
4
 
3
5
  module CfnGuardian
4
6
  module Stacks
5
7
  class Resources
6
8
  include CfnDsl::CloudFormation
7
9
 
8
- def build_template(resources)
9
- @template = CloudFormation("Guardian nested stack")
10
-
11
- %w(Critical Warning Task Informational).each do |name|
10
+ attr_reader :template
11
+
12
+ def initialize(parameters,stack_id)
13
+ @stack_id = stack_id
14
+
15
+ @template = CloudFormation("Guardian nested - stack-id:stk#{@stack_id}")
16
+ parameters.each do |name|
12
17
  parameter = @template.Parameter(name)
13
18
  parameter.Type 'String'
14
- parameter.Description "SNS topic ARN for #{name} notifications"
15
19
  end
16
-
20
+ end
21
+
22
+ def build_template(resources)
17
23
  resources.each do |resource|
18
- case resource[:type]
24
+ case resource.type
19
25
  when 'Alarm'
20
26
  add_alarm(resource)
21
27
  when 'Event'
22
28
  add_event(resource)
29
+ when 'Composite'
30
+ add_composite_alarm(resource)
31
+ when 'MetricFilter'
32
+ add_metric_filter(resource)
33
+ when 'EventSubscription'
34
+ add_event_subscription(resource)
23
35
  else
24
- puts "Warn: #{resource[:type]} is a unsuported resource type"
36
+ puts "Warn: #{resource.type} is a unsuported resource type"
25
37
  end
26
38
  end
27
-
28
- return @template
29
39
  end
30
-
31
- def add_alarm(resource)
40
+
41
+ def add_alarm(alarm)
42
+ actions = alarm.alarm_action.kind_of?(Array) ? alarm.alarm_action.map{|action| Ref(action)} : [Ref(alarm.alarm_action)]
43
+ actions.concat alarm.maintenance_groups.map {|mg| Ref(mg)} if alarm.maintenance_groups.any?
44
+ stack_id = @stack_id
45
+
32
46
  @template.declare do
33
- CloudWatch_Alarm("#{resource[:resource_name]}#{resource[:class]}#{resource[:name]}#{resource[:type]}"[0..255]) do
47
+ CloudWatch_Alarm("#{alarm.resource_hash}#{alarm.group}#{alarm.name.gsub(/[^0-9a-zA-Z]/i, '')}#{alarm.type}"[0..255]) do
34
48
  ActionsEnabled true
35
- AlarmDescription "Guardian alarm #{resource[:class]} #{resource[:resource]} #{resource[:name]}"
36
- AlarmName "#{resource[:class]}-#{resource[:resource]}-#{resource[:name]}"
37
- ComparisonOperator resource[:comparison_operator]
38
- Dimensions resource[:dimensions].map {|k,v| {Name: k, Value: v}}
39
- EvaluationPeriods resource[:evaluation_periods]
40
- Statistic resource[:statistic]
41
- Period resource[:period]
42
- Threshold resource[:threshold]
43
- MetricName resource[:metric_name]
44
- Namespace resource[:namespace]
45
- AlarmActions [Ref(resource[:alarm_action])]
46
- OKActions [Ref(resource[:alarm_action])]
47
- TreatMissingData resource[:treat_missing_data] unless resource[:treat_missing_data].nil?
48
- DatapointsToAlarm resource[:datapoints_to_alarm] unless resource[:datapoints_to_alarm].nil?
49
- ExtendedStatistic resource[:extended_statistic] unless resource[:extended_statistic].nil?
50
- EvaluateLowSampleCountPercentile resource[:evaluate_low_sample_count_percentile] unless resource[:evaluate_low_sample_count_percentile].nil?
51
- Unit resource[:unit] unless resource[:unit].nil?
49
+ AlarmDescription "Guardian alarm #{alarm.name} for the resource #{alarm.resource_id} in alarm group #{alarm.group}"
50
+ AlarmName CfnGuardian::CloudWatch.get_alarm_name(alarm) + "-stk#{stack_id}"
51
+ ComparisonOperator alarm.comparison_operator
52
+ Dimensions alarm.dimensions.map {|k,v| {Name: k, Value: v}} unless alarm.dimensions.nil?
53
+ EvaluationPeriods alarm.evaluation_periods
54
+ Statistic alarm.statistic if alarm.extended_statistic.nil?
55
+ Period alarm.period
56
+ Threshold alarm.threshold
57
+ MetricName alarm.metric_name
58
+ Namespace alarm.namespace
59
+ AlarmActions actions
60
+ OKActions actions
61
+ TreatMissingData alarm.treat_missing_data unless alarm.treat_missing_data.nil?
62
+ DatapointsToAlarm alarm.datapoints_to_alarm unless alarm.datapoints_to_alarm.nil?
63
+ ExtendedStatistic alarm.extended_statistic unless alarm.extended_statistic.nil?
64
+ EvaluateLowSampleCountPercentile alarm.evaluate_low_sample_count_percentile unless alarm.evaluate_low_sample_count_percentile.nil?
65
+ Unit alarm.unit unless alarm.unit.nil?
52
66
  end
53
67
  end
54
68
  end
55
69
 
56
- def add_event(resource)
57
- @template.declare do
58
- Parameter(resource[:target]) do
59
- Type 'String'
60
- Description "Lamba funtion Arn for #{resource[:class]} #{resource[:type]}"
61
- end
62
-
63
- Events_Rule("#{resource[:class]}#{resource[:type]}#{resource[:hash]}"[0..255]) do
70
+ def add_event(event)
71
+ @template.declare do
72
+ Events_Rule("#{event.group}#{event.type}#{event.hash}"[0..255]) do
64
73
  State 'ENABLED'
65
- Description "Guardian scheduled #{resource[:class]} #{resource[:type]}"
66
- ScheduleExpression "cron(#{resource[:cron]})"
74
+ Description "Guardian scheduled #{event.group} #{event.type}"
75
+ ScheduleExpression "cron(#{event.cron})"
67
76
  Targets([
68
77
  {
69
- Arn: Ref(resource[:target]),
70
- Id: resource[:hash],
71
- Input: FnSub(resource[:payload])
78
+ Arn: Ref(event.target),
79
+ Id: event.hash,
80
+ Input: FnSub(event.payload)
72
81
  }
73
82
  ])
74
83
  end
75
84
  end
76
85
  end
77
86
 
87
+ def add_composite_alarm(alarm)
88
+ stack_id = @stack_id
89
+
90
+ @template.declare do
91
+ CloudWatch_CompositeAlarm(alarm.name.gsub(/[^0-9a-zA-Z]/i, '')) do
92
+
93
+ AlarmDescription alarm.description
94
+ AlarmName "guardian-#{alarm.name}-stk#{stack_id}"
95
+ AlarmRule alarm.rule
96
+
97
+ unless alarm.alarm_action.nil?
98
+ ActionsEnabled true
99
+ AlarmActions [Ref(alarm.alarm_action)]
100
+ # InsufficientDataActions [Ref(alarm.alarm_action)]
101
+ # OKActions [Ref(alarm.alarm_action)]
102
+ end
103
+
104
+ end
105
+ end
106
+ end
107
+
108
+ def add_metric_filter(filter)
109
+ @template.declare do
110
+ Logs_MetricFilter("#{filter.name.gsub(/[^0-9a-zA-Z]/i, '')}#{filter.type}") do
111
+ LogGroupName filter.log_group
112
+ FilterPattern filter.pattern
113
+ MetricTransformations([
114
+ {
115
+ MetricValue: filter.metric_value,
116
+ MetricName: filter.metric_name,
117
+ MetricNamespace: filter.metric_namespace
118
+ }
119
+ ])
120
+ end
121
+ end
122
+ end
123
+
124
+ def add_event_subscription(subscription)
125
+ event_pattern = {}
126
+ event_pattern['detail-type'] = [subscription.detail_type]
127
+ event_pattern['source'] = [subscription.source]
128
+ event_pattern['resources'] = [subscription.resource_arn] unless subscription.resource_arn.empty?
129
+ event_pattern['detail'] = subscription.detail unless subscription.detail.empty?
130
+
131
+ @template.declare do
132
+ Events_Rule("#{subscription.group}#{subscription.name}#{subscription.hash}"[0..255]) do
133
+ State subscription.enabled ? 'ENABLED' : 'DISABLED'
134
+ Description "Guardian event subscription #{subscription.group} #{subscription.name} for resource #{subscription.resource_id}"
135
+ EventPattern event_pattern
136
+ Targets [
137
+ {
138
+ Arn: Ref(subscription.topic),
139
+ Id: "#{subscription.topic}Notifier"
140
+ }
141
+ ]
142
+ end
143
+ end
144
+ end
145
+
78
146
  end
79
147
  end
80
148
  end