sensu-plugins/sensu-plugins-ssl

View on GitHub
bin/check-ssl-cert.rb

Summary

Maintainability
A
2 hrs
Test Coverage
#! /usr/bin/env ruby
# frozen_string_literal: false

#
#   check-ssl-cert
#
# DESCRIPTION:
#   Check when a SSL certificate will expire.
#
# OUTPUT:
#   plain text
#
# PLATFORMS:
#   Linux
#
# DEPENDENCIES:
#   gem: sensu-plugin
#
# USAGE:
#   example commands
#
# NOTES:
#   Does it behave differently on specific platforms, specific use cases, etc
#
# LICENSE:
#   Jean-Francois Theroux <me@failshell.io>
#   Nathan Williams <nath.e.will@gmail.com>
#   Released under the same terms as Sensu (the MIT license); see LICENSE
#   for details.
#

require 'date'
require 'openssl'
require 'sensu-plugin/check/cli'

#
# Check SSL Cert
#
class CheckSSLCert < Sensu::Plugin::Check::CLI
  option :critical,
         description: 'Numbers of days left',
         short: '-c',
         long: '--critical DAYS',
         required: true

  option :warning,
         description: 'Numbers of days left',
         short: '-w',
         long: '--warning DAYS',
         required: true

  option :pem,
         description: 'Path to PEM file',
         short: '-P',
         long: '--pem PEM'

  option :host,
         description: 'Host to validate',
         short: '-h',
         long: '--host HOST'

  option :port,
         description: 'Port to validate',
         short: '-p',
         long: '--port PORT'

  option :servername,
         description: 'Set the TLS SNI (Server Name Indication) extension',
         short: '-s',
         long: '--servername SERVER'

  option :pkcs12,
         description: 'Path to PKCS#12 certificate',
         short: '-C',
         long: '--cert P12'

  option :pass,
         description: 'Pass phrase for the private key in PKCS#12 certificate',
         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
  end

  def ssl_pem_expiry
    OpenSSL::X509::Certificate.new(File.read config[:pem]).not_after # rubocop:disable Style/NestedParenthesizedCalls
  end

  def ssl_pkcs12_expiry
    `openssl pkcs12 -in #{config[:pkcs12]} -nokeys -nomacver -passin pass:"#{config[:pass]}" | openssl x509 -noout -enddate | grep -v MAC`.split('=').last
  end

  def validate_opts
    if !config[:pem] && !config[:pkcs12]
      unknown 'Host and port required' unless config[:host] && config[:port]
    elsif config[:pem]
      unknown 'No such cert' unless File.exist? config[:pem]
    elsif config[:pkcs12]
      if !config[:pass]
        unknown 'No pass phrase specified for PKCS#12 certificate'
      else
        unknown 'No such cert' unless File.exist? config[:pkcs12]
      end
    end
    config[:servername] = config[:host] unless config[:servername]
  end

  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 # rubocop:disable Style/NumericPredicate
      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