sensu-plugins-ssl-boutetnico 1.0.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 16378e5222efd774d58d33c47dfa46facac0b2cd
4
+ data.tar.gz: 55dd9684c413e0b36ed44e6a89e83a571a0742d3
5
+ SHA512:
6
+ metadata.gz: cebae6d1239bcae312147ce8f4df7acc5bb01698c39da3a4f5ff351031fde0ab2e0fe16f54a49d980db5d80731f8a1020a64a74ce0a230b8283a17323ac5f53a
7
+ data.tar.gz: f1f9c483b7dc9e4769651de62277b2abaa9d6b1571cdf6f5cf2469acab557746bd344832ad8c2aaecdc654ae9082265304738ad312f8f8da216567c24595b0e5
@@ -0,0 +1 @@
1
+ Can be found at [https://github.com/boutetnico/sensu-plugins-ssl/releases](https://github.com/boutetnico/sensu-plugins-ssl/releases).
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Sensu-Plugins
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,78 @@
1
+ ## Sensu-Plugins-SSL
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/sensu-plugins-ssl-boutetnico.svg)](https://badge.fury.io/rb/sensu-plugins-ssl-boutetnico.svg)
4
+ [![Sensu Bonsai Asset](https://img.shields.io/badge/Bonsai-Download%20Me-brightgreen.svg?colorB=89C967&logo=sensu)](https://bonsai.sensu.io/assets/boutetnico/sensu-plugins-ssl)
5
+
6
+ ## This is an unofficial fork
7
+
8
+ This fork is automatically tested, built and published to [RubyGems](https://rubygems.org/gems/sensu-plugins-ssl-boutetnico/) and [Bonsai](https://bonsai.sensu.io/assets/boutetnico/sensu-plugins-ssl).
9
+
10
+ ## Files
11
+ * bin/check-java-keystore-cert.rb
12
+ * bin/check-ssl-anchor.rb
13
+ * bin/check-ssl-crl.rb
14
+ * bin/check-ssl-cert.rb
15
+ * bin/check-ssl-host.rb
16
+ * bin/check-ssl-hsts-preload.rb
17
+ * bin/check-ssl-hsts-preloadable.rb
18
+ * bin/check-ssl-qualys.rb
19
+ * bin/check-ssl-root-issuer.rb
20
+
21
+ ## Usage
22
+
23
+ ### `bin/check-ssl-anchor.rb`
24
+
25
+ Check that a specific website is chained to a specific root certificate (Let's Encrypt for instance). Requires the `openssl` commandline tool to be available on the system.
26
+
27
+ ```
28
+ ./bin/check-ssl-anchor.rb -u example.com -a "i:/O=Digital Signature Trust Co./CN=DST Root CA X3"
29
+ ```
30
+
31
+ ### `bin/check-ssl-crl.rb`
32
+
33
+ Checks a CRL has not or is not expiring by inspecting it's next update value.
34
+
35
+ You can check against a CRL file on disk:
36
+
37
+ ```
38
+ ./bin/check-ssl-crl -c 300 -w 600 -u /path/to/crl
39
+ ```
40
+
41
+ or an online CRL:
42
+
43
+ ```
44
+ ./bin/check-ssl-crl -c 300 -w 600 -u http://www.website.com/file.crl
45
+ ```
46
+
47
+ Critical and Warning thresholds are specified in minutes.
48
+
49
+ ### `bin/check-ssl-qualys.rb`
50
+
51
+ Checks the ssllabs qualysis api for grade of your server, this check can be quite long so it should not be scheduled with a low interval and will probably need to adjust the check `timeout` options per the [check attributes spec](https://docs.sensu.io/sensu-core/1.2/reference/checks/#check-attributes) based on my tests you should expect this to take around 3 minutes.
52
+ ```
53
+ ./bin/check-ssl-qualys.rb -d google.com
54
+ ```
55
+
56
+ ### `bin/check-ssl-root-issuer.rb`
57
+
58
+ Check that a specific website is chained to a specific root certificate issuer. This is a pure Ruby implementation, does not require the openssl cmdline client tool to be installed.
59
+
60
+ ```
61
+ ./bin/check-ssl-root-issuer.rb -u example.com -a "CN=DST Root CA X3,O=Digital Signature Trust Co."
62
+ ```
63
+
64
+ ## Installation
65
+
66
+ [Installation and Setup](http://sensu-plugins.io/docs/installation_instructions.html)
67
+
68
+ ## Testing
69
+
70
+ To run the testing suite, you'll need to have a working `ruby` environment, `gem`, and `bundler` installed. We use `rake` to run the `rspec` tests automatically.
71
+
72
+ bundle install
73
+ bundle update
74
+ bundle exec rake
75
+
76
+ ## Notes
77
+
78
+ `bin/check-ssl-anchor.rb` and `bin/check-ssl-host.rb` would be good to run in combination with each other to test that the chain is anchored to a specific certificate and each certificate in the chain is correctly signed.
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # check-java-keystore-cert
4
+ #
5
+ # DESCRIPTION:
6
+ # Check when a certificate stored in a Java Keystore will expire
7
+ #
8
+ # OUTPUT:
9
+ # plain text
10
+ #
11
+ # PLATFORMS:
12
+ # Linux
13
+ #
14
+ # DEPENDENCIES:
15
+ # gem: sensu-plugin
16
+ #
17
+ # USAGE:
18
+ # example commands
19
+ #
20
+ # NOTES:
21
+ # Does it behave differently on specific platforms, specific use cases, etc
22
+ #
23
+
24
+ require 'date'
25
+ require 'shellwords'
26
+ require 'sensu-plugin/check/cli'
27
+
28
+ class CheckJavaKeystoreCert < Sensu::Plugin::Check::CLI
29
+ option :path,
30
+ long: '--path PATH',
31
+ description: '',
32
+ required: true
33
+
34
+ option :alias,
35
+ long: '--alias ALIAS',
36
+ description: '',
37
+ required: true
38
+
39
+ option :password,
40
+ long: '--password PASSWORD',
41
+ description: '',
42
+ required: true
43
+
44
+ option :warning,
45
+ long: '--warning DAYS',
46
+ description: '',
47
+ proc: proc { |v| v.to_i },
48
+ required: true
49
+
50
+ option :critical,
51
+ long: '--critical DAYS',
52
+ description: '',
53
+ proc: proc { |v| v.to_i },
54
+ required: true
55
+
56
+ def certificate_expiration_date
57
+ result = `keytool -keystore #{Shellwords.escape(config[:path])} \
58
+ -export -alias #{Shellwords.escape(config[:alias])} \
59
+ -storepass #{Shellwords.escape(config[:password])} -rfc 2>&1 | \
60
+ openssl x509 -enddate -noout 2>&1`
61
+
62
+ # rubocop:disable Style/SpecialGlobalVars
63
+ unknown 'could not get certificate from keystore' unless $?.success?
64
+ # rubocop:enable Style/SpecialGlobalVars
65
+
66
+ Date.parse(result.split('=').last)
67
+ end
68
+
69
+ def validate_opts
70
+ unknown 'warning cannot be less than critical' if config[:warning] < config[:critical]
71
+ end
72
+
73
+ def run
74
+ validate_opts
75
+
76
+ days_until = (certificate_expiration_date - Date.today).to_i
77
+
78
+ if days_until.negative?
79
+ critical "Expired #{days_until.abs} days ago"
80
+ elsif days_until < config[:critical]
81
+ critical "#{days_until} days left"
82
+ elsif days_until < config[:warning]
83
+ warning "#{days_until} days left"
84
+ end
85
+
86
+ ok "#{days_until} days left"
87
+ end
88
+ end
@@ -0,0 +1,120 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ # check-ssl-anchor
4
+ #
5
+ # DESCRIPTION:
6
+ # Check that a certificate is chained to a specific root certificate
7
+ #
8
+ # OUTPUT:
9
+ # plain text
10
+ #
11
+ # PLATFORMS:
12
+ # Linux
13
+ #
14
+ # DEPENDENCIES:
15
+ # gem: sensu-plugin
16
+ #
17
+ # USAGE:
18
+ #
19
+ # Check that a specific website is chained to a specific root certificate (Let's Encrypt for instance)
20
+ # ./check-ssl-anchor.rb \
21
+ # -u example.com \
22
+ # -a "i:/O=Digital Signature Trust Co./CN=DST Root CA X3"
23
+ #
24
+ # NOTES:
25
+ # This is basically a ruby wrapper around the following openssl command.
26
+ #
27
+ # openssl s_client -connect example.com:443 -servername example.com
28
+ #
29
+ #
30
+ #
31
+ # Use the -s flag if you need to override SNI (Server Name Indication). If you
32
+ # are seeing discrepencies between `openssl s_client` and browser, that's a good
33
+ # indication to use this flag.
34
+ #
35
+ # LICENSE:
36
+ # Copyright 2017 Phil Porada <philporada@gmail.com>
37
+ #
38
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
39
+ # for details.
40
+ #
41
+
42
+ require 'sensu-plugin/check/cli'
43
+
44
+ #
45
+ # Check certificate is anchored to a specific root
46
+ #
47
+ class CheckSSLAnchor < Sensu::Plugin::Check::CLI
48
+ option :host,
49
+ description: 'Host to check',
50
+ short: '-h',
51
+ long: '--host HOST',
52
+ required: true
53
+
54
+ option :anchor,
55
+ description: 'An anchor looks something like /O=Digital Signature Trust Co./CN=DST Root CA X3',
56
+ short: '-a',
57
+ long: '--anchor ANCHOR_VAL',
58
+ required: true
59
+
60
+ option :regexp,
61
+ description: 'Treat the anchor as a regexp',
62
+ short: '-r',
63
+ long: '--regexp',
64
+ default: false,
65
+ boolean: true,
66
+ required: false
67
+
68
+ option :servername,
69
+ description: 'Set the TLS SNI (Server Name Indication) extension',
70
+ short: '-s',
71
+ long: '--servername SERVER'
72
+
73
+ option :port,
74
+ description: 'Port on server to check',
75
+ short: '-p',
76
+ long: '--port PORT',
77
+ default: 443
78
+
79
+ def validate_opts
80
+ config[:servername] = config[:host] unless config[:servername]
81
+ end
82
+
83
+ # Do the actual work and massage some data
84
+ def anchor_information
85
+ data = `openssl s_client \
86
+ -connect #{config[:host]}:#{config[:port]} \
87
+ -servername #{config[:servername]} < /dev/null 2>&1`.match(/Certificate chain(.*)---\nServer certificate/m)[1].split(/$/).map(&:strip)
88
+ data = data.reject(&:empty?)
89
+
90
+ unless data[0] =~ /0 s:\/?CN ?=.*/m
91
+ data = 'NOTOK'
92
+ end
93
+ data
94
+ end
95
+
96
+ def run
97
+ validate_opts
98
+ data = anchor_information
99
+ if data == 'NOTOK'
100
+ critical 'An error was encountered while trying to retrieve the certificate chain.'
101
+ end
102
+ puts config[:regexp]
103
+ # rubocop:disable Style/IfInsideElse
104
+ if config[:regexp]
105
+ anchor_regexp = Regexp.new(config[:anchor].to_s)
106
+ if data[-1] =~ anchor_regexp
107
+ ok 'Root anchor has been found.'
108
+ else
109
+ critical 'Root anchor did not match regexp /' + config[:anchor].to_s + "/\nFound \"" + data[-1] + '" instead.'
110
+ end
111
+ else
112
+ if data[-1] == config[:anchor].to_s
113
+ ok 'Root anchor has been found.'
114
+ else
115
+ critical 'Root anchor did not match string "' + config[:anchor].to_s + "\"\nFound \"" + data[-1] + '" instead.'
116
+ end
117
+ end
118
+ # rubocop:enable Style/IfInsideElse
119
+ end
120
+ end
@@ -0,0 +1,130 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ # check-ssl-cert
4
+ #
5
+ # DESCRIPTION:
6
+ # Check when a SSL certificate will expire.
7
+ #
8
+ # OUTPUT:
9
+ # plain text
10
+ #
11
+ # PLATFORMS:
12
+ # Linux
13
+ #
14
+ # DEPENDENCIES:
15
+ # gem: sensu-plugin
16
+ #
17
+ # USAGE:
18
+ # example commands
19
+ #
20
+ # NOTES:
21
+ # Does it behave differently on specific platforms, specific use cases, etc
22
+ #
23
+ # LICENSE:
24
+ # Jean-Francois Theroux <me@failshell.io>
25
+ # Nathan Williams <nath.e.will@gmail.com>
26
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
27
+ # for details.
28
+ #
29
+
30
+ require 'date'
31
+ require 'openssl'
32
+ require 'sensu-plugin/check/cli'
33
+
34
+ #
35
+ # Check SSL Cert
36
+ #
37
+ class CheckSSLCert < Sensu::Plugin::Check::CLI
38
+ option :critical,
39
+ description: 'Numbers of days left',
40
+ short: '-c',
41
+ long: '--critical DAYS',
42
+ required: true
43
+
44
+ option :warning,
45
+ description: 'Numbers of days left',
46
+ short: '-w',
47
+ long: '--warning DAYS',
48
+ required: true
49
+
50
+ option :pem,
51
+ description: 'Path to PEM file',
52
+ short: '-P',
53
+ long: '--pem PEM'
54
+
55
+ option :host,
56
+ description: 'Host to validate',
57
+ short: '-h',
58
+ long: '--host HOST'
59
+
60
+ option :port,
61
+ description: 'Port to validate',
62
+ short: '-p',
63
+ long: '--port PORT'
64
+
65
+ option :servername,
66
+ description: 'Set the TLS SNI (Server Name Indication) extension',
67
+ short: '-s',
68
+ long: '--servername SERVER'
69
+
70
+ option :pkcs12,
71
+ description: 'Path to PKCS#12 certificate',
72
+ short: '-C',
73
+ long: '--cert P12'
74
+
75
+ option :pass,
76
+ description: 'Pass phrase for the private key in PKCS#12 certificate',
77
+ short: '-S',
78
+ long: '--pass '
79
+
80
+ def ssl_cert_expiry
81
+ `openssl s_client -servername #{config[:servername]} -connect #{config[:host]}:#{config[:port]} < /dev/null 2>&1 | openssl x509 -enddate -noout`.split('=').last
82
+ end
83
+
84
+ def ssl_pem_expiry
85
+ OpenSSL::X509::Certificate.new(File.read config[:pem]).not_after # rubocop:disable Style/NestedParenthesizedCalls
86
+ end
87
+
88
+ def ssl_pkcs12_expiry
89
+ `openssl pkcs12 -in #{config[:pkcs12]} -nokeys -nomacver -passin pass:"#{config[:pass]}" | openssl x509 -noout -enddate | grep -v MAC`.split('=').last
90
+ end
91
+
92
+ def validate_opts
93
+ if !config[:pem] && !config[:pkcs12]
94
+ unknown 'Host and port required' unless config[:host] && config[:port]
95
+ elsif config[:pem]
96
+ unknown 'No such cert' unless File.exist? config[:pem]
97
+ elsif config[:pkcs12]
98
+ if !config[:pass]
99
+ unknown 'No pass phrase specified for PKCS#12 certificate'
100
+ else
101
+ unknown 'No such cert' unless File.exist? config[:pkcs12]
102
+ end
103
+ end
104
+ config[:servername] = config[:host] unless config[:servername]
105
+ end
106
+
107
+ def run
108
+ validate_opts
109
+
110
+ expiry = if config[:pem]
111
+ ssl_pem_expiry
112
+ elsif config[:pkcs12]
113
+ ssl_pkcs12_expiry
114
+ else
115
+ ssl_cert_expiry
116
+ end
117
+
118
+ days_until = (Date.parse(expiry.to_s) - Date.today).to_i
119
+
120
+ if days_until.negative?
121
+ critical "Expired #{days_until.abs} days ago"
122
+ elsif days_until < config[:critical].to_i
123
+ critical "#{days_until} days left"
124
+ elsif days_until < config[:warning].to_i
125
+ warning "#{days_until} days left"
126
+ else
127
+ ok "#{days_until} days left"
128
+ end
129
+ end
130
+ end