Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I can find out the expiry date of ssl certificates using this OpenSSL command:

openssl x509 -noout -in <filename> -enddate

But if the certificates are scattered on different web servers, how do you find the expiry dates of all these certificates on all the servers?

There seems to be a way to connect to other host, but I'm not sure how to get the expiry date using this:

openssl s_client -connect host:port
share|improve this question
up vote 9 down vote accepted

I had the same issue and wrote this... It's quick and dirty, but should work. It'll log (and print to screen with debugging on) any certs which aren't yet valid or expire in the next 90 days. Might contain some bugs, but feel free to tidy it up.


warning_days=90 # Number of days to warn about soon-to-expire certs

for CERT in $certs_to_check
  $DEBUG && echo "Checking cert: [$CERT]"

  output=$(echo | openssl s_client -connect ${CERT} 2>/dev/null |\
  openssl x509 -noout -subject -dates 2>/dev/null) 

  if [ "$?" -ne 0 ]; then
    $DEBUG && echo "Error connecting to host for cert [$CERT]"
    logger -p local6.warn "Error connecting to host for cert [$CERT]"

  start_date=$(echo $output | sed 's/.*notBefore=\(.*\).*not.*/\1/g')
  end_date=$(echo $output | sed 's/.*notAfter=\(.*\)$/\1/g')

  start_epoch=$(date +%s -d "$start_date")
  end_epoch=$(date +%s -d "$end_date")

  epoch_now=$(date +%s)

  if [ "$start_epoch" -gt "$epoch_now" ]; then
    $DEBUG && echo "Certificate for [$CERT] is not yet valid"
    logger -p local6.warn "Certificate for $CERT is not yet valid"

  seconds_to_expire=$(($end_epoch - $epoch_now))
  days_to_expire=$(($seconds_to_expire / 86400))

  $DEBUG && echo "Days to expiry: ($days_to_expire)"

  warning_seconds=$((86400 * $warning_days))

  if [ "$seconds_to_expire" -lt "$warning_seconds" ]; then
    $DEBUG && echo "Cert [$CERT] is soon to expire ($seconds_to_expire seconds)"
    logger -p local6.warn "cert [$CERT] is soon to expire ($seconds_to_expire seconds)"
share|improve this answer
I modified/expanded your script a bit to also be able to check mail server certificates as well as to give a nice littlöe overview about the status of all certificates. You can find the modified script at: – Lars Kiesow Mar 30 at 12:16

Below is my script that as a check within nagios. It connects to a specific host, it verifies that the certificate is valid within a threshold set by the -c/-w options. It can check that the CN of the certificate matches the name you expect.

You need the python openssl library, and I did all the testing with python 2.7.

It would be trivial to have a shell script call this multiple times. The script returns the standard nagios exit values for critical/warning/ok status.

A simple check of Google's certificate can be performed like this.

./check_ssl_certificate -H -p 443 -n

Expire OK[108d] - CN OK -



Usage: check_ssl_certificate -H <host> -p <port> [-m <method>] 
                      [-c <days>] [-w <days>]
  -h show the help
  -H <HOST>    host/ip to check
  -p <port>    port number
  -m <method>  (SSLv2|SSLv3|SSLv23|TLSv1) defaults to SSLv23
  -c <days>    day threshold for critical
  -w <days>    day threshold for warning
  -n name      Check CN value is valid

import getopt,sys
import __main__
from OpenSSL import SSL
import socket
import datetime

# On debian Based systems requires python-openssl

def get_options():
  "get options"


    opts, args = getopt.getopt(sys.argv[1:], "hH:p:m:c:w:n:", ['help', "host", 'port', 'method'])
  except getopt.GetoptError as err:
    # print help information and exit:
    print str(err) # will print something like "option -a not recognized"
  for o, a in opts:
    if o in ("-h", "--help"):
      print __main__.__doc__
    elif o in ("-H", "--host"):
      options['host'] = a
    elif o in ("-p", "--port"):
      options['port'] = a
    elif o in ("-m", "--method"):
      options['method'] = a
    elif o == '-c':
      options['critical'] = int(a)
    elif o == '-w':
      options['warning'] = int(a)
    elif o == '-n':
      options['cn'] = a
      assert False, "unhandled option"

  if (''==options['host'] or 
    print __main__.__doc__

  if options['critical'] >= options['warning']:
    print "Critical must be smaller then warning"
    print __main__.__doc__

  return options

def main():
  options = get_options()

  # Initialize context
  if options['method']=='SSLv3':
    ctx = SSL.Context(SSL.SSLv3_METHOD)
  elif options['method']=='SSLv2':
    ctx = SSL.Context(SSL.SSLv2_METHOD)
  elif options['method']=='SSLv23':
    ctx = SSL.Context(SSL.SSLv23_METHOD)
    ctx = SSL.Context(SSL.TLSv1_METHOD)

  # Set up client
  sock = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
  sock.connect((options['host'], int(options['port'])))
  # Send an EOF
  except SSL.Error,e:
    print e


  cur_date = datetime.datetime.utcnow()
  cert_nbefore = datetime.datetime.strptime(peer_cert.get_notBefore(),'%Y%m%d%H%M%SZ')
  cert_nafter = datetime.datetime.strptime(peer_cert.get_notAfter(),'%Y%m%d%H%M%SZ')

  expire_days = int((cert_nafter - cur_date).days)

  if cert_nbefore > cur_date:
    if exit_status < 2: 
      exit_status = 2
    exit_message.append('C: cert is not valid')
  elif expire_days < 0:
    if exit_status < 2: 
      exit_status = 2
    exit_message.append('Expire critical (expired)')
  elif options['critical'] > expire_days:
    if exit_status < 2: 
      exit_status = 2
    exit_message.append('Expire critical')
  elif options['warning'] > expire_days:
    if exit_status < 1: 
      exit_status = 1
    exit_message.append('Expire warning')
    exit_message.append('Expire OK')


  for part in peer_cert.get_subject().get_components():
    if part[0]=='CN':

  if options['cn']!='' and options['cn'].lower()!=cert_cn.lower():
    if exit_status < 2:
      exit_status = 2
    exit_message.append(' - CN mismatch')
    exit_message.append(' - CN OK')

  exit_message.append(' - cn:'+cert_cn)

  print ''.join(exit_message)

if __name__ == "__main__":
share|improve this answer


Connect to host:port, extract the certificate with sed and write it to /tmp/host.port.pem.


Read the given pem file and evaluate the notAfter key as a bash variable. Then print the file name and the date when it expires in a given locale.


Iterate some input file and run the above functions.

get_pem () {
    openssl s_client -connect $1:$2 < /dev/null |& \
    sed -n '/BEGIN CERTIFICATE/,/END CERTIFICATE/w'/tmp/$1.$2.pem
get_expiration_date () {
    local pemfile=$1 notAfter
    if [ -s $pemfile ]; then
        eval `
          openssl x509 -noout -enddate -in /tmp/$pemfile |
          sed -E 's/=(.*)/="\1"/'
        printf "%40s: " $pemfile
        LC_ALL=ru_RU.utf-8 date -d "$notAfter" +%c
        printf "%40s: %s\n" $pemfile '???'

get_pem_expiration_dates () {
    local pemfile server port
    while read host; do
        pemfile=${host/ /.}.pem
        server=${host% *}
        port=${host#* }
        if [ ! -f /tmp/$pemfile ]; then get_pem $server $port; fi
        if [   -f /tmp/$pemfile ]; then get_expiration_date $pemfile; fi
    done < ${1:-input.txt}

if [ -f "$1" ]; then
    get_pem_expiration_dates "$1" ; fi

sample output

 $ sh input.txt
    Пн. 30 дек. 2013 01:00:00
     Чт. 13 марта 2014 13:00:00
      Сб. 24 мая 2014 00:49:50
 $ cat input.txt 443 443 443 443

And to answer your question:

$ openssl s_client -connect </dev/null |& \
openssl x509 -noout -enddate |& \
grep ^notAfter
share|improve this answer

Just run the command below and it will provide the expiration date:

openssl s_client -connect | openssl x509 -noout -enddate

You can use this command into a batch file, to gather this information for more remote servers.

share|improve this answer

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .