cfn-guardian 0.6.13 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed07cb07793213554d2611f693312d285d672d54146a8188c6b178f56d946aa7
4
- data.tar.gz: 2322c8908d7239288fb689e0a102ccd9ab5af32a702a6aa6af3df76c90f6c740
3
+ metadata.gz: f06747af0d401c54e458d9becbe4ce2f9e217b2c363fbddf89d5a3e09d65c03b
4
+ data.tar.gz: bd7782ab5b234ebf259bdc6ada2ee0717fe89121fe487e79ea45a13286b16a8b
5
5
  SHA512:
6
- metadata.gz: 35f90c8f88dafa4092f3b44adb604f794ced719fc8d1b72252b8013d9c7420df66981d40435c96c7176a46623b98f701e0d725ed866adcb93bcfdb2d4b31843b
7
- data.tar.gz: 887fac6d120e13890639341295a97f54955e7de67875e554c2806177daacf3abe2542a0ec5ab45d73166eed71e63327d31e2e123329e93910324e43cc0eff58e
6
+ metadata.gz: e5d3227e82977a8f4878d42cae70e5280238004fc72e1fffcc49080d70cd14592c45179fab4c0ea78a54b3fac18f4499c145cbf01895c99a8dc46da041c78ec5
7
+ data.tar.gz: c38cc4edef74b46dd58a13332f03c5cce1d783556d2ec58e109316792bec4b2c709a2165a19543d340869940a586e98c64ff405260bbf06731630644a01a602a
data/.gitignore CHANGED
@@ -9,4 +9,5 @@
9
9
 
10
10
  cfn-guardian-*.gem
11
11
 
12
- out/
12
+ out/
13
+ alarms.yaml
data/Dockerfile CHANGED
@@ -1,6 +1,6 @@
1
1
  FROM ruby:2.7-alpine
2
2
 
3
- ARG GUARDIAN_VERSION="0.6.9"
3
+ ARG GUARDIAN_VERSION="0.7.1"
4
4
 
5
5
  COPY . /src
6
6
 
@@ -32,6 +32,8 @@ Resources:
32
32
  Method: post
33
33
  # specify headers using "key=value key=value"
34
34
  Headers: content-type=application/json
35
+ # specify a useragent that contains spaces
36
+ UserAgent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Base2/Lambda
35
37
  # pass in custom payload for the request
36
38
  Payload: '{"name": "john"}'
37
39
  ```
@@ -15,10 +15,20 @@ Resources:
15
15
  # Name of the cloud watch metric
16
16
  - MetricName: MyFunctionErrors
17
17
  # search pattern, see aws docs for syntax
18
- Pattern: error
18
+ Pattern: 'error'
19
19
  # metric to push to cloudwatch. Optional as it defaults to 1
20
20
  MetricValue: 1
21
-
21
+ - Id: /prod/custom/app
22
+ # List of metric filters
23
+ MetricFilters:
24
+ # Name of the cloud watch metric
25
+ - MetricName: MyAppErrors
26
+ # search pattern, see aws docs for syntax
27
+ # note; any non-alphanumeric characters have to be wrapped in double quotes WITHIN single quotes
28
+ Pattern: '"Connection to ssl://mail.google.com:465 Timed Out"'
29
+ # metric to push to cloudwatch. Optional as it defaults to 1
30
+ MetricValue: 1
31
+
22
32
  Templates:
23
33
  LogGroup:
24
34
  # use the MetricName name to override the alarm defaults
@@ -8,8 +8,8 @@ Alarms can be provided to the function the following ways
8
8
  Alarm names be provided by a space delimited list using the `--alarms` switch.
9
9
 
10
10
  ```bash
11
- cfn-guardian disable-alarms --group alarm-1 alarm-2
12
- cfn-guardian enable-alarms --group alarm-1 alarm-2
11
+ cfn-guardian disable-alarms --alarms alarm-1 alarm-2
12
+ cfn-guardian enable-alarms --alarms alarm-1 alarm-2
13
13
  ```
14
14
 
15
15
  ## Alarm Name Prefix
@@ -60,10 +60,16 @@ Resources:
60
60
  StatusCode: 200
61
61
 
62
62
  # Define the top level key
63
- MaintenaceGroups:
63
+ MaintenanceGroups:
64
64
 
65
65
  # Define the group name
66
66
  AppUpdate:
67
+ # Optionally set a schedule for enabling/disabling
68
+ Schedules:
69
+ Disable: '30 0 * * ? *'
70
+ Enable: '00 1 * * ? *'
71
+ #Optionally specify and set to true to enable logging on lambda
72
+ Debug: true
67
73
  # Define the resource group
68
74
  ECSService:
69
75
  # define the alarms in the resource group
@@ -82,4 +88,6 @@ MaintenaceGroups:
82
88
  ```bash
83
89
  cfn-guardian disable-alarms --group AppUpdate
84
90
  cfn-guardian enable-alarms --group AppUpdate
85
- ```
91
+ ```
92
+
93
+ Optionally add a Schedule for disabling and enabling alarm actions as shown in the example above to deploy a lambda function that will be invoked by event rules created with the given cron expressions.
@@ -44,6 +44,7 @@ require 'cfnguardian/resources/step_functions'
44
44
  require 'cfnguardian/resources/vpn_tunnel'
45
45
  require 'cfnguardian/resources/vpn_connection'
46
46
  require 'cfnguardian/resources/elastic_search'
47
+ require 'cfnguardian/resources/jenkins'
47
48
  require 'cfnguardian/version'
48
49
  require 'cfnguardian/error'
49
50
 
@@ -61,7 +62,7 @@ module CfnGuardian
61
62
  @composites = config.fetch('Composites',{})
62
63
  @templates = config.fetch('Templates',{})
63
64
  @topics = config.fetch('Topics',{})
64
- @maintenance_groups = config.fetch('MaintenaceGroups', {})
65
+ @maintenance_groups = config.fetch('MaintenanceGroups', {})
65
66
  @event_subscriptions = config.fetch('EventSubscriptions', {})
66
67
 
67
68
  # Make sure the default topics exist if they aren't supplied in the alarms.yaml
@@ -69,7 +70,6 @@ module CfnGuardian
69
70
  @topics[topic] = '' unless @topics.has_key?(topic)
70
71
  end
71
72
 
72
- @maintenance_group_list = @maintenance_groups.keys.map {|group| "#{group}MaintenanceGroup"}
73
73
  @resources = []
74
74
  @stacks = []
75
75
  @checks = []
@@ -116,6 +116,9 @@ module CfnGuardian
116
116
 
117
117
  @maintenance_groups.each do |maintenance_group,resource_groups|
118
118
  resource_groups.each do |group, alarms|
119
+ if group == 'Schedules'
120
+ next
121
+ end
119
122
  alarms.each do |alarm, resources|
120
123
  resources.each do |resource|
121
124
 
@@ -190,7 +193,7 @@ module CfnGuardian
190
193
  resources = split_resources(bucket,path)
191
194
 
192
195
  main_stack = CfnGuardian::Stacks::Main.new()
193
- main_stack.build_template(@stacks,@checks,@topics,@maintenance_group_list,@ssm_parameters)
196
+ main_stack.build_template(@stacks,@checks,@topics,@maintenance_groups,@ssm_parameters)
194
197
  valid = main_stack.template.validate
195
198
  FileUtils.mkdir_p 'out'
196
199
  File.write("out/guardian.compiled.yaml", JSON.parse(valid.to_json).to_yaml)
@@ -485,6 +485,15 @@ module CfnGuardian
485
485
  end
486
486
  end
487
487
 
488
+ class JenkinsAlarm < BaseAlarm
489
+ def initialize(resource)
490
+ super(resource)
491
+ @group = 'Jenkins'
492
+ @namespace = 'Ciinabox/Jenkins'
493
+ @dimensions = { Jenkins: resource['Id'], Monitoring: 'JenkMon' }
494
+ end
495
+ end
496
+
488
497
  class VPNTunnelAlarm < BaseAlarm
489
498
  def initialize(resource)
490
499
  super(resource)
@@ -40,7 +40,7 @@ module CfnGuardian
40
40
  @name = 'HttpCheck'
41
41
  @package = 'http-check'
42
42
  @handler = 'handler.http_check'
43
- @version = 'f739631de74f1a882163b7e584a8b4710ccbc134'
43
+ @version = '0e945240f9d93242f807e86d1a9b3383a1764b96'
44
44
  @runtime = 'python3.7'
45
45
  end
46
46
  end
@@ -205,5 +205,16 @@ module CfnGuardian
205
205
  end
206
206
  end
207
207
 
