cfn_monitor 0.4.0 → 0.4.1

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: d9ad46a04c973e8e513a89fa1a6aaa774c55680e6d23b3a86d295107420cfe79
4
- data.tar.gz: 2004bfad14bb93e09873f4d048d24a03333b43c489da972be5525ab3f402f669
3
+ metadata.gz: 420d2480a272de76dfcd2baad3c7cb3f955466dcff3fe2cf9ba2bcc2f607d3f6
4
+ data.tar.gz: 0ccdcb98a99859f0cce7019ceedee88dff40b4f0dc63ea32e53d1d97b0dc1304
5
5
  SHA512:
6
- metadata.gz: e10aa44c6904f4f2e669ebd4d30ff1876c1bab5d6b79a6672591cf7003f762b830d744695864b8de89c7b99ddd7f7db55adf6c019d357f59d21df3003fcbc896
7
- data.tar.gz: 4a99599700015475d0df8ae6e2822763c07b343c94a325167b838c09e0cc1644a3403e6a1e4cefc16659b0c65795e6ee07f63953a8cbc666b2c891037603a2af
6
+ metadata.gz: 6dd02e4fdee8bf609e43e11d423534e82cbfb68c6007969348074b72a5b05e2926c86cb2419318cde1df99a78dbfb408a7cdb5970cc0abd314a45e6f98ba0a48
7
+ data.tar.gz: 4fcf0812c6941e3d7ac13579efd6d42156f982403f53d23f420f8ebee16cb166582f372c4614bfdb1959f120cafa033a64fc9548680ebc9b7f2915a0e4f68876
data/README.md CHANGED
@@ -13,6 +13,10 @@ It is packaged as a docker container `base2/cfn-monitor` and
13
13
  can be run by volume mounting in a local directory to access the config
14
14
  or by using within AWS CodePipeline.
15
15
 
16
+ ## Install Gem
17
+
18
+ `gem install cfn_monitor`
19
+
16
20
  ## Commands
17
21
 
