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 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: