1

I'm trying to determine the age of AWS keys in days. I'm using Bash.

I get the creation date of the AWS key using this command:

 user_key1_date=$(aws iam list-access-keys --user-name "$aws_user_name" --profile "$aws_key" --output text --query 'AccessKeyMetadata[*].[AccessKeyId,CreateDate]' | awk 'NR==1 { print $2 }')

And I get a result like this:

2018-01-04T20:59:01Z

I am then trying to get the age of the keys in days and assign it to a variable with this line:

key1Age=$(date -d "$user_key1_date" +%j)

I then try to report the age of the key with this line:

The AWS access key: $user_access_key1 for user name: $aws_user_name was created on $date1. This key is $key1Age days old and needs to be replaced.

But the age of the key that gets reported is innacurate:

Key AKIAIPSNLEFKBLH2CLOQ is 004 days old. Time to change your key!

What am I doing wrong?

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
bluethundr
  • 1,005
  • 17
  • 68
  • 141

3 Answers3

2

%j gives you the number of days into a year on which a date takes place. January 4th of 2018 is thus 4, but so is January 4th of 1998; it's not useful when you need to do comparisons that can cross year boundaries.

Consider something more like:

now=$(date +%s) # slow but more reliable way
key1Date=2018-01-04T20:59:01Z
key1TimeSeconds=$(date -d "$key1Date" +%s)
key1AgeSeconds=$(( now - key1TimeSeconds ))
key1AgeDays=$(( key1AgeSeconds / (60 * 60 * 24) ))
echo "Key created on $key1Date. This key is $key1AgeDays days old and needs to be replaced."

...which, when run (as of today), emits:

Key created on 2018-01-04T20:59:01Z. This key is 188 days old and needs to be replaced.

If you're only using new versions of bash, printf -v now '%(%s)T' -1 is a more efficient alternative to now=$(date +%s).

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Thanks! Great solution. Works perfectly. This is my exact implementation: `timeago='90 days ago' key1dtSec=$(date -d "$user_key1_date" +'%s') key2dtSec=$(date -d "$user_key2_date" +'%s') taSec=$(date -d "$timeago" +'%s') now=$(date +%s) # slow but more reliable way key1AgeDays=$(( $key1dtSec / (60 * 60 * 24) )) key2AgeDays=$(( $key2dtSec / (60 * 60 * 24) ))` – bluethundr Jul 12 '18 at 15:08
2

The date command may not be giving the answer you want, but it is giving the correct answer to the question you asked. :) The %j gives Julian days, or the number of days from the beginning of the year. Jan 4 is the 4th day of the year.

There are probably several ways of doing what you want. I'll give you one way to get you in the right direction.

echo "($(date +%s) - $(date -d "2018-01-04T20:59:01Z" +%s)) / 3600 / 24"|bc

The %s converts a date into the the number of seconds from Jan 1, 1970. Here I took the number of seconds now and subtract the number of seconds from your key date. Dividing by 3600 gets me the number of hours and then by 24 gets me the number of days. bc converts the math expression to a value. I believe this will be truncated, but you might want to experiment with this.

UncleCarl
  • 331
  • 2
  • 15
  • Is there a particular reason to use `bc` here, vs, say, `echo $(( ( $(date +%s) - $(date -d "2018-01-04T20:59:01Z" +%s) ) / 3600 / 24 ))`? – Charles Duffy Jul 11 '18 at 22:16
  • 1
    Since the POSIX sh standard came out in the early 90s, `$(( ))` is the way to get into an arithmetic context (and expand to the expression's result). Bash has `(( ))` as an extension, so you can run `(( foo = bar + baz ))` or `if (( n > 3 ))`, but that's not portable to all POSIX-y shells. – Charles Duffy Jul 11 '18 at 22:23
  • `bc` is still needed if one wants POSIX-y floating point math, but it's not really called for any more with integers. (ksh93 has native floating-point, but it's a feature bash has chosen not to adopt). – Charles Duffy Jul 11 '18 at 22:25
  • (ksh93 also supports `(( ))` ) . ; -) – shellter Jul 11 '18 at 23:50
0

The %j format in my date's man page refers to day of year (001..366), so for Jan 4th, 004 would make sense.

You need to do some math to get the difference and there are plenty of answers out there for that, e.g How to find the difference in days between two dates?

zzevannn
  • 3,414
  • 2
  • 12
  • 20
  • Funny enough, I closed the OP's last iteration of this question (to which this one is effectively a follow-up/clarification) as a duplicate of precisely that question. That said, it's actually a quite good clarification (less unrelated content, more focus on the details of where and how they're trying to do date math and how it goes wrong). – Charles Duffy Jul 11 '18 at 22:08