208
+ class MaintenanceGroupCheck < BaseCheck
209
+ def initialize(resource)
210
+ super(resource)
211
+ @name = 'MaintenanceGroupCheck'
212
+ @package = 'maintenance-group-check'
213
+ @handler = 'handler.maintenance_group_check'
214
+ @version = '5b795e6509068d1767e4be80f2e6868cbeb3b425'
215
+ @runtime = 'python3.7'
216
+ end
217
+ end
218
+
208
219
  end
209
- end
220
+ end
@@ -52,6 +52,7 @@ module CfnGuardian
52
52
  @status_code = resource.fetch('StatusCode',200)
53
53
  @body_regex = resource.fetch('BodyRegex',nil)
54
54
  @headers = resource.fetch('Headers',nil)
55
+ @user_agent = resource.fetch('UserAgent',nil)
55
56
  @payload = resource.fetch('Payload',nil)
56
57
  @compressed = resource.fetch('Compressed',false)
57
58
  end
@@ -65,6 +66,7 @@ module CfnGuardian
65
66
  }
66
67
  payload['BODY_REGEX_MATCH'] = @body_regex unless @body_regex.nil?
67
68
  payload['HEADERS'] = @headers unless @headers.nil?
69
+ payload['USER_AGENT'] = @user_agent unless @user_agent.nil?
68
70
  payload['PAYLOAD'] = @payload unless @payload.nil?
69
71
  payload['COMPRESSED'] = '1' if @compressed
70
72
  return payload.to_json
@@ -70,6 +70,7 @@ module CfnGuardian::Resource
70
70
  alarm.threshold = 25000
71
71
  alarm.evaluation_periods = 1
72
72
  alarm.alarm_action = 'Critical'
73
+ alarm.statistic = 'Minimum'
73
74
  alarm.comparison_operator = 'LessThanOrEqualToThreshold'
74
75
  @alarms.push(alarm)
75
76
 
@@ -0,0 +1,17 @@
1
+ module CfnGuardian::Resource
2
+ class Jenkins < Base
3
+
4
+ def default_alarms
5
+ alarm = CfnGuardian::Models::JenkinsAlarm.new(@resource)
6
+ alarm.name = 'NoSuccess'
7
+ alarm.metric_name = 'Success'
8
+ alarm.statistic = 'Maximum'
9
+ alarm.treat_missing_data = 'breaching'
10
+ alarm.alarm_action = 'Warning'
11
+ alarm.period = 3600
12
+ alarm.comparison_operator = 'LessThanThreshold'
13
+ alarm.threshold = 1
14
+ @alarms.push(alarm)
15
+ end
16
+ end
17
+ end
@@ -24,6 +24,7 @@ module CfnGuardian::Resource
24
24
  alarm.name = 'IteratorAge'
25
25
  alarm.metric_name = 'IteratorAge'
26
26
  alarm.threshold = 600000
27
+ alarm.treat_missing_data = 'notBreaching'
27
28
  @alarms.push(alarm)
28
29
 
29
30
  alarm = CfnGuardian::Models::LambdaAlarm.new(@resource)
@@ -31,6 +32,7 @@ module CfnGuardian::Resource
31
32
  alarm.metric_name = 'Duration'
32
33
  alarm.statistic = 'Average'
33
34
  alarm.threshold = 30
35
+ alarm.treat_missing_data = 'notBreaching'
34
36
  @alarms.push(alarm)
35
37
  end
36
38
 
@@ -3,7 +3,18 @@ module CfnGuardian::Resource
3
3
 
4
4
  def default_alarms
5
5
  alarm = CfnGuardian::Models::VPNConnectionAlarm.new(@resource)
6
- alarm.name = 'VPNConnectionState'
6
+ alarm.name = 'VPNConnectionStateNonRedundant'
7
+ alarm.metric_name = 'TunnelState'
8
+ alarm.comparison_operator = 'LessThanThreshold'
9
+ alarm.statistic = 'Average'
10
+ alarm.threshold = 1.0
11
+ alarm.evaluation_periods = 3
12
+ alarm.treat_missing_data = 'breaching'
13
+ alarm.datapoints_to_alarm = 3
14
+ @alarms.push(alarm)
15
+
16
+ alarm = CfnGuardian::Models::VPNConnectionAlarm.new(@resource)
17
+ alarm.name = 'VPNConnectionStateAllDown'
7
18
  alarm.metric_name = 'TunnelState'
8
19
  alarm.comparison_operator = 'LessThanThreshold'
9
20
  alarm.statistic = 'Average'
@@ -4,6 +4,7 @@ module CfnGuardian
4
4
  module Stacks
5
5
  class Main
6
6
  include CfnDsl::CloudFormation
7
+ include Logging
7
8
 
8
9
  attr_reader :parameters, :template
9
10
 
@@ -22,12 +23,10 @@ module CfnGuardian
22
23
  parameter.Default sns
23
24
  parameters[name] = Ref(name)
24
25
  end
25
-
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)
26
+
27
+ if maintenance_groups.any?
28
+ add_lambda(CfnGuardian::Models::MaintenanceGroupCheck.new(maintenance_groups))
29
+ maintenance_groups.each {|group,config| add_maintenance_group(group,config,parameters)}
31
30
  end
32
31
 
33
32
  add_iam_role(ssm_parameters)
@@ -73,6 +72,17 @@ module CfnGuardian
73
72
  }]
74
73
  }
75
74
  }
75
+ policies << {
76
+ PolicyName: 'maintenance-group-actions',
77
+ PolicyDocument: {
78
+ Version: '2012-10-17',
79
+ Statement: [{
80
+ Effect: 'Allow',
81
+ Action: [ 'cloudwatch:DescribeAlarms', 'cloudwatch:DisableAlarmActions', 'cloudwatch:EnableAlarmActions', 'cloudwatch:SetAlarmState' ],
82
+ Resource: FnSub("arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:*")
83
+ }]
84
+ }
85
+ }
76
86
  if ssm_parameters.any?
77
87
  policies << {
78
88
  PolicyName: 'ssm-parameters',
@@ -165,7 +175,37 @@ module CfnGuardian
165
175
  end
166
176
  end
167
177
  end
168
-
178
+
179
+ def add_maintenance_group(group,config,parameters)
180
+ group_name = "#{group}MaintenanceGroup"
181
+ schedules = config.fetch('Schedules', {})
182
+ logging = config.dig('Schedules', 'Debug').to_s
183
+
184
+ topic = @template.SNS_Topic(group_name)
185
+ topic.TopicName group_name
186
+ topic.Tags([{ Key: 'Environment', Value: 'guardian' }])
187
+ parameters[group_name] = Ref(group_name)
188
+
189
+ if schedules.any?
190
+ event = @template.Events_Rule("#{group_name}EnableEvent")
191
+ event.Name "#{group_name}EnableEvent"
192
+ event.ScheduleExpression "cron(#{schedules['Enable']})"
193
+ event.Targets([{
194
+ Arn: FnGetAtt('MaintenanceGroupCheckFunction', 'Arn'),
195
+ Id: "#{group_name}EnableTarget",
196
+ Input: {action:"enable_alarms", maintenance_group: group_name, logging: logging}.to_json
197
+ }])
198
+
199
+ event = @template.Events_Rule("#{group_name}DisableEvent")
200
+ event.Name "#{group_name}DisableEvent"
201
+ event.ScheduleExpression "cron(#{schedules['Disable']})"
202
+ event.Targets([{
203
+ Arn: FnGetAtt('MaintenanceGroupCheckFunction', 'Arn'),
204
+ Id: "#{group_name}DisableTarget",
205
+ Input: {action:"disable_alarms", maintenance_group: group_name, logging: logging}.to_json
206
+ }])
207
+ end
208
+ end
169
209
  end
170
210
  end
171
211
  end
@@ -1,4 +1,4 @@
1
1
  module CfnGuardian
2
- VERSION = "0.6.13"
2
+ VERSION = "0.7.3"
3
3
  CHANGE_SET_VERSION = VERSION.gsub('.', '-').freeze
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cfn-guardian
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.13
4
+ version: 0.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guslington
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-07-06 00:00:00.000000000 Z
11
+ date: 2021-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -295,6 +295,7 @@ files:
295
295
  - lib/cfnguardian/resources/internal_http.rb
296
296
  - lib/cfnguardian/resources/internal_port.rb
297
297
  - lib/cfnguardian/resources/internal_sftp.rb
298
+ - lib/cfnguardian/resources/jenkins.rb
298
299
  - lib/cfnguardian/resources/lambda.rb
299
300
  - lib/cfnguardian/resources/log_group.rb
300
301
  - lib/cfnguardian/resources/network_targetgroup.rb