sensu-plugins-ssl 1.0.0 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bd6139788580da152ea21011bcf673388d067cf2
4
- data.tar.gz: 96c53d56a691211326adc84b967e0282bf31c7fc
3
+ metadata.gz: ad7f900ae9946ad4bb040d4e7968761847ca38f6
4
+ data.tar.gz: f7485dfc07f15d1789ef4000455a60e3b32c78d8
5
5
  SHA512:
6
- metadata.gz: 9aa9628fc76a95b28c8cd070cc5676e834ee950e7a69edc1569dd117dd5397300ee1ce7e9561f2c025172b121eb71f53d8283e1e6c760ed575fd83d071b0fa1f
7
- data.tar.gz: f2fdde4418085c7167972c88e44e3728e15d9a69cb9506da3f9149a5e119ab4231984f2648a70a48aa0d3a15d56fac1fec3f9e5d451274c8f22c110dd49a14d9
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.0.0...HEAD
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-ssl
1
+ ## Sensu-Plugins-SSL
2
2
 
3
- [ ![Build Status](https://travis-ci.org/sensu-plugins/sensu-plugins-ssl.svg?branch=master)](https://travis-ci.org/sensu-plugins/sensu-plugins-ssl)
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
@@ -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
- # SNI
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
@@ -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
- r = RestClient.get("#{config[:api_url]}analyze", params: params)
94
- warning "HTTP#{r.code} recieved from API" unless r.code == 200
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]
@@ -1,7 +1,7 @@
1
1
  module SensuPluginsSSL
2
2
  module Version
3
3
  MAJOR = 1
4
- MINOR = 0
4
+ MINOR = 1
5
5
  PATCH = 0
6
6
 
7
7
  VER_STRING = [MAJOR, MINOR, PATCH].compact.join('.')
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.0.0
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: 2016-06-20 00:00:00.000000000 Z
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.1
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: