From a3599009c798e8aaffdbb408007d505a178b79cb Mon Sep 17 00:00:00 2001 From: Derrik Pates Date: Thu, 4 Jun 2020 10:06:21 -0600 Subject: [PATCH 1/5] [OPS-12590] Check expirations for the whole cert chain. --- bin/check-ssl-cert.rb | 58 +++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/bin/check-ssl-cert.rb b/bin/check-ssl-cert.rb index b1c3333..aadfc2d 100755 --- a/bin/check-ssl-cert.rb +++ b/bin/check-ssl-cert.rb @@ -77,8 +77,8 @@ class CheckSSLCert < Sensu::Plugin::Check::CLI short: '-S', long: '--pass ' - def ssl_cert_expiry - `openssl s_client -servername #{config[:servername]} -connect #{config[:host]}:#{config[:port]} < /dev/null 2>&1 | openssl x509 -enddate -noout`.split('=').last + def ssl_cert_expiry(certnum) + `openssl s_client -servername #{config[:servername]} -connect #{config[:host]}:#{config[:port]} < /dev/null 2>&1 | awk 'BEGIN { certnum = -1; in_cert = 0; } /^-----BEGIN CERTIFICATE-----$/ { certnum++; if (certnum == #{certnum}) { in_cert = 1 } } in_cert == 1 { print } /^-----END CERTIFICATE-----$/ { in_cert = 0 }' | openssl x509 -text -noout 2> /dev/null | sed -n -e 's/^[[:space:]]\\+Subject: .*CN[[:space:]]*=[[:space:]]*//p' -e 's/^[[:space:]]\\+Not After[[:space:]]*:[[:space:]]*//p'` end def ssl_pem_expiry @@ -107,24 +107,44 @@ def validate_opts def run validate_opts - expiry = if config[:pem] - ssl_pem_expiry - elsif config[:pkcs12] - ssl_pkcs12_expiry - else - ssl_cert_expiry - end - - days_until = (Date.parse(expiry.to_s) - Date.today).to_i - - if days_until < 0 - critical "Expired #{days_until.abs} days ago" - elsif days_until < config[:critical].to_i - critical "#{days_until} days left" - elsif days_until < config[:warning].to_i - warning "#{days_until} days left" + if not config[:pem] and not config[:pkcs12] + certnum = 0 + while true + expiry = ssl_cert_expiry(certnum) + + break if expiry == "" + expiry = expiry.split(/\n/) + + days_until = (Date.parse(expiry[1].to_s) - Date.today).to_i + + if days_until < 0 + critical "Cert '#{expiry[0]}' expired #{days_until.abs} days ago" + elsif days_until < config[:critical].to_i + critical "Cert '#{expiry[0]}' expires in #{days_until} days" + elsif days_until < config[:warning].to_i + warning "Cert '#{expiry[0]}' expires in #{days_until} days" + end + i += 1 + end + ok "No certs in chain expiring soon" else - ok "#{days_until} days left" + expiry = if config[:pem] + ssl_pem_expiry + elsif config[:pkcs12] + ssl_pkcs12_expiry + end + + days_until = (Date.parse(expiry.to_s) - Date.today).to_i + + if days_until < 0 + critical "Expired #{days_until.abs} days ago" + elsif days_until < config[:critical].to_i + critical "#{days_until} days left" + elsif days_until < config[:warning].to_i + warning "#{days_until} days left" + else + ok "#{days_until} days left" + end end end end From 35cf76ec019f979e1e1c1c1549751f641a17882a Mon Sep 17 00:00:00 2001 From: Derrik Pates Date: Thu, 4 Jun 2020 10:25:07 -0600 Subject: [PATCH 2/5] [OPS-12591] Increment the actual variable. --- bin/check-ssl-cert.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/check-ssl-cert.rb b/bin/check-ssl-cert.rb index aadfc2d..c66adcc 100755 --- a/bin/check-ssl-cert.rb +++ b/bin/check-ssl-cert.rb @@ -124,7 +124,7 @@ def run elsif days_until < config[:warning].to_i warning "Cert '#{expiry[0]}' expires in #{days_until} days" end - i += 1 + certnum += 1 end ok "No certs in chain expiring soon" else From bacb2ca2e9ad55feed5c2723cd09c0d07c4e1547 Mon Sep 17 00:00:00 2001 From: Derrik Pates Date: Thu, 4 Jun 2020 10:33:54 -0600 Subject: [PATCH 3/5] [OPS-12591] Oops, gotta add -showcerts for the whole chain. --- bin/check-ssl-cert.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/check-ssl-cert.rb b/bin/check-ssl-cert.rb index c66adcc..852e08a 100755 --- a/bin/check-ssl-cert.rb +++ b/bin/check-ssl-cert.rb @@ -78,7 +78,7 @@ class CheckSSLCert < Sensu::Plugin::Check::CLI long: '--pass ' def ssl_cert_expiry(certnum) - `openssl s_client -servername #{config[:servername]} -connect #{config[:host]}:#{config[:port]} < /dev/null 2>&1 | awk 'BEGIN { certnum = -1; in_cert = 0; } /^-----BEGIN CERTIFICATE-----$/ { certnum++; if (certnum == #{certnum}) { in_cert = 1 } } in_cert == 1 { print } /^-----END CERTIFICATE-----$/ { in_cert = 0 }' | openssl x509 -text -noout 2> /dev/null | sed -n -e 's/^[[:space:]]\\+Subject: .*CN[[:space:]]*=[[:space:]]*//p' -e 's/^[[:space:]]\\+Not After[[:space:]]*:[[:space:]]*//p'` + `openssl s_client -servername #{config[:servername]} -connect #{config[:host]}:#{config[:port]} -showcerts < /dev/null 2>&1 | awk 'BEGIN { certnum = -1; in_cert = 0; } /^-----BEGIN CERTIFICATE-----$/ { certnum++; if (certnum == #{certnum}) { in_cert = 1 } } in_cert == 1 { print } /^-----END CERTIFICATE-----$/ { in_cert = 0 }' | openssl x509 -text -noout 2> /dev/null | sed -n -e 's/^[[:space:]]\\+Subject: .*CN[[:space:]]*=[[:space:]]*//p' -e 's/^[[:space:]]\\+Not After[[:space:]]*:[[:space:]]*//p'` end def ssl_pem_expiry From e7e1c2ff82f5a3d6cfa75c61d1d16c52afa84d8e Mon Sep 17 00:00:00 2001 From: Derrik Pates Date: Thu, 4 Jun 2020 11:47:08 -0600 Subject: [PATCH 4/5] [OPS-12591] Clean up rubocop warnings and fix indexes. --- bin/check-ssl-cert.rb | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/bin/check-ssl-cert.rb b/bin/check-ssl-cert.rb index 852e08a..b0b07a8 100755 --- a/bin/check-ssl-cert.rb +++ b/bin/check-ssl-cert.rb @@ -78,7 +78,12 @@ class CheckSSLCert < Sensu::Plugin::Check::CLI long: '--pass ' def ssl_cert_expiry(certnum) - `openssl s_client -servername #{config[:servername]} -connect #{config[:host]}:#{config[:port]} -showcerts < /dev/null 2>&1 | awk 'BEGIN { certnum = -1; in_cert = 0; } /^-----BEGIN CERTIFICATE-----$/ { certnum++; if (certnum == #{certnum}) { in_cert = 1 } } in_cert == 1 { print } /^-----END CERTIFICATE-----$/ { in_cert = 0 }' | openssl x509 -text -noout 2> /dev/null | sed -n -e 's/^[[:space:]]\\+Subject: .*CN[[:space:]]*=[[:space:]]*//p' -e 's/^[[:space:]]\\+Not After[[:space:]]*:[[:space:]]*//p'` + `openssl s_client -servername #{config[:servername]} -connect #{config[:host]}:#{config[:port]} -showcerts < /dev/null 2> /dev/null | \ + awk 'BEGIN { certnum = -1; in_cert = 0; } + /^-----BEGIN CERTIFICATE-----$/ { certnum++; if (certnum == #{certnum}) { in_cert = 1 } } + in_cert == 1 { print } + /^-----END CERTIFICATE-----$/ { in_cert = 0 }' | openssl x509 -text -noout 2> /dev/null | \ + sed -n -e 's/^[[:space:]]\\+Subject: .*CN[[:space:]]*=[[:space:]]*//p' -e 's/^[[:space:]]\\+Not After[[:space:]]*:[[:space:]]*//p'` end def ssl_pem_expiry @@ -107,26 +112,26 @@ def validate_opts def run validate_opts - if not config[:pem] and not config[:pkcs12] + if !config[:pem] && !config[:pkcs12] certnum = 0 - while true + loop do expiry = ssl_cert_expiry(certnum) - break if expiry == "" + break if expiry == '' expiry = expiry.split(/\n/) - days_until = (Date.parse(expiry[1].to_s) - Date.today).to_i + days_until = (Date.parse(expiry[0].to_s) - Date.today).to_i if days_until < 0 - critical "Cert '#{expiry[0]}' expired #{days_until.abs} days ago" + critical "Cert '#{expiry[1]}' expired #{days_until.abs} days ago" elsif days_until < config[:critical].to_i - critical "Cert '#{expiry[0]}' expires in #{days_until} days" + critical "Cert '#{expiry[1]}' expires in #{days_until} days" elsif days_until < config[:warning].to_i - warning "Cert '#{expiry[0]}' expires in #{days_until} days" + warning "Cert '#{expiry[1]}' expires in #{days_until} days" end certnum += 1 end - ok "No certs in chain expiring soon" + ok 'No certs in chain expiring soon' else expiry = if config[:pem] ssl_pem_expiry From 82334a72cd7a40666308aee67fbd8e28e19a9e6c Mon Sep 17 00:00:00 2001 From: Derrik Pates Date: Thu, 4 Jun 2020 12:40:39 -0600 Subject: [PATCH 5/5] Update Changelog with what I did. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1d43a6..b99faeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ This CHANGELOG follows the format listed [here](https://github.com/sensu-plugins ### Added - 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 - Require latest sensu-plugin for [Sensu Go support](https://github.com/sensu-plugins/sensu-plugin#sensu-go-enablement) +- `check-ssl-cert.rb`: Check expiration times for all certs in the chain, not just the leaf cert. Comodo/Sectigo intermediate certs expired recently, causing widespread panic, and so validation of all certs in the chain has become a concern. ## [2.0.1] - 2018-05-30 ### Fixed