Check Certificate Expiration Perl Script

1 Likes

The script will report if a certificate is expired, if it expires today, or if it will expire within a month.
This only reports the problem certificates in your eDir tree, and if they are all good, then nothing is returned.

 

I use Net::LDAP and Date::Manip in the perl script. The corresponding packages on SLES are:

 

    • perl
    • perl-DateManip
    • perl-ldap



The options needed for the script to run are:

checkcerts.pl LDAP-IP-or-DNS-name Bind-DN Bind-password


Example:

checkcerts.pl 10.20.30.40 cn=admin,o=novell novell


The user that is used for this script only needs to have the following rights:


Entry: Browse, Inherit (for the entire tree)

Attribute: ObjectClass & ndspkinotafter - Read, Compare, Inherit


The easiest way to use this script would be to create a cron job on one server that runs once a week.

An example for the script results to be emailed to idmadmins:

/usr/local/bin/checkcerts.pl 10.20.30.40 cn=admin,o=novell password | mail -s "Certificate Expiration Report for `date -I`" -r certreport@mydomain.com idmadmins@mydomain.com


You would need to create a job for each tree you want to monitor.


The following example would run against the 10.20.30.40 tree at 1:00AM every Saturday:

0 1 * * 6  /usr/local/bin/checkcerts.pl 10.20.30.40 cn=admin,o=novell password | nail -s "Certificate Expiration Report for `date -I`" -r certreport@mydomain.com idmadmins@mydomain.com

 

#!/usr/bin/perl -w
use Net::LDAP;
use POSIX qw(strftime);
use Date::Manip;

$argc = $#ARGV + 1;
if ($argc != 3) { die "checkcerts.pl LDAPURI binduser bindpwd"; }
$ldap = Net::LDAP->new( $ARGV[0]) or die "$@";
$mesg = $ldap->bind( $ARGV[1], password => $ARGV[2] );
$mesg = $ldap->search( base => "", filter => "(objectclass=ndspkikeymaterial)" );
$mesg->code && die $mesg->error;
$currenttime = strftime("%Y%m%d", localtime());
$currtime = &ParseDate($currenttime);
$currtimeplus = &DateCalc($currtime, "1 month");

my @entries = $mesg->entries;
 my $entr;
 foreach $entr ( @entries ) {
   my $attr="ndspkinotafter";
   $certdate = substr($entr-> get_value ( $attr ), 0, 8 );
   $crtdate = &ParseDate($certdate);
   $dateresult = &Date_Cmp($currtime,$crtdate);
   $futuredateresult = &Date_Cmp($currtimeplus,$crtdate);
   if ( $dateresult < 0 ) {
         if ( $futuredateresult < 0 ) {
#             print "The certificate ", $entr->dn, " is valid.\n";
          } else {
             print "The certificate ", $entr->dn, " will expire within a month.\n"
          }
   } elsif ($dateresult==0) {
         print "The certificate ", $entr->dn, " expires today.\n";
   } else {
         print "The certificate ", $entr->dn, " has already expired.\n";
   } 
 }
$mesg = $ldap->unbind;
 

Tags:

Labels:

Collateral
Support Tip
Comment List
  • ah ha,  I see how "Require TLS for all operations" didn't get turned on for a few key servers,  a good reason for the effort, now to start back tracking why it is off for some of those other systems.

    Not likely surprises either, I've cronned checkcerts.pl for some clients, each once a week on two different OES boxes at different ends of the network to email the results which has been a great headache saver.  that way of one box fails, I still get the other one and its warnings.

    very extendable, and worth exploring for any of us.  this is how I've grown my bash and perl scripting. doesn't make me a real dev, but helps in those day to day things.

    ________________________

    Andy of KonecnyConsulting.ca in Toronto
    Please use the "Like" and/or "Verified Answers" as appropriate as that helps us all.

  • The only additional functionality is that it supports SSL/TLS while the old (original) script does not.  Many companies do not allow clear text bind on ldap so SSL/TLS/StartTLS is required.

    I have used this script as a framework for other processes as well.  If you need to search for date values in LDAP/eDir, it is great to run a query then you can add conditions to report what you are looking for.  In one iteration I used it for reports for help desk manager to know how many password expirations were due in the next week, by day.

    Are there improvements that could be made - sure depending on your use case, but for me at least it helps me avoid unexpected certificate expiration issues (evening and weekend)

  • Hi Robert
    Thank you for updating this
      but what does this additional bit give us for the extra steps?   
    Running it on an OES 18.3 box I see no difference and the old one has been working perfectly (so far).  For now I'm not rolling this out any further than my test without any value for that additional effort and complexity of adding the ca-cert.crt (thought that script has its own value on its own)


    In my touching of many systems over the years I find various mystery scripts when troubleshooting systems others have worked on,  scripts like this with No Docs/comments!  
    So for my instances (and would be a good habit for all reading this) I added after the 1st line something like this.

    # to check|list for expiring certificates in the eDir tree,  usage in crontab
    #   0 7 * * 1 root /software/checkcerts.pl ldaps://192.168.1.10 cn=admin,ou=sa,o=system mypassword ca-cert.cer |mail -s "Certificate Expiration Report for `date -I`" adminuser@domain.com,otheradmin@domain.com
    # by Robert Ridly of NetIQ/MicroFocus, 1st posted 2009-05-12, 2019 update posted 2022-04-15 at
    community.microfocus.com/.../check-certificate-expiration-perl-script


    a one line add gets you to list all your certs so you see how far out the expires are.
     insert ~line25 before the if line
       print "Cert ", $entr->dn, " expires ", $certdate, "\n";

    ________________________

    Andy of KonecnyConsulting.ca in Toronto
    Please use the "Like" and/or "Verified Answers" as appropriate as that helps us all.

  • I am the original author.  Here is an updated version that added SSL/TLS support (I updated it in 2019):

    #!/usr/bin/perl -w
    use Net::LDAP;
    use POSIX qw(strftime);
    use Date::Manip;
    use IO::Socket::SSL;
    
    $argc = $#ARGV + 1;
    if ($argc != 4) { die "checkcerts.pl LDAPURI binduser bindpwd SSLCert"; }
    $ldap = Net::LDAP->new( $ARGV[0], verify => 'require', cafile => $ARGV[3], ) or die "$@";
    $mesg = $ldap->bind( $ARGV[1], password => $ARGV[2] );
    $mesg = $ldap->search( base => "", filter => "(objectclass=ndspkikeymaterial)" );
    $mesg->code && die $mesg->error;
    $currenttime = strftime("%Y%m%d", localtime());
    $currtime = &ParseDate($currenttime);
    $currtimeplus = &DateCalc($currtime, "1 month");
    
    my @entries = $mesg->entries;
     my $entr;
     foreach $entr ( @entries ) {
       my $attr="ndspkinotafter";
       $certdate = substr($entr-> get_value ( $attr ), 0, 8 );
       $crtdate = &ParseDate($certdate);
       $dateresult = &Date_Cmp($currtime,$crtdate);
       $futuredateresult = &Date_Cmp($currtimeplus,$crtdate);
       if ( $dateresult < 0 ) {
             if ( $futuredateresult < 0 ) {
    #             print "The certificate ", $entr->dn, " is valid.\n";
              } else {
                 print "The certificate ", $entr->dn, " will expire within a month.\n"
              }
       } elsif ($dateresult==0) {
             print "The certificate ", $entr->dn, " expires today.\n";
       } else {
             print "The certificate ", $entr->dn, " has already expired.\n";
       } 
     }
    $mesg = $ldap->unbind;
    
    

    The script now also requires perl module IO::Socket::SSL to function.  An example connection URL would be:

    ./checkcerts.pl ldaps://192.168.1.10 cn=admin,ou=sa,o=system mypassword ca-cert.cer

    The certificate needs to be the CA self signed public key/certificate.  Here is another script that uses bash/sed/awk/openssl to pull the certificate from ldap (eDirectory).

    #!/bin/sh
    while getopts h:p:f: flag
    do 
       case "${flag}" in
    	h) HOST_NAME=${OPTARG};;
    	p) PORT=${OPTARG};;
    	f) SERVER_ROOT_CERTIFICATE=${OPTARG};;
       esac
    done
    CERTS=$(echo -n | openssl s_client -connect $HOST_NAME:$PORT -showcerts | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p')
    echo "$CERTS" | awk -v RS="-----BEGIN CERTIFICATE-----" 'NR > 1 { printf RS $0 > "'$SERVER_ROOT_CERTIFICATE'"; close("'$SERVER_ROOT_CERTIFICATE'") }'
    openssl x509 -noout -in $SERVER_ROOT_CERTIFICATE -subject -dates

    The syntax for the "export-ca.sh" script is:

    sh export-ca.sh -h 192.168.1.10 -p 636 -f ca-cert.cer

  • The original attachment didn't survived the migration as did the name of the original author, but I happen to have the code and have been using it very successfully and added that code back in here 2021-07-05

    ________________________

    Andy of KonecnyConsulting.ca in Toronto
    Please use the "Like" and/or "Verified Answers" as appropriate as that helps us all.

  • The file downloads without any issues but when trying to extract it I get the following error:

    tar: This does not look like a tar archive
    tar: Skipping to next header
    tar: Exiting with failure status due to previous errors

    The file size is also 744 bytes instead of 721Bytes as stated above.
  • If it produced no output and did not provide an error then you don't have any expired (or soon to expire) certificates. The user used to login to the tree should also have enough rights to browse the tree and read the ndspkinotafter attribute on the certificate objects (the ndspkikeymaterial objectclass).
  • I ran the script and followed the example. And it produced no output. Am I doing something wrong?
Related
Recommended