sensu-plugins-ssl 2.0.1 → 3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -1
- data/README.md +12 -1
- data/bin/check-java-keystore-cert.rb +3 -1
- data/bin/check-ssl-anchor.rb +26 -5
- data/bin/check-ssl-cert.rb +3 -1
- data/bin/check-ssl-crl.rb +4 -2
- data/bin/check-ssl-host.rb +7 -4
- data/bin/check-ssl-hsts-preloadable.rb +6 -4
- data/bin/check-ssl-hsts-status.rb +7 -5
- data/bin/check-ssl-qualys.rb +3 -2
- data/bin/check-ssl-root-issuer.rb +128 -0
- data/lib/sensu-plugins-ssl.rb +2 -0
- data/lib/sensu-plugins-ssl/version.rb +4 -2
- metadata +25 -24
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 81a09f41b7a0220a938ceee8561f7433321376e5617e4c09fb65454476630d88
|
|
4
|
+
data.tar.gz: b0ecba81c6266494db6a0f8c9ecb50da9f8302bef75e6f5267ca6a79aa2c17b5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7ba079ecb12548b22f684681ee0c077e965ac04a725623554a74b6fc45f009b1a72c3b1657d3ac69dbf58f213497bfee7b3e830dcc769c13c0eeb57fea9c56b9
|
|
7
|
+
data.tar.gz: 45ecf2194f83c759681b9e167a8c8d08e77a20e4691c2c432dc18b779bcd52d1b089fb148a758dd5a7f9e208cab6de8bf54e41a9c785de9eb5935d2155f3b22e
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,25 @@ This CHANGELOG follows the format listed [here](https://github.com/sensu-plugins
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [3.0.0] - 2020-08-27
|
|
9
|
+
### Breaking Changes
|
|
10
|
+
- Bump `sensu-plugin` dependency from `~> 1.2` to `~> 4.0` you can read the changelog entries for [4.0](https://github.com/sensu-plugins/sensu-plugin/blob/master/CHANGELOG.md#400---2018-02-17), [3.0](https://github.com/sensu-plugins/sensu-plugin/blob/master/CHANGELOG.md#300---2018-12-04), and [2.0](https://github.com/sensu-plugins/sensu-plugin/blob/master/CHANGELOG.md#v200---2017-03-29)
|
|
11
|
+
- Remove ruby-2.3.0. Upgrade bundler. Fix failing tests (@phumpal).
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- Travis build automation to generate Sensu Asset tarballs that can be used n conjunction with Sensu provided ruby runtime assets and the Bonsai Asset Index
|
|
15
|
+
- Require latest sensu-plugin for [Sensu Go support](https://github.com/sensu-plugins/sensu-plugin#sensu-go-enablement)
|
|
16
|
+
- New option to treat anchor argument as a regexp
|
|
17
|
+
- New Check plugin `check-ssl-root-issuer.rb` with alternative logic for trust anchor verification.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- `check-ssl-anchor.rb` uses regexp to test for present of certificates in cert chain that works with both openssl 1.0 and 1.1 formatting
|
|
21
|
+
- Upgrade rake and rubocop dependencies
|
|
22
|
+
- Remediate rubocop issues
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
- ssl-anchor test now uses regexp
|
|
26
|
+
|
|
8
27
|
## [2.0.1] - 2018-05-30
|
|
9
28
|
### Fixed
|
|
10
29
|
- `check-ssl-qualys.rb`: Fixed typo and removed timeout `-t` short option replacing it with `--timeout` as per previous changelog. `-t` conflicts with the short option for `--time-between`
|
|
@@ -110,7 +129,8 @@ This CHANGELOG follows the format listed [here](https://github.com/sensu-plugins
|
|
|
110
129
|
### Added
|
|
111
130
|
- initial release
|
|
112
131
|
|
|
113
|
-
[Unreleased]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/
|
|
132
|
+
[Unreleased]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/3.0.0...HEAD
|
|
133
|
+
[3.0.0]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/2.0.1...3.0.0
|
|
114
134
|
[2.0.1]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/2.0.0...2.0.1
|
|
115
135
|
[2.0.0]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/1.5.0...2.0.0
|
|
116
136
|
[1.5.0]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/1.4.0...1.5.0
|
data/README.md
CHANGED
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
[](https://codeclimate.com/github/sensu-plugins/sensu-plugins-ssl)
|
|
6
6
|
[](https://codeclimate.com/github/sensu-plugins/sensu-plugins-ssl)
|
|
7
7
|
[](https://gemnasium.com/sensu-plugins/sensu-plugins-ssl)
|
|
8
|
+
[](https://bonsai.sensu.io/assets/sensu-plugins/sensu-plugins-ssl)
|
|
8
9
|
|
|
10
|
+
## Sensu Asset
|
|
11
|
+
The Sensu assets packaged from this repository are built against the Sensu Ruby runtime environment. When using these assets as part of a Sensu Go resource (check, mutator or handler), make sure you include the corresponding Sensu Ruby runtime asset in the list of assets needed by the resource. The current ruby-runtime assets can be found [here](https://bonsai.sensu.io/assets/sensu/sensu-ruby-runtime) in the [Bonsai Asset Index](bonsai.sensu.io).
|
|
9
12
|
## Functionality
|
|
10
13
|
|
|
11
14
|
## Files
|
|
@@ -17,12 +20,13 @@
|
|
|
17
20
|
* bin/check-ssl-hsts-preload.rb
|
|
18
21
|
* bin/check-ssl-hsts-preloadable.rb
|
|
19
22
|
* bin/check-ssl-qualys.rb
|
|
23
|
+
* bin/check-ssl-root-issuer.rb
|
|
20
24
|
|
|
21
25
|
## Usage
|
|
22
26
|
|
|
23
27
|
### `bin/check-ssl-anchor.rb`
|
|
24
28
|
|
|
25
|
-
Check that a specific website is chained to a specific root certificate (Let's Encrypt for instance).
|
|
29
|
+
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
30
|
|
|
27
31
|
```
|
|
28
32
|
./bin/check-ssl-anchor.rb -u example.com -a "i:/O=Digital Signature Trust Co./CN=DST Root CA X3"
|
|
@@ -53,6 +57,13 @@ Checks the ssllabs qualysis api for grade of your server, this check can be quit
|
|
|
53
57
|
./bin/check-ssl-qualys.rb -d google.com
|
|
54
58
|
```
|
|
55
59
|
|
|
60
|
+
### `bin/check-ssl-root-issuer.rb`
|
|
61
|
+
|
|
62
|
+
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.
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
./bin/check-ssl-root-issuer.rb -u example.com -a "CN=DST Root CA X3,O=Digital Signature Trust Co."
|
|
66
|
+
```
|
|
56
67
|
|
|
57
68
|
## Installation
|
|
58
69
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
2
4
|
#
|
|
3
5
|
# check-java-keystore-cert
|
|
4
6
|
#
|
|
@@ -75,7 +77,7 @@ class CheckJavaKeystoreCert < Sensu::Plugin::Check::CLI
|
|
|
75
77
|
|
|
76
78
|
days_until = (certificate_expiration_date - Date.today).to_i
|
|
77
79
|
|
|
78
|
-
if days_until < 0
|
|
80
|
+
if days_until < 0 # rubocop: disable Style/NumericPredicate
|
|
79
81
|
critical "Expired #{days_until.abs} days ago"
|
|
80
82
|
elsif days_until < config[:critical]
|
|
81
83
|
critical "#{days_until} days left"
|
data/bin/check-ssl-anchor.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#! /usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
2
4
|
#
|
|
3
5
|
# check-ssl-anchor
|
|
4
6
|
#
|
|
@@ -57,6 +59,14 @@ class CheckSSLAnchor < Sensu::Plugin::Check::CLI
|
|
|
57
59
|
long: '--anchor ANCHOR_VAL',
|
|
58
60
|
required: true
|
|
59
61
|
|
|
62
|
+
option :regexp,
|
|
63
|
+
description: 'Treat the anchor as a regexp',
|
|
64
|
+
short: '-r',
|
|
65
|
+
long: '--regexp',
|
|
66
|
+
default: false,
|
|
67
|
+
boolean: true,
|
|
68
|
+
required: false
|
|
69
|
+
|
|
60
70
|
option :servername,
|
|
61
71
|
description: 'Set the TLS SNI (Server Name Indication) extension',
|
|
62
72
|
short: '-s',
|
|
@@ -79,7 +89,7 @@ class CheckSSLAnchor < Sensu::Plugin::Check::CLI
|
|
|
79
89
|
-servername #{config[:servername]} < /dev/null 2>&1`.match(/Certificate chain(.*)---\nServer certificate/m)[1].split(/$/).map(&:strip)
|
|
80
90
|
data = data.reject(&:empty?)
|
|
81
91
|
|
|
82
|
-
unless data[0] =~ /0 s
|
|
92
|
+
unless data[0] =~ /0 s:\/?CN ?=.*/m
|
|
83
93
|
data = 'NOTOK'
|
|
84
94
|
end
|
|
85
95
|
data
|
|
@@ -91,11 +101,22 @@ class CheckSSLAnchor < Sensu::Plugin::Check::CLI
|
|
|
91
101
|
if data == 'NOTOK'
|
|
92
102
|
critical 'An error was encountered while trying to retrieve the certificate chain.'
|
|
93
103
|
end
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
104
|
+
puts config[:regexp]
|
|
105
|
+
# rubocop:disable Style/IfInsideElse
|
|
106
|
+
if config[:regexp]
|
|
107
|
+
anchor_regexp = Regexp.new(config[:anchor].to_s)
|
|
108
|
+
if data[-1] =~ anchor_regexp
|
|
109
|
+
ok 'Root anchor has been found.'
|
|
110
|
+
else
|
|
111
|
+
critical 'Root anchor did not match regexp /' + config[:anchor].to_s + "/\nFound \"" + data[-1] + '" instead.'
|
|
112
|
+
end
|
|
97
113
|
else
|
|
98
|
-
|
|
114
|
+
if data[-1] == config[:anchor].to_s
|
|
115
|
+
ok 'Root anchor has been found.'
|
|
116
|
+
else
|
|
117
|
+
critical 'Root anchor did not match string "' + config[:anchor].to_s + "\"\nFound \"" + data[-1] + '" instead.'
|
|
118
|
+
end
|
|
99
119
|
end
|
|
120
|
+
# rubocop:enable Style/IfInsideElse
|
|
100
121
|
end
|
|
101
122
|
end
|
data/bin/check-ssl-cert.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#! /usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
2
4
|
#
|
|
3
5
|
# check-ssl-cert
|
|
4
6
|
#
|
|
@@ -117,7 +119,7 @@ class CheckSSLCert < Sensu::Plugin::Check::CLI
|
|
|
117
119
|
|
|
118
120
|
days_until = (Date.parse(expiry.to_s) - Date.today).to_i
|
|
119
121
|
|
|
120
|
-
if days_until < 0
|
|
122
|
+
if days_until < 0 # rubocop:disable Style/NumericPredicate
|
|
121
123
|
critical "Expired #{days_until.abs} days ago"
|
|
122
124
|
elsif days_until < config[:critical].to_i
|
|
123
125
|
critical "#{days_until} days left"
|
data/bin/check-ssl-crl.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#! /usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
2
4
|
#
|
|
3
5
|
# check-ssl-crl
|
|
4
6
|
#
|
|
@@ -65,10 +67,10 @@ class CheckSSLCRL < Sensu::Plugin::Check::CLI
|
|
|
65
67
|
def run
|
|
66
68
|
validate_opts
|
|
67
69
|
|
|
68
|
-
next_update = OpenSSL::X509::CRL.new(open(config[:url]).read).next_update
|
|
70
|
+
next_update = OpenSSL::X509::CRL.new(open(config[:url]).read).next_update # rubocop:disable Security/Open
|
|
69
71
|
minutes_until = seconds_to_minutes(Time.parse(next_update.to_s) - Time.now)
|
|
70
72
|
|
|
71
|
-
critical "#{config[:url]} - Expired #{minutes_until.abs} minutes ago" if minutes_until < 0
|
|
73
|
+
critical "#{config[:url]} - Expired #{minutes_until.abs} minutes ago" if minutes_until < 0 # rubocop:disable Style/NumericPredicate
|
|
72
74
|
critical "#{config[:url]} - #{minutes_until} minutes left, next update at #{next_update}" if minutes_until < config[:critical].to_i
|
|
73
75
|
warning "#{config[:url]} - #{minutes_until} minutes left, next update at #{next_update}" if minutes_until < config[:warning].to_i
|
|
74
76
|
ok "#{config[:url]} - #{minutes_until} minutes left, next update at #{next_update}"
|
data/bin/check-ssl-host.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
#
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
3
4
|
# check-ssl-host.rb
|
|
4
5
|
#
|
|
5
6
|
# DESCRIPTION:
|
|
@@ -42,7 +43,7 @@ require 'socket'
|
|
|
42
43
|
# Check SSL Host
|
|
43
44
|
#
|
|
44
45
|
class CheckSSLHost < Sensu::Plugin::Check::CLI
|
|
45
|
-
STARTTLS_PROTOS = %w
|
|
46
|
+
STARTTLS_PROTOS = %w[smtp imap].freeze
|
|
46
47
|
|
|
47
48
|
check_name 'check_ssl_host'
|
|
48
49
|
|
|
@@ -104,7 +105,7 @@ class CheckSSLHost < Sensu::Plugin::Check::CLI
|
|
|
104
105
|
long: '--starttls PROTO'
|
|
105
106
|
|
|
106
107
|
def get_cert_chain(host, port, address, client_cert, client_key)
|
|
107
|
-
tcp_client = TCPSocket.new(address ? address : host, port)
|
|
108
|
+
tcp_client = TCPSocket.new(address ? address : host, port) # rubocop:disable Style/RedundantCondition
|
|
108
109
|
handle_starttls(config[:starttls], tcp_client) if config[:starttls]
|
|
109
110
|
ssl_context = OpenSSL::SSL::SSLContext.new
|
|
110
111
|
ssl_context.cert = OpenSSL::X509::Certificate.new File.read(client_cert) if client_cert
|
|
@@ -139,6 +140,7 @@ class CheckSSLHost < Sensu::Plugin::Check::CLI
|
|
|
139
140
|
|
|
140
141
|
status = socket.readline
|
|
141
142
|
return if /^220 / =~ status
|
|
143
|
+
|
|
142
144
|
critical "#{config[:host]} - did not receive SMTP 220 in response to STARTTLS"
|
|
143
145
|
end
|
|
144
146
|
|
|
@@ -151,6 +153,7 @@ class CheckSSLHost < Sensu::Plugin::Check::CLI
|
|
|
151
153
|
|
|
152
154
|
status = socket.readline
|
|
153
155
|
return if /^a001 OK Begin TLS negotiation now/ =~ status
|
|
156
|
+
|
|
154
157
|
critical "#{config[:host]} - did not receive OK Begin TLS negotiation now"
|
|
155
158
|
end
|
|
156
159
|
|
|
@@ -158,7 +161,7 @@ class CheckSSLHost < Sensu::Plugin::Check::CLI
|
|
|
158
161
|
# Expiry check
|
|
159
162
|
days = (cert.not_after.to_date - Date.today).to_i
|
|
160
163
|
message = "#{config[:host]} - #{days} days until expiry"
|
|
161
|
-
critical "#{config[:host]} - Expired #{days} days ago" if days < 0
|
|
164
|
+
critical "#{config[:host]} - Expired #{days} days ago" if days < 0 # rubocop:disable Style/NumericPredicate
|
|
162
165
|
critical message if days < config[:critical]
|
|
163
166
|
warning message if days < config[:warning]
|
|
164
167
|
ok message
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
#
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
3
4
|
# check-ssl-hsts-preloadable.rb
|
|
4
5
|
#
|
|
5
6
|
# DESCRIPTION:
|
|
@@ -43,16 +44,16 @@ class CheckSSLHSTSPreloadable < Sensu::Plugin::Check::CLI
|
|
|
43
44
|
default: 'https://hstspreload.org/api/v2/preloadable'
|
|
44
45
|
|
|
45
46
|
def fetch(uri, limit = 10)
|
|
46
|
-
if limit == 0
|
|
47
|
+
if limit == 0 # rubocop:disable Style/NumericPredicate
|
|
47
48
|
return nil
|
|
48
49
|
end
|
|
49
50
|
|
|
50
51
|
response = Net::HTTP.get_response(uri)
|
|
51
52
|
|
|
52
53
|
case response
|
|
53
|
-
when Net::HTTPSuccess
|
|
54
|
+
when Net::HTTPSuccess
|
|
54
55
|
response
|
|
55
|
-
when Net::HTTPRedirection
|
|
56
|
+
when Net::HTTPRedirection
|
|
56
57
|
location = URI(response['location'])
|
|
57
58
|
fetch(location, limit - 1)
|
|
58
59
|
end
|
|
@@ -65,6 +66,7 @@ class CheckSSLHSTSPreloadable < Sensu::Plugin::Check::CLI
|
|
|
65
66
|
if response.nil?
|
|
66
67
|
return warning 'Bad response recieved from API'
|
|
67
68
|
end
|
|
69
|
+
|
|
68
70
|
body = JSON.parse(response.body)
|
|
69
71
|
if !body['errors'].empty?
|
|
70
72
|
critical body['errors'].map { |u| u['summary'] }.join(', ')
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
#
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
3
4
|
# check-ssl-hsts-preload.rb
|
|
4
5
|
#
|
|
5
6
|
# DESCRIPTION:
|
|
@@ -33,7 +34,7 @@ require 'json'
|
|
|
33
34
|
require 'net/http'
|
|
34
35
|
|
|
35
36
|
class CheckSSLHSTSStatus < Sensu::Plugin::Check::CLI
|
|
36
|
-
STATUSES = %w
|
|
37
|
+
STATUSES = %w[unknown pending preloaded].freeze
|
|
37
38
|
|
|
38
39
|
option :domain,
|
|
39
40
|
description: 'The domain to run the test against',
|
|
@@ -61,16 +62,16 @@ class CheckSSLHSTSStatus < Sensu::Plugin::Check::CLI
|
|
|
61
62
|
default: 'https://hstspreload.org/api/v2/status'
|
|
62
63
|
|
|
63
64
|
def fetch(uri, limit = 10)
|
|
64
|
-
if limit == 0
|
|
65
|
+
if limit == 0 # rubocop:disable Style/NumericPredicate
|
|
65
66
|
return nil
|
|
66
67
|
end
|
|
67
68
|
|
|
68
69
|
response = Net::HTTP.get_response(uri)
|
|
69
70
|
|
|
70
71
|
case response
|
|
71
|
-
when Net::HTTPSuccess
|
|
72
|
+
when Net::HTTPSuccess
|
|
72
73
|
response
|
|
73
|
-
when Net::HTTPRedirection
|
|
74
|
+
when Net::HTTPRedirection
|
|
74
75
|
location = URI(response['location'])
|
|
75
76
|
fetch(location, limit - 1)
|
|
76
77
|
end
|
|
@@ -83,6 +84,7 @@ class CheckSSLHSTSStatus < Sensu::Plugin::Check::CLI
|
|
|
83
84
|
if response.nil?
|
|
84
85
|
return warning 'Bad response recieved from API'
|
|
85
86
|
end
|
|
87
|
+
|
|
86
88
|
body = JSON.parse(response.body)
|
|
87
89
|
unless STATUSES.include? body['status']
|
|
88
90
|
warning 'Invalid status returned ' + body['status']
|
data/bin/check-ssl-qualys.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
#
|
|
2
|
+
# frozen_string_literal: false
|
|
3
3
|
|
|
4
4
|
# check-ssl-qualys.rb
|
|
5
5
|
#
|
|
@@ -138,7 +138,8 @@ class CheckSSLQualys < Sensu::Plugin::Check::CLI
|
|
|
138
138
|
ssl_check(true)
|
|
139
139
|
end
|
|
140
140
|
return json if json['status'] == 'READY'
|
|
141
|
-
|
|
141
|
+
|
|
142
|
+
if json['endpoints'] && json['endpoints'].is_a?(Array) # rubocop:disable Style/SafeNavigation
|
|
142
143
|
p "endpoints: #{json['endpoints']}" if config[:debug]
|
|
143
144
|
# The api response sometimes has low eta (which seems unrealistic) from
|
|
144
145
|
# my tests that can be 0 or low numbers which would imply it is done...
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#! /usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
4
|
+
#
|
|
5
|
+
# check-ssl-root-issuer
|
|
6
|
+
#
|
|
7
|
+
# DESCRIPTION:
|
|
8
|
+
# Check that a certificate is chained to a specific root certificate issuer
|
|
9
|
+
#
|
|
10
|
+
# OUTPUT:
|
|
11
|
+
# plain text
|
|
12
|
+
#
|
|
13
|
+
# PLATFORMS:
|
|
14
|
+
# Linux
|
|
15
|
+
#
|
|
16
|
+
# DEPENDENCIES:
|
|
17
|
+
# gem: sensu-plugin
|
|
18
|
+
#
|
|
19
|
+
# USAGE:
|
|
20
|
+
#
|
|
21
|
+
# Check that a specific website is chained to a specific root certificate
|
|
22
|
+
# ./check-ssl-root-issuer.rb \
|
|
23
|
+
# -u https://example.com \
|
|
24
|
+
# -i "CN=DST Root CA X3,O=Digital Signature Trust Co."
|
|
25
|
+
#
|
|
26
|
+
# LICENSE:
|
|
27
|
+
# Copyright Jef Spaleta (jspaleta@gmail.com) 2020
|
|
28
|
+
# Released under the same terms as Sensu (the MIT license); see LICENSE
|
|
29
|
+
# for details.
|
|
30
|
+
#
|
|
31
|
+
|
|
32
|
+
require 'sensu-plugin/check/cli'
|
|
33
|
+
require 'openssl'
|
|
34
|
+
require 'uri'
|
|
35
|
+
require 'net/http'
|
|
36
|
+
require 'net/https'
|
|
37
|
+
|
|
38
|
+
#
|
|
39
|
+
# Check root certificate has specified issuer name
|
|
40
|
+
#
|
|
41
|
+
class CheckSSLRootIssuer < Sensu::Plugin::Check::CLI
|
|
42
|
+
option :url,
|
|
43
|
+
description: 'Url to check: Ex "https://google.com"',
|
|
44
|
+
short: '-u',
|
|
45
|
+
long: '--url URL',
|
|
46
|
+
required: true
|
|
47
|
+
|
|
48
|
+
option :issuer,
|
|
49
|
+
description: 'An X509 certificate issuer name, RFC2253 format Ex: "CN=DST Root CA X3,O=Digital Signature Trust Co."',
|
|
50
|
+
short: '-i',
|
|
51
|
+
long: '--issuer ISSUER_NAME',
|
|
52
|
+
required: true
|
|
53
|
+
|
|
54
|
+
option :regexp,
|
|
55
|
+
description: 'Treat the issuer name as a regexp',
|
|
56
|
+
short: '-r',
|
|
57
|
+
long: '--regexp',
|
|
58
|
+
default: false,
|
|
59
|
+
boolean: true,
|
|
60
|
+
required: false
|
|
61
|
+
|
|
62
|
+
option :format,
|
|
63
|
+
description: 'optional issuer name format.',
|
|
64
|
+
short: '-f',
|
|
65
|
+
long: '--format FORMAT_VAL',
|
|
66
|
+
default: 'RFC2253',
|
|
67
|
+
in: %w[RFC2253 ONELINE COMPAT],
|
|
68
|
+
required: false
|
|
69
|
+
|
|
70
|
+
def cert_name_format
|
|
71
|
+
# Note: because format argument is pre-validated by mixin 'in' logic eval is safe to use
|
|
72
|
+
eval "OpenSSL::X509::Name::#{config[:format]}" # rubocop:disable Security/Eval, Style/EvalWithLocation
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def validate_issuer(cert)
|
|
76
|
+
issuer = cert.issuer.to_s(cert_name_format)
|
|
77
|
+
if config[:regexp]
|
|
78
|
+
issuer_regexp = Regexp.new(config[:issuer].to_s)
|
|
79
|
+
issuer =~ issuer_regexp
|
|
80
|
+
else
|
|
81
|
+
issuer == config[:issuer].to_s
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def find_root_cert(uri)
|
|
86
|
+
root_cert = nil
|
|
87
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
88
|
+
http.open_timeout = 10
|
|
89
|
+
http.read_timeout = 10
|
|
90
|
+
http.use_ssl = true
|
|
91
|
+
http.cert_store = OpenSSL::X509::Store.new
|
|
92
|
+
http.cert_store.set_default_paths
|
|
93
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
94
|
+
|
|
95
|
+
http.verify_callback = lambda { |verify_ok, store_context|
|
|
96
|
+
root_cert = store_context.current_cert unless root_cert # rubocop:disable Style/OrAssignment
|
|
97
|
+
unless verify_ok
|
|
98
|
+
@failed_cert = store_context.current_cert
|
|
99
|
+
@failed_cert_reason = [store_context.error, store_context.error_string] if store_context.error != 0
|
|
100
|
+
end
|
|
101
|
+
verify_ok
|
|
102
|
+
}
|
|
103
|
+
http.start {}
|
|
104
|
+
root_cert
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Do the actual work and massage some data
|
|
108
|
+
|
|
109
|
+
def run
|
|
110
|
+
@fail_cert = nil
|
|
111
|
+
@failed_cert_reason = 'Unknown'
|
|
112
|
+
uri = URI.parse(config[:url])
|
|
113
|
+
critical "url protocol must be https, you specified #{url}" if uri.scheme != 'https'
|
|
114
|
+
root_cert = find_root_cert(uri)
|
|
115
|
+
if @failed_cert
|
|
116
|
+
msg = "Certificate verification failed.\n Reason: #{@failed_cert_reason}"
|
|
117
|
+
critical msg
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
if validate_issuer(root_cert)
|
|
121
|
+
msg = 'Root certificate in chain has expected issuer name'
|
|
122
|
+
ok msg
|
|
123
|
+
else
|
|
124
|
+
msg = "Root certificate issuer did not match expected name.\nFound: \"#{root_cert.issuer.to_s(config[:issuer_format])}\""
|
|
125
|
+
critical msg
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
data/lib/sensu-plugins-ssl.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sensu-plugins-ssl
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sensu-Plugins and contributors
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2020-08-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: sensu-plugin
|
|
@@ -16,28 +16,28 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '4.0'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
26
|
+
version: '4.0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: bundler
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '1
|
|
33
|
+
version: '2.1'
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '1
|
|
40
|
+
version: '2.1'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: codeclimate-test-reporter
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -58,14 +58,14 @@ dependencies:
|
|
|
58
58
|
requirements:
|
|
59
59
|
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '
|
|
61
|
+
version: '3.0'
|
|
62
62
|
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: '
|
|
68
|
+
version: '3.0'
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: pry
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -86,14 +86,14 @@ dependencies:
|
|
|
86
86
|
requirements:
|
|
87
87
|
- - "~>"
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '
|
|
89
|
+
version: '13.0'
|
|
90
90
|
type: :development
|
|
91
91
|
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
94
|
- - "~>"
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '
|
|
96
|
+
version: '13.0'
|
|
97
97
|
- !ruby/object:Gem::Dependency
|
|
98
98
|
name: redcarpet
|
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -128,55 +128,56 @@ dependencies:
|
|
|
128
128
|
requirements:
|
|
129
129
|
- - "~>"
|
|
130
130
|
- !ruby/object:Gem::Version
|
|
131
|
-
version: 0.
|
|
131
|
+
version: 0.89.1
|
|
132
132
|
type: :development
|
|
133
133
|
prerelease: false
|
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
|
135
135
|
requirements:
|
|
136
136
|
- - "~>"
|
|
137
137
|
- !ruby/object:Gem::Version
|
|
138
|
-
version: 0.
|
|
138
|
+
version: 0.89.1
|
|
139
139
|
- !ruby/object:Gem::Dependency
|
|
140
|
-
name:
|
|
140
|
+
name: timecop
|
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
|
142
142
|
requirements:
|
|
143
143
|
- - "~>"
|
|
144
144
|
- !ruby/object:Gem::Version
|
|
145
|
-
version:
|
|
145
|
+
version: 0.8.0
|
|
146
146
|
type: :development
|
|
147
147
|
prerelease: false
|
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
|
149
149
|
requirements:
|
|
150
150
|
- - "~>"
|
|
151
151
|
- !ruby/object:Gem::Version
|
|
152
|
-
version:
|
|
152
|
+
version: 0.8.0
|
|
153
153
|
- !ruby/object:Gem::Dependency
|
|
154
|
-
name:
|
|
154
|
+
name: yard
|
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
|
156
156
|
requirements:
|
|
157
157
|
- - "~>"
|
|
158
158
|
- !ruby/object:Gem::Version
|
|
159
|
-
version: 0.8
|
|
159
|
+
version: '0.8'
|
|
160
160
|
type: :development
|
|
161
161
|
prerelease: false
|
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
|
163
163
|
requirements:
|
|
164
164
|
- - "~>"
|
|
165
165
|
- !ruby/object:Gem::Version
|
|
166
|
-
version: 0.8
|
|
166
|
+
version: '0.8'
|
|
167
167
|
description: |-
|
|
168
168
|
This plugin provides native SSL instrumentation
|
|
169
169
|
for monitoring, including: hostname and chain
|
|
170
170
|
verification, cert and crl expiry, and Qualys SSL Labs reporting
|
|
171
171
|
email: "<sensu-users@googlegroups.com>"
|
|
172
172
|
executables:
|
|
173
|
-
- check-
|
|
174
|
-
- check-ssl-
|
|
173
|
+
- check-ssl-hsts-status.rb
|
|
174
|
+
- check-ssl-root-issuer.rb
|
|
175
175
|
- check-ssl-cert.rb
|
|
176
|
+
- check-java-keystore-cert.rb
|
|
176
177
|
- check-ssl-crl.rb
|
|
178
|
+
- check-ssl-anchor.rb
|
|
177
179
|
- check-ssl-host.rb
|
|
178
180
|
- check-ssl-hsts-preloadable.rb
|
|
179
|
-
- check-ssl-hsts-status.rb
|
|
180
181
|
- check-ssl-qualys.rb
|
|
181
182
|
extensions: []
|
|
182
183
|
extra_rdoc_files: []
|
|
@@ -192,6 +193,7 @@ files:
|
|
|
192
193
|
- bin/check-ssl-hsts-preloadable.rb
|
|
193
194
|
- bin/check-ssl-hsts-status.rb
|
|
194
195
|
- bin/check-ssl-qualys.rb
|
|
196
|
+
- bin/check-ssl-root-issuer.rb
|
|
195
197
|
- lib/sensu-plugins-ssl.rb
|
|
196
198
|
- lib/sensu-plugins-ssl/version.rb
|
|
197
199
|
homepage: https://github.com/sensu-plugins/sensu-plugins-ssl
|
|
@@ -212,15 +214,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
212
214
|
requirements:
|
|
213
215
|
- - ">="
|
|
214
216
|
- !ruby/object:Gem::Version
|
|
215
|
-
version: 2.
|
|
217
|
+
version: 2.4.0
|
|
216
218
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
217
219
|
requirements:
|
|
218
220
|
- - ">="
|
|
219
221
|
- !ruby/object:Gem::Version
|
|
220
222
|
version: '0'
|
|
221
223
|
requirements: []
|
|
222
|
-
|
|
223
|
-
rubygems_version: 2.7.7
|
|
224
|
+
rubygems_version: 3.0.8
|
|
224
225
|
signing_key:
|
|
225
226
|
specification_version: 4
|
|
226
227
|
summary: Sensu plugins for SSL
|