18
22
  ```bash
@@ -61,11 +61,12 @@ module CfnMonitor
61
61
  hosts = custom_alarms_config['hosts'] || {}
62
62
  ssl = custom_alarms_config['ssl'] || {}
63
63
  dns = custom_alarms_config['dns'] || {}
64
+ sql = custom_alarms_config['sql'] || {}
64
65
  services = custom_alarms_config['services'] || {}
65
66
  endpoints = custom_alarms_config['endpoints'] || {}
66
67
  ecsClusters = custom_alarms_config['ecsClusters'] || {}
67
68
 
68
- alarm_parameters = { resources: resources, metrics: metrics, endpoints: endpoints, hosts: hosts, ssl: ssl, dns: dns, services: services, ecsClusters: ecsClusters }
69
+ alarm_parameters = { resources: resources, metrics: metrics, endpoints: endpoints, hosts: hosts, ssl: ssl, dns: dns, sql: sql, services: services, ecsClusters: ecsClusters }
69
70
  source_bucket = custom_alarms_config['source_bucket']
70
71
 
71
72
  alarm_parameters.each do | k,v |
@@ -180,7 +181,7 @@ module CfnMonitor
180
181
  File.open("#{output_path}/alarms#{index}.json", 'w') { |file|
181
182
  file.write(JSON.pretty_generate( CfnDsl.eval_file_with_extras("#{template_path}/alarms.rb",[[:yaml, config],[:raw, "template_number=#{index}"],[:raw, "template_envs=#{template_envs}"]],verbose_cfndsl)))}
182
183
  end
183
- ['endpoints', 'ssl', "dns", 'hosts', 'services','ecsClusters'].each do |template|
184
+ ['endpoints', 'ssl', "dns", 'sql', 'hosts', 'services','ecsClusters'].each do |template|
184
185
  if !alarm_parameters[template.to_sym].nil? and alarm_parameters[template.to_sym] != {}
185
186
  File.open("#{output_path}/#{template}.json", 'w') { |file|
186
187
  file.write(JSON.pretty_generate( CfnDsl.eval_file_with_extras("#{template_path}/#{template}.rb",[[:yaml, alarms_config_file],[:raw, "template_envs=#{template_envs}"]],verbose_cfndsl)))
@@ -1,3 +1,3 @@
1
1
  module CfnMonitor
2
- VERSION = "0.4.0".freeze
2
+ VERSION = "0.4.1".freeze
3
3
  end
@@ -101,6 +101,20 @@ templates:
101
101
  EvaluationPeriods: 1
102
102
  MetricName: ExpiresInDays
103
103
  AlarmDescription: { 'Fn::Join': [ ' ', [ '${resource}', '${templateName}' ] ] }
104
+ Sql:
105
+ Crit:
106
+ # An SQL check is highly customisable; this config should be overriden by
107
+ # a custom template.
108
+ AlarmActions: crit
109
+ Namespace: SQL
110
+ ComparisonOperator: GreaterThanOrEqualToThreshold
111
+ Dimensions: [ { Name: 'Host', Value: '' } ]
112
+ Statistic: Maximum
113
+ Threshold: 1
114
+ Period: 60
115
+ EvaluationPeriods: 1
116
+ MetricName: Your_Metric_Name
117
+ AlarmDescription: { 'Fn::Join': [ ' ', [ '${resource}', '${templateName}' ] ] }
104
118
  Dns:
105
119
  Crit:
106
120
  AlarmActions: crit
@@ -615,6 +629,74 @@ templates:
615
629
  MetricName: DiskSpaceUsedPercent
616
630
  TreatMissingData: breaching
617
631
 
632
+ DiskINodeCheck:
633
+ CritLowINodeCountAtRootPath:
634
+ AlarmActions: crit
635
+ Namespace: CWAgent
636
+ ComparisonOperator: GreaterThanOrEqualToThreshold
637
+ Dimensions: [ { Name: 'path', Value: '/' }, { Name: 'host', Value: "${metric}" }, { Name: 'device', Value: 'xvda1' }, { Name: 'fstype', Value: 'ext4' } ]
638
+ Statistic: Maximum
639
+ Threshold: 471859 # 90% full, based off 524288 inodes (a 7.8GB disk)
640
+ Period: 60
641
+ EvaluationPeriods: 1
642
+ MetricName: INodesUsedCount
643
+ TreatMissingData: breaching
644
+ WarnLowINodeCountAtRootPath:
645
+ AlarmActions: warn
646
+ Namespace: CWAgent
647
+ ComparisonOperator: GreaterThanOrEqualToThreshold
648
+ Dimensions: [ { Name: 'path', Value: '/' }, { Name: 'host', Value: "${metric}" }, { Name: 'device', Value: 'xvda1' }, { Name: 'fstype', Value: 'ext4' } ]
649
+ Statistic: Maximum
650
+ Threshold: 419430 # 80% full, based off 524288 inodes (a 7.8GB disk)
651
+ Period: 60
652
+ EvaluationPeriods: 1
653
+ MetricName: INodesUsedCount
654
+ TreatMissingData: breaching
655
+ CritLowINodeCountAtDataPath:
656
+ AlarmActions: crit
657
+ Namespace: CWAgent
658
+ ComparisonOperator: GreaterThanOrEqualToThreshold
659
+ Dimensions: [ { Name: 'path', Value: '/data' }, { Name: 'host', Value: "${metric}" }, { Name: 'device', Value: 'xvdf' }, { Name: 'fstype', Value: 'ext4' } ]
660
+ Statistic: Maximum
661
+ Threshold: 23592960 # 90% full, based off 26214400 inodes (a 394GB disk)
662
+ Period: 60
663
+ EvaluationPeriods: 1
664
+ MetricName: INodesUsedCount
665
+ TreatMissingData: breaching
666
+ WarnLowINodeCountAtDataPath:
667
+ AlarmActions: warn
668
+ Namespace: CWAgent
669
+ ComparisonOperator: GreaterThanOrEqualToThreshold
670
+ Dimensions: [ { Name: 'path', Value: '/data' }, { Name: 'host', Value: "${metric}" }, { Name: 'device', Value: 'xvdf' }, { Name: 'fstype', Value: 'ext4' } ]
671
+ Statistic: Maximum
672
+ Threshold: 20971520 # 80% full, based off 26214400 inodes (a 394GB disk)
673
+ Period: 60
674
+ EvaluationPeriods: 1
675
+ MetricName: INodesUsedCount
676
+ TreatMissingData: breaching
677
+ CritLowINodeCountAtDockerPath:
678
+ AlarmActions: crit
679
+ Namespace: CWAgent
680
+ ComparisonOperator: GreaterThanOrEqualToThreshold
681
+ Dimensions: [ { Name: 'path', Value: '/var/lib/docker' }, { Name: 'host', Value: "${metric}" }, { Name: 'device', Value: 'xvdcz' }, { Name: 'fstype', Value: 'ext4' } ]
682
+ Statistic: Maximum
683
+ Threshold: 20643840 # 90% full, based off 22937600 inodes (a 345GB disk)
684
+ Period: 60
685
+ EvaluationPeriods: 1
686
+ MetricName: INodesUsedCount
687
+ TreatMissingData: breaching
688
+ WarnLowINodeCountAtDockerPath:
689
+ AlarmActions: warn
690
+ Namespace: CWAgent
691
+ ComparisonOperator: GreaterThanOrEqualToThreshold
692
+ Dimensions: [ { Name: 'path', Value: '/var/lib/docker' }, { Name: 'host', Value: "${metric}" }, { Name: 'device', Value: 'xvdcz' }, { Name: 'fstype', Value: 'ext4' } ]
693
+ Statistic: Maximum
694
+ Threshold: 18350080 # 80% full, based off 22937600 inodes (a 345GB disk)
695
+ Period: 60
696
+ EvaluationPeriods: 1
697
+ MetricName: INodesUsedCount
698
+ TreatMissingData: breaching
699
+
618
700
  AmazonMQBroker: # AWS::AmazonMQ::Broker
619
701
  CpuCreditBalanceCrit:
620
702
  AlarmActions: crit
@@ -164,7 +164,7 @@ CloudFormation do
164
164
  Property('Handler', 'handler.main')
165
165
  Property('MemorySize', 128)
166
166
  Property('Runtime', 'python3.6')
167
- Property('Timeout', 300)
167
+ Property('Timeout', 120)
168
168
  Property('Role', FnGetAtt('LambdaExecutionRole','Arn'))
169
169
  end
170
170
 
@@ -181,7 +181,7 @@ CloudFormation do
181
181
  Property('Handler', 'main')
182
182
  Property('MemorySize', 128)
183
183
  Property('Runtime', 'go1.x')
184
- Property('Timeout', 300)
184
+ Property('Timeout', 30)
185
185
  Property('Role', FnGetAtt('LambdaExecutionRole','Arn'))
186
186
  end
187
187
 
@@ -198,7 +198,7 @@ CloudFormation do
198
198
  Property('Handler', 'main')
199
199
  Property('MemorySize', 128)
200
200
  Property('Runtime', 'go1.x')
201
- Property('Timeout', 300)
201
+ Property('Timeout', 30)
202
202
  Property('Role', FnGetAtt('LambdaExecutionRole','Arn'))
203
203
  end
204
204
 
@@ -215,7 +215,7 @@ CloudFormation do
215
215
  Property('Handler', 'handler.run_check')
216
216
  Property('MemorySize', 128)
217
217
  Property('Runtime', 'python3.6')
218
- Property('Timeout', 300)
218
+ Property('Timeout', 30)
219
219
  Property('Role', FnGetAtt('EcsCICheckLambdaExecutionRole','Arn'))
220
220
  end
221
221
 
@@ -296,6 +296,21 @@ CloudFormation do
296
296
  end
297
297
  end
298
298
 
299
+ sqlParams = {
300
+ MonitoredStack: Ref('MonitoredStack'),
301
+ EnvironmentName: FnGetAtt('GetEnvironmentName', 'EnvironmentName' )
302
+ }
303
+
304
+ sql ||= {}
305
+ if !sql.empty?
306
+ Resource("SqlStack") do
307
+ Type 'AWS::CloudFormation::Stack'
308
+ Property('TemplateURL', "https://#{source_bucket}.s3.amazonaws.com/#{upload_path}/sql.json")
309
+ Property('TimeoutInMinutes', 5)
310
+ Property('Parameters', sqlParams)
311
+ end
312
+ end
313
+
299
314
  hostParams = {
300
315
  EnvironmentName: FnGetAtt('GetEnvironmentName', 'EnvironmentName' )
301
316
  }
@@ -0,0 +1,117 @@
1
+ require 'cfndsl'
2
+
3
+ CloudFormation do
4
+ Description("CloudWatch Endpoints")
5
+
6
+ Parameter("MonitoredStack"){
7
+ Type 'String'
8
+ }
9
+ Parameter("EnvironmentName"){
10
+ Type 'String'
11
+ }
12
+
13
+ Resource("SqlLambdaExecutionRole") do
14
+ Type 'AWS::IAM::Role'
15
+ Property('AssumeRolePolicyDocument', {
16
+ Version: '2012-10-17',
17
+ Statement: [{
18
+ Effect: 'Allow',
19
+ Principal: { Service: [ 'lambda.amazonaws.com' ] },
20
+ Action: [ 'sts:AssumeRole' ]
21
+ }]
22
+ })
23
+ Property('Path','/')
24
+ Property('Policies', [
25
+ PolicyName: 'SQL',
26
+ PolicyDocument: {
27
+ Version: '2012-10-17',
28
+ Statement: [{
29
+ Effect: 'Allow',
30
+ Action: [ 'logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents' ],
31
+ Resource: 'arn:aws:logs:*:*:*'
32
+ },
33
+ {
34
+ Effect: 'Allow',
35
+ Action: [ 'cloudwatch:PutMetricData' ],
36
+ Resource: '*'
37
+ },
38
+ {
39
+ Effect: 'Allow',
40
+ Action: [ 'ec2:CreateNetworkInterface', 'ec2:DescribeNetworkInterfaces', 'ec2:DeleteNetworkInterface' ],
41
+ Resource: '*'
42
+ }]
43
+ }
44
+ ])
45
+ end
46
+
47
+ alarms.each do |alarm|
48
+ if alarm[:type] == 'sq'
49
+
50
+ config = alarm[:parameters]
51
+ configHash = Digest::MD5.hexdigest ("sql-" + config['subnetIds'].sort().join() + config['vpcId'])
52
+
53
+ # No default as this is value is highly variable
54
+ #params['scheduleExpression'] ||= "0 12 * * ? *"
55
+
56
+ Resource("SqlSecurityGroup#{configHash}") {
57
+ Type 'AWS::EC2::SecurityGroup'
58
+ Property('VpcId', config['vpcId'])
59
+ Property('GroupDescription', "Monitoring Security Group (SQL)")
60
+ }
61
+
62
+ Resource("SqlCheckFunction#{configHash}") do
63
+ Type 'AWS::Lambda::Function'
64
+ Property('Code', { S3Bucket: FnJoin('.', ['base2.lambda', Ref('AWS::Region')]), S3Key: 'aws-lambda-sql-check/0.1/handler.zip' })
65
+ Property('Handler', 'main')
66
+ Property('MemorySize', 128)
67
+ Property('Runtime', 'go1.x')
68
+ Property('Timeout', 300)
69
+ Property('Role', FnGetAtt("SqlLambdaExecutionRole",'Arn'))
70
+ Property('VpcConfig', {
71
+ SecurityGroupIds: config['securityGroupIds'] || [ Ref("SqlSecurityGroup#{configHash}") ],
72
+ SubnetIds: config['subnetIds']
73
+ })
74
+ end
75
+
76
+ Resource("SqlCheckPermissions#{configHash}") do
77
+ Type 'AWS::Lambda::Permission'
78
+ Property('FunctionName', Ref("SqlCheckFunction#{configHash}"))
79
+ Property('Action', 'lambda:InvokeFunction')
80
+ Property('Principal', 'events.amazonaws.com')
81
+ end
82
+
83
+ # e.g. db_user:password@tcp(localhost:3306)/my_db
84
+ connection_string = "#{config['databaseUsername']}:#{config['databasePassword']}@tcp(#{config['databaseHost']}:#{config['databasePort']})"
85
+ if config.key?('databaseName')
86
+ connection_string += "/#{config['databaseName']}"
87
+ end
88
+
89
+ #p "Connection string for metric is: #{connection_string}"
90
+
91
+ # Create payload
92
+ payload = {
93
+ SqlHost: config['databaseHost'],
94
+ SqlDriver: config['databaseDriver'],
95
+ SqlCall: config['databaseQuery'],
96
+ SqlConnectionString: connection_string,
97
+ MetricName: alarm[:resource],
98
+ Region: "${region}",
99
+ TestType: '1-row-1-value-zero-is-good'
100
+ }
101
+
102
+ Resource("SqlCheckSchedule#{configHash}") do
103
+ Type 'AWS::Events::Rule'
104
+ Property('Description', "#{config['databaseHost']} => #{alarm[:resource]}")
105
+ Property('ScheduleExpression', config['scheduleExpression'])
106
+ Property('State', 'ENABLED')
107
+ Property('Targets', [
108
+ {
109
+ Arn: FnGetAtt("SqlCheckFunction#{configHash}", "Arn"),
110
+ Id: configHash,
111
+ Input: FnSub(payload.to_json, region: Ref("AWS::Region"))
112
+ }
113
+ ])
114
+ end
115
+ end
116
+ end
117
+ end
@@ -1,7 +1,7 @@
1
1
  require 'cfndsl'
2
2
 
3
3
  CloudFormation do
4
- Description("CloudWatch Endpoints")
4
+ Description("CloudWatch SQL Queries")
5
5
 
6
6
  Parameter("MonitoredStack"){
7
7
  Type 'String'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cfn_monitor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Base2Services
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2019-06-20 00:00:00.000000000 Z
13
+ date: 2019-07-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: thor
@@ -227,6 +227,7 @@ files:
227
227
  - lib/templates/master.rb
228
228
  - lib/templates/resources.rb
229
229
  - lib/templates/services.rb
230
+ - lib/templates/sql.rb
230
231
  - lib/templates/ssl.rb
231
232
  homepage: https://github.com/base2Services/cfn-monitor/blob/master/README.md
232
233
  licenses: