cfn_monitor 0.4.0 → 0.4.1

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.
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: