sensu-plugins-ssl 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -1
- data/README.md +22 -2
- data/bin/check-java-keystore-cert.rb +87 -0
- data/bin/check-ssl-crl.rb +76 -0
- data/bin/check-ssl-host.rb +40 -6
- data/bin/check-ssl-qualys.rb +10 -2
- data/lib/sensu-plugins-ssl/version.rb +1 -1
- metadata +22 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad7f900ae9946ad4bb040d4e7968761847ca38f6
|
4
|
+
data.tar.gz: f7485dfc07f15d1789ef4000455a60e3b32c78d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c2a81176f56ca91455c54ffa18e62f34e26d9fb1cc29cbdd53e9fa421aa5e7552f251e799fd4191ff806dbe228e3b29b9261d7a3bd4f76b449b89f4a544d405
|
7
|
+
data.tar.gz: 17e6353a089229402fb90abc4a2729a0221e43f4fd820aa3b402d32da60318e1c9e8207a18cdaf870c170ddc1258b432c0f7aefd114a6de607adc0a203dc962f
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,20 @@ This CHANGELOG follows the format listed at [Keep A Changelog](http://keepachang
|
|
5
5
|
|
6
6
|
## [Unreleased]
|
7
7
|
|
8
|
+
## [1.1.0] - 2017-02-28
|
9
|
+
### Added
|
10
|
+
- `check-ssl-host.rb`: Add optional `address` command line parameter for specifying the address of the server to
|
11
|
+
connect to, to override the `hostname` parameter (which is still used for verification/SNI) (@advance512)
|
12
|
+
- `check-ssl-host.rb`: Better error message when unable to connect to target host (@johntdyer)
|
13
|
+
- `check-ssl-host.rb`: Add support for client certificates (@modax)
|
14
|
+
- `check-ssl-host.rb`: Add basic IMAP STARTTLS negotiation (@lobeck)
|
15
|
+
- `check-java-keystore-cert.rb`: Add new check to verify a certificate in a Java Keystore has not expired. (@joerayme)
|
16
|
+
- `check-ssl-crl.rb`: Add check for expiring CRL (@shoekstra)
|
17
|
+
|
18
|
+
### Fixed
|
19
|
+
- `check-ssl-qualys.rb`: Handle API errors with status unknown instead of unhandled "Check failed to run". (@11mariom)
|
20
|
+
- `check-ssl-qualys.rb`: Handle nil grade_rank as critical not rated (@11mariom)
|
21
|
+
|
8
22
|
## [1.0.0]
|
9
23
|
### Changed
|
10
24
|
- Updated Rubocop to 0.40, applied auto-correct
|
@@ -47,7 +61,8 @@ This CHANGELOG follows the format listed at [Keep A Changelog](http://keepachang
|
|
47
61
|
### Added
|
48
62
|
- initial release
|
49
63
|
|
50
|
-
[unreleased]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/1.
|
64
|
+
[unreleased]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/1.1.0...HEAD
|
65
|
+
[1.1.0]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/1.0.0...1.1.0
|
51
66
|
[1.0.0]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/0.0.6...1.0.0
|
52
67
|
[0.0.6]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/0.0.5...0.0.6
|
53
68
|
[0.0.5]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/0.0.4...0.0.5
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
## Sensu-Plugins-
|
1
|
+
## Sensu-Plugins-SSL
|
2
2
|
|
3
|
-
[
|
3
|
+
[![Build Status](https://travis-ci.org/sensu-plugins/sensu-plugins-ssl.svg?branch=master)](https://travis-ci.org/sensu-plugins/sensu-plugins-ssl)
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/sensu-plugins-ssl.svg)](http://badge.fury.io/rb/sensu-plugins-ssl)
|
5
5
|
[![Code Climate](https://codeclimate.com/github/sensu-plugins/sensu-plugins-ssl/badges/gpa.svg)](https://codeclimate.com/github/sensu-plugins/sensu-plugins-ssl)
|
6
6
|
[![Test Coverage](https://codeclimate.com/github/sensu-plugins/sensu-plugins-ssl/badges/coverage.svg)](https://codeclimate.com/github/sensu-plugins/sensu-plugins-ssl)
|
@@ -9,12 +9,32 @@
|
|
9
9
|
## Functionality
|
10
10
|
|
11
11
|
## Files
|
12
|
+
* bin/check-java-keystore-cert.rb
|
13
|
+
* bin/check-ssl-crl.rb
|
12
14
|
* bin/check-ssl-cert.rb
|
13
15
|
* bin/check-ssl-host.rb
|
14
16
|
* bin/check-ssl-qualys.rb
|
15
17
|
|
16
18
|
## Usage
|
17
19
|
|
20
|
+
### `bin/check-ssl-crl.rb`
|
21
|
+
|
22
|
+
Checks a CRL has not or is not expiring by inspecting it's next update value.
|
23
|
+
|
24
|
+
You can check against a CRL file on disk:
|
25
|
+
|
26
|
+
```
|
27
|
+
./bin/check-ssl-crl -c 300 -w 600 -u /path/to/crl
|
28
|
+
```
|
29
|
+
|
30
|
+
or an online CRL:
|
31
|
+
|
32
|
+
```
|
33
|
+
./bin/check-ssl-crl -c 300 -w 600 -u http://www.website.com/file.crl
|
34
|
+
```
|
35
|
+
|
36
|
+
Critical and Warning thresholds are specified in minutes.
|
37
|
+
|
18
38
|
## Installation
|
19
39
|
|
20
40
|
[Installation and Setup](http://sensu-plugins.io/docs/installation_instructions.html)
|
@@ -0,0 +1,87 @@
|
|
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 'sensu-plugin/check/cli'
|
26
|
+
|
27
|
+
class CheckJavaKeystoreCert < Sensu::Plugin::Check::CLI
|
28
|
+
option :path,
|
29
|
+
long: '--path PATH',
|
30
|
+
description: '',
|
31
|
+
required: true
|
32
|
+
|
33
|
+
option :alias,
|
34
|
+
long: '--alias ALIAS',
|
35
|
+
description: '',
|
36
|
+
required: true
|
37
|
+
|
38
|
+
option :password,
|
39
|
+
long: '--password PASSWORD',
|
40
|
+
description: '',
|
41
|
+
required: true
|
42
|
+
|
43
|
+
option :warning,
|
44
|
+
long: '--warning DAYS',
|
45
|
+
description: '',
|
46
|
+
proc: proc { |v| v.to_i },
|
47
|
+
required: true
|
48
|
+
|
49
|
+
option :critical,
|
50
|
+
long: '--critical DAYS',
|
51
|
+
description: '',
|
52
|
+
proc: proc { |v| v.to_i },
|
53
|
+
required: true
|
54
|
+
|
55
|
+
def certificate_expiration_date
|
56
|
+
result = `keytool -keystore #{config[:path]} \
|
57
|
+
-export -alias #{config[:alias]} \
|
58
|
+
-storepass #{config[:password]} 2>&1 | \
|
59
|
+
openssl x509 -enddate -inform der -noout 2>&1`
|
60
|
+
|
61
|
+
# rubocop:disable Style/SpecialGlobalVars
|
62
|
+
unknown 'could not get certificate from keystore' unless $?.success?
|
63
|
+
# rubocop:enable Style/SpecialGlobalVars
|
64
|
+
|
65
|
+
Date.parse(result.split('=').last)
|
66
|
+
end
|
67
|
+
|
68
|
+
def validate_opts
|
69
|
+
unknown 'warning cannot be less than critical' if config[:warning] < config[:critical]
|
70
|
+
end
|
71
|
+
|
72
|
+
def run
|
73
|
+
validate_opts
|
74
|
+
|
75
|
+
days_until = (certificate_expiration_date - Date.today).to_i
|
76
|
+
|
77
|
+
if days_until < 0
|
78
|
+
critical "Expired #{days_until.abs} days ago"
|
79
|
+
elsif days_until < config[:critical]
|
80
|
+
critical "#{days_until} days left"
|
81
|
+
elsif days_until < config[:warning]
|
82
|
+
warning "#{days_until} days left"
|
83
|
+
end
|
84
|
+
|
85
|
+
ok "#{days_until} days left"
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# check-ssl-crl
|
4
|
+
#
|
5
|
+
# DESCRIPTION:
|
6
|
+
# Check in minutes when a certificate revocation list will expire.
|
7
|
+
#
|
8
|
+
# OUTPUT:
|
9
|
+
# plain text
|
10
|
+
#
|
11
|
+
# PLATFORMS:
|
12
|
+
# Linux
|
13
|
+
#
|
14
|
+
# DEPENDENCIES:
|
15
|
+
# gem: sensu-plugin
|
16
|
+
#
|
17
|
+
# USAGE:
|
18
|
+
# ./check-ssl-crl -c 300 -w 600 -u /path/to/crl
|
19
|
+
# ./check-ssl-crl -c 300 -w 600 -u http://www.website.com/file.crl
|
20
|
+
#
|
21
|
+
# LICENSE:
|
22
|
+
# Stephen Hoekstra <shoekstra@schubergphilis.com>
|
23
|
+
#
|
24
|
+
# Released under the same terms as Sensu (the MIT license); see LICENSE
|
25
|
+
# for details.
|
26
|
+
#
|
27
|
+
|
28
|
+
require 'open-uri'
|
29
|
+
require 'openssl'
|
30
|
+
require 'sensu-plugin/check/cli'
|
31
|
+
require 'time'
|
32
|
+
|
33
|
+
#
|
34
|
+
# Check SSL Cert
|
35
|
+
#
|
36
|
+
class CheckSSLCRL < Sensu::Plugin::Check::CLI
|
37
|
+
option :critical,
|
38
|
+
description: 'Numbers of minutes left',
|
39
|
+
short: '-c',
|
40
|
+
long: '--critical MINUTES',
|
41
|
+
proc: proc { |v| v.to_i },
|
42
|
+
required: true
|
43
|
+
|
44
|
+
option :url,
|
45
|
+
description: 'URL (or path) to CRL file',
|
46
|
+
short: '-u',
|
47
|
+
long: '--url URL',
|
48
|
+
required: true
|
49
|
+
|
50
|
+
option :warning,
|
51
|
+
description: 'Numbers of minutes left',
|
52
|
+
short: '-w',
|
53
|
+
long: '--warning MINUTES',
|
54
|
+
proc: proc { |v| v.to_i },
|
55
|
+
required: true
|
56
|
+
|
57
|
+
def seconds_to_minutes(seconds)
|
58
|
+
(seconds / 60).to_i
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate_opts
|
62
|
+
unknown 'warning cannot be less than critical' if config[:warning] < config[:critical]
|
63
|
+
end
|
64
|
+
|
65
|
+
def run
|
66
|
+
validate_opts
|
67
|
+
|
68
|
+
next_update = OpenSSL::X509::CRL.new(open(config[:url]).read).next_update
|
69
|
+
minutes_until = seconds_to_minutes(Time.parse(next_update.to_s) - Time.now)
|
70
|
+
|
71
|
+
critical "#{config[:url]} - Expired #{minutes_until.abs} minutes ago" if minutes_until < 0
|
72
|
+
critical "#{config[:url]} - #{minutes_until} minutes left, next update at #{next_update}" if minutes_until < config[:critical].to_i
|
73
|
+
warning "#{config[:url]} - #{minutes_until} minutes left, next update at #{next_update}" if minutes_until < config[:warning].to_i
|
74
|
+
ok "#{config[:url]} - #{minutes_until} minutes left, next update at #{next_update}"
|
75
|
+
end
|
76
|
+
end
|
data/bin/check-ssl-host.rb
CHANGED
@@ -42,7 +42,7 @@ require 'socket'
|
|
42
42
|
# Check SSL Host
|
43
43
|
#
|
44
44
|
class CheckSSLHost < Sensu::Plugin::Check::CLI
|
45
|
-
STARTTLS_PROTOS = %w(smtp).freeze
|
45
|
+
STARTTLS_PROTOS = %w(smtp imap).freeze
|
46
46
|
|
47
47
|
check_name 'check_ssl_host'
|
48
48
|
|
@@ -62,7 +62,8 @@ class CheckSSLHost < Sensu::Plugin::Check::CLI
|
|
62
62
|
default: 14
|
63
63
|
|
64
64
|
option :host,
|
65
|
-
description: 'Hostname of server to check'
|
65
|
+
description: 'Hostname of the server certificate to check, by default used as the server address if none ' \
|
66
|
+
'is given',
|
66
67
|
short: '-h',
|
67
68
|
long: '--host HOST',
|
68
69
|
required: true
|
@@ -73,6 +74,20 @@ class CheckSSLHost < Sensu::Plugin::Check::CLI
|
|
73
74
|
long: '--port PORT',
|
74
75
|
default: 443
|
75
76
|
|
77
|
+
option :address,
|
78
|
+
description: 'Address of server to check. This is used instead of the host argument for the TCP connection, ' \
|
79
|
+
'however the server hostname is still used for the TLS/SSL context.',
|
80
|
+
short: '-a',
|
81
|
+
long: '--address ADDRESS'
|
82
|
+
|
83
|
+
option :client_cert,
|
84
|
+
description: 'Path to the client certificate in DER/PEM format',
|
85
|
+
long: '--client-cert CERT'
|
86
|
+
|
87
|
+
option :client_key,
|
88
|
+
description: 'Path to the client RSA key in DER/PEM format',
|
89
|
+
long: '--client-key KEY'
|
90
|
+
|
76
91
|
option :skip_hostname_verification,
|
77
92
|
description: 'Disables hostname verification',
|
78
93
|
long: '--skip-hostname-verification',
|
@@ -88,13 +103,18 @@ class CheckSSLHost < Sensu::Plugin::Check::CLI
|
|
88
103
|
"(#{STARTTLS_PROTOS.join(', ')})",
|
89
104
|
long: '--starttls PROTO'
|
90
105
|
|
91
|
-
def get_cert_chain(host, port)
|
92
|
-
tcp_client = TCPSocket.new(host, port)
|
106
|
+
def get_cert_chain(host, port, address, client_cert, client_key)
|
107
|
+
tcp_client = TCPSocket.new(address ? address : host, port)
|
93
108
|
handle_starttls(config[:starttls], tcp_client) if config[:starttls]
|
94
109
|
ssl_context = OpenSSL::SSL::SSLContext.new
|
110
|
+
ssl_context.cert = OpenSSL::X509::Certificate.new File.read(client_cert) if client_cert
|
111
|
+
ssl_context.key = OpenSSL::PKey::RSA.new File.read(client_key) if client_key
|
95
112
|
ssl_client = OpenSSL::SSL::SSLSocket.new(tcp_client, ssl_context)
|
96
|
-
|
113
|
+
|
114
|
+
# If the OpenSSL version in use supports Server Name Indication (SNI, RFC 3546), then we set the hostname we
|
115
|
+
# received to request that certificate.
|
97
116
|
ssl_client.hostname = host if ssl_client.respond_to? :hostname=
|
117
|
+
|
98
118
|
ssl_client.connect
|
99
119
|
certs = ssl_client.peer_cert_chain
|
100
120
|
ssl_client.close
|
@@ -122,6 +142,18 @@ class CheckSSLHost < Sensu::Plugin::Check::CLI
|
|
122
142
|
critical "#{config[:host]} - did not receive SMTP 220 in response to STARTTLS"
|
123
143
|
end
|
124
144
|
|
145
|
+
def starttls_imap(socket)
|
146
|
+
status = socket.readline
|
147
|
+
unless /^* OK / =~ status
|
148
|
+
critical "#{config[:host]} - did not receive initial * OK"
|
149
|
+
end
|
150
|
+
socket.puts 'a001 STARTTLS'
|
151
|
+
|
152
|
+
status = socket.readline
|
153
|
+
return if /^a001 OK Begin TLS negotiation now/ =~ status
|
154
|
+
critical "#{config[:host]} - did not receive OK Begin TLS negotiation now"
|
155
|
+
end
|
156
|
+
|
125
157
|
def verify_expiry(cert)
|
126
158
|
# Expiry check
|
127
159
|
days = (cert.not_after.to_date - Date.today).to_i
|
@@ -154,9 +186,11 @@ class CheckSSLHost < Sensu::Plugin::Check::CLI
|
|
154
186
|
end
|
155
187
|
|
156
188
|
def run
|
157
|
-
chain = get_cert_chain(config[:host], config[:port])
|
189
|
+
chain = get_cert_chain(config[:host], config[:port], config[:address], config[:client_cert], config[:client_key])
|
158
190
|
verify_hostname(chain[0]) unless config[:skip_hostname_verification]
|
159
191
|
verify_certificate_chain(chain) unless config[:skip_chain_verification]
|
160
192
|
verify_expiry(chain[0])
|
193
|
+
rescue Errno::ECONNRESET => e
|
194
|
+
critical "#{e.class} - #{e.message}"
|
161
195
|
end
|
162
196
|
end
|
data/bin/check-ssl-qualys.rb
CHANGED
@@ -90,8 +90,12 @@ class CheckSSLQualys < Sensu::Plugin::Check::CLI
|
|
90
90
|
def ssl_api_request(from_cache)
|
91
91
|
params = { host: config[:domain] }
|
92
92
|
params[:startNew] = 'on' unless from_cache
|
93
|
-
|
94
|
-
|
93
|
+
begin
|
94
|
+
r = RestClient.get("#{config[:api_url]}analyze", params: params)
|
95
|
+
warning "HTTP#{r.code} recieved from API" unless r.code == 200
|
96
|
+
rescue RestClient::ExceptionWithResponse => e
|
97
|
+
unknown e.response
|
98
|
+
end
|
95
99
|
JSON.parse(r.body)
|
96
100
|
end
|
97
101
|
|
@@ -122,6 +126,10 @@ class CheckSSLQualys < Sensu::Plugin::Check::CLI
|
|
122
126
|
|
123
127
|
def run
|
124
128
|
grade = lowest_grade
|
129
|
+
unless grade
|
130
|
+
message "#{config[:domain]} not rated"
|
131
|
+
critical
|
132
|
+
end
|
125
133
|
message "#{config[:domain]} rated #{grade}"
|
126
134
|
grade_rank = GRADE_OPTIONS.index(grade)
|
127
135
|
if grade_rank > config[:critical]
|
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: 1.
|
4
|
+
version: 1.1.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: 2017-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sensu-plugin
|
@@ -164,13 +164,29 @@ dependencies:
|
|
164
164
|
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0.8'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: timecop
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: 0.8.0
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: 0.8.0
|
167
181
|
description: |-
|
168
182
|
This plugin provides native SSL instrumentation
|
169
183
|
for monitoring, including: hostname and chain
|
170
|
-
verification, cert expiry, and Qualys SSL Labs reporting
|
184
|
+
verification, cert and crl expiry, and Qualys SSL Labs reporting
|
171
185
|
email: "<sensu-users@googlegroups.com>"
|
172
186
|
executables:
|
187
|
+
- check-java-keystore-cert.rb
|
173
188
|
- check-ssl-cert.rb
|
189
|
+
- check-ssl-crl.rb
|
174
190
|
- check-ssl-host.rb
|
175
191
|
- check-ssl-qualys.rb
|
176
192
|
extensions: []
|
@@ -179,7 +195,9 @@ files:
|
|
179
195
|
- CHANGELOG.md
|
180
196
|
- LICENSE
|
181
197
|
- README.md
|
198
|
+
- bin/check-java-keystore-cert.rb
|
182
199
|
- bin/check-ssl-cert.rb
|
200
|
+
- bin/check-ssl-crl.rb
|
183
201
|
- bin/check-ssl-host.rb
|
184
202
|
- bin/check-ssl-qualys.rb
|
185
203
|
- lib/sensu-plugins-ssl.rb
|
@@ -210,9 +228,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
210
228
|
version: '0'
|
211
229
|
requirements: []
|
212
230
|
rubyforge_project:
|
213
|
-
rubygems_version: 2.5
|
231
|
+
rubygems_version: 2.4.5
|
214
232
|
signing_key:
|
215
233
|
specification_version: 4
|
216
234
|
summary: Sensu plugins for SSL
|
217
235
|
test_files: []
|
218
|
-
has_rdoc:
|