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 +4 -4
- data/README.md +4 -0
- data/lib/cfn_monitor/generate.rb +3 -2
- data/lib/cfn_monitor/version.rb +1 -1
- data/lib/config/templates.yml +82 -0
- data/lib/templates/master.rb +19 -4
- data/lib/templates/sql.rb +117 -0
- data/lib/templates/ssl.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 420d2480a272de76dfcd2baad3c7cb3f955466dcff3fe2cf9ba2bcc2f607d3f6
|
4
|
+
data.tar.gz: 0ccdcb98a99859f0cce7019ceedee88dff40b4f0dc63ea32e53d1d97b0dc1304
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/cfn_monitor/generate.rb
CHANGED
@@ -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)))
|
data/lib/cfn_monitor/version.rb
CHANGED
data/lib/config/templates.yml
CHANGED
@@ -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
|
data/lib/templates/master.rb
CHANGED
@@ -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',
|
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',
|
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',
|
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',
|
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
|
data/lib/templates/ssl.rb
CHANGED
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.
|
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-
|
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:
|