Bash check if file was modified within date range

Question:

I have a script that checks to see if a cert, (.cer file), is within 14 days of expiring, and if it is, it will archive the old cert request, generate a new one, and send it to the middleware team. The thought occurs though, that if this script runs on a cron at midnight every night, what’s to prevent it from sending another cert request to the middleware team on each subsequent night within the date range (within 14 days of cert expiring)?

I’d like to check the time stamp on the .csr file, and it it’s been replaced or modified within 14 days of the cert, (.cer file), expiring, then do nothing, else archive csr, gencsr, mailcsr. Here’s the main routine of the script:

if python -c "
import datetime
import sys
current_time = datetime.datetime.now()
key_time = datetime.datetime.strptime(sys.argv[1], '%b %d %Y')
difference = key_time - current_time
sys.exit(0 if difference.days < 14 else 1)
" "$( keytool -printcert -file "$1" | sed '4q;d' | awk '{print $11,$12,$15}' )";then archive;gencert;mail;else echo "Cert is still current";fi

I’m currently on Oracle Linux Server release 7.9

It would seem that the next course of action is to save the output of the .cer file check to a variable in epoch time, save the output of a timestamp check on a file in epoch time to a variable or a flag file, and then compare the two. If timestamp on .csr is -gt (14 days of .cer expiring), then do nothing; else archive; gencsr; mailcsr; fi.

And the implementation is something like:

domain=`echo "$1" | sed 's/.cer//'`
csr_time_stamp=$(<epoch time of modified date>)
cer_exp_date=$(<epoch time of .cer exp. date>)
if [ $csr_time_stamp > $cer_time_stamp ] && [ -f flagfiles/$domain.csr ];then echo $csr_time_stamp >> flagfiles/$domain.csr;else archivecsr; gencsr; mailcsr;fi

But I still didn’t check the flag file for the date stamp, is that an unnecessary step if you put both dates in a variable each time?

The output of the keytool command:

keytool -printcert -file fqdn.domainname.com.cer | sed '4q;d' | awk '{print $11,$12,$15}'
Jan 24 2018

The output of the timestamp on the .csr file:

stat fqdn.domainname.com.csr | grep Modify | awk '{print $2}'
2023-03-13

With the excellent help from @markp-fuso, here is the code I used:

domain=`echo "$1" | sed 's/.cer//'`
OUTPUT_DIR=<obfuscated>
archive=<obfuscated>

# convert keytool/expire date to epoch; could probably streamline this a bit

keytool_dt=$(keytool -printcert -file "$1" | sed '4q;d' | awk '{print $11,$12,$15}') # eg: 'Jan 24 2018'
exp_dt=$(date -d "${keytool_dt}" "+%s")      # convert to epoch seconds

# calculate number of secs in 14 day range

dt_range=$((14 * 60 * 60 * 24))              # 1209600

# current epoch - one of the following:

now_dt=$(date "+%s")                         # spawns a subprocess

#printf -v now_dt '%(%s)T'                   # does not spawn a subprocess; requires bash 3.1+

# last modification date of csr file, in epoch seconds

mod_dt=$(stat -c "%Y" "$domain".csr)

echo "domain.csr: $domain.csr"

echo "now_dt: $now_dt exp_dt: $exp_dt dt_range: $dt_range exp_dt: $exp_dt mod_dt: $mod_dt"

if (( $now_dt > ($exp_dt + $dt_range) ))     # cert has, or will soon, expire
then
   if (( ($now_dt - $mod_dt) > $dt_range ))  # csr last mod date was more than 14 days ago
   then
       echo "cert expired: generate new csr"
   else
       echo "cert expired: new csr pending"
   fi
else
   echo "cert is valid"
fi

Now it works, I had to change now_dt back to what you used in your code and mod_dt wasn’t declared, I was tired at that point:

now_dt: 1678893896
domain.csr: <obfuscated>.csr
now_dt: 1678893896 exp_dt: 1516780800 dt_range: 1209600 exp_dt: 1516780800 mod_dt: 1678767236
cert expired: new csr pending
Asked By: puppet_master

||

Answers:

General approach:

  • obtain various datetime stamps in epoch format, placing in separate variables
  • perform conditionals/tests against these epoch variables
  • OP has access to GNU core utils (for date -d and stat -c support)

One approach:

# convert keytool/expire date to epoch; could probably steamline this a bit
# but would need complete keytool output; for now we'll work with what OP 
# has provided in the question:

keytool_dt=$(keytool | sed | awk)            # eg: 'Jan 24 2018'
exp_dt=$(date -d "${keytool_dt}" "+%s")      # convert to epoch seconds

# calculate number of secs in 14 day range

dt_range=$((14 * 60 * 60 * 24))              # 1209600

# current epoch - one of the following:

now_dt=$(date "+%s")                         # spawns a subprocess
printf -v now_dt '%(%s)T'                    # does not spawn a subprocess; requires bash 3.1+

# last modification date of csr file, in epoch seconds

mod_dt=$(stat -c "%Y" file.csr)

Now the comparisons:

if (( now_dt > (exp_dt - dt_range) ))        # cert has, or will soon, expire
then
   if (( (now_dt - mod_dt) > dt_range ))     # csr last mod date was more than 14 days ago
   then
       echo "cert expired: generate new csr"
   else
       echo "cert expired: new csr pending"
   fi
else
   echo "cert is valid"
fi

NOTE:

  • I haven’t done an exhaustive set of validations on the conditionals
  • not sure that I’ve covered all of OP’s scenarios
  • with the various (epoch) numbers in hand it shouldn’t be to hard for OP to (re)write the conditionals as needed
Answered By: markp-fuso
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.