Extension Attribute using Date / Smart group issue

bbot
Contributor

I'm using an EA to generate the date of a certificate expiration.

Sample output for the EA result is 2019-06-08 (I've also tried including time -- 2019-08-17 16:32:39 )

I'm using a smart group with the operator "less than x days ago" and setting the value to 60.

I want the smart group to only return with certificates that are expiring in 60 days or less. What am I doing wrong?

16 REPLIES 16

Look
Valued Contributor III

I use a number of EA's that use the longer (time included) format and they seem to functiojn correctly.
For example, this one shows me when files on a Windows partition were last altered.
You presumably have date format selected for the EA and are only returning a single date/time?

#!/bin/bash
Win_Volume=$(mount | awk '/dev/disk/ && /ntfs/ {print $3}' | head -n 1)

if [ "$Win_Volume" ] && [ -d "$Win_Volume/Windows" ]; then
    Access_Date=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M:%S" "$Win_Volume/Windows/"* | sort | tail -n 1)
fi

echo "<result>$Access_Date</result>"

mschroder
Valued Contributor

It is difficult to say what might be wrong, since you don't say why you are not happy with the result. But a standard problem with Smart Group criteria and EAs is that the software does not handle NULL entries in date fields properly, and there is no way to add any criteria to filter out the NULL entries. This can make it very difficult to define smart groups based on date values in EAs.

Oh, and I don't think that 'less than 60 days ago' is the same as 'in less than 60 days'.

bbot
Contributor

@Look I'm using an EA with "data type - Date (YYYY-MM-DD hh:mm:ss). Gathering of the data is working as expected, I just can't seem to get the smart group to do what I want it to do, which is filter a list of machines that having certificates expiring within 60 days.

@mschroder Here's an example. I have two devices with the EA value of 2019-08-18 15:49:13 and 2019-08-11 12:50:53
I want my smart group to only show machines with certificates expiring in 60 days or less.
Using the operator "less than x days ago - value 60", these machines are showing up in my smart group. How can I structure my EA to do this?
(these certificates all expire at different times)

sdagley
Esteemed Contributor II

@bbot You're looking for an operator of "within x days", not "less than x days ago". That doesn't exist in the current JSS, and I'm not sure if it's a planned Jamf 10 feature or not. You could re-write your EA to return the number of days until the cert expires and simply do a numeric comparison for the smart group criteria to filter it.

bbot
Contributor

@sdagley Good suggestion. Anyone have an EA available? If not, i'll spend this afternoon writing something up.

This is what I'm currently using.

#!/bin/sh

compname=`dsconfigad -show | grep "Computer Account" | awk '{print $4}' | sed 's/.$//'`
Cert="$compname.domain.name"
certexpdate=$(/usr/bin/security find-certificate -a -c "$Cert" -p -Z "/Library/Keychains/System.keychain" | /usr/bin/openssl x509 -noout -enddate| cut -f2 -d=)

dateformat=$(/bin/date -j -f "%b %d %T %Y %Z" "$certexpdate" "+%Y-%m-%d %H:%M:%S")

echo "<result>$dateformat</result>"

tlarkin
Honored Contributor

I think you might be best off converting the output to an actual number representing days to a flat file, then have an EA pick it up every recon and update it. Then you can use the less than operator in the JSS to create your groups. Parsing by date stamp I don't think will work. So, what I have done in the past is get a date value in epoch time, then delta that time stamp to the current epoch time on the system, then divide by 86,400 to get the number of days something has. From there I can escrow the day amount in an EA and use the greater than and less than operators to take action or for reporting.

sdagley
Esteemed Contributor II

@bbot Here's your EA modified to return the number of days until your cert expires:

#!/bin/sh

compname=`dsconfigad -show | grep "Computer Account" | awk '{print $4}' | sed 's/.$//'`
Cert="$compname.domain.name"
certexpdate=$(/usr/bin/security find-certificate -a -c "$Cert" -p -Z "/Library/Keychains/System.keychain" | /usr/bin/openssl x509 -noout -enddate| cut -f2 -d=)

dateexpires=$(/bin/date -jf "%b %d %T %Y %Z" "$certexpdate" "+%s")

datetoday=$(/bin/date "+%s")

datedelta=$(((dateexpires - datetoday)/86400))
echo "<result>$datedelta </result>"

Edit - Revised script to skip using human readable dates as suggested by @tlarkin

tlarkin
Honored Contributor

@sdagley

That is what I would do as well, then you have a days value that will count down every recon and can use it to scope accordingly. I just didn't have time to write it out. Epoch date stamps are really good for this and are much easier to parse than something like a human readable date format. Also the version of date that ships with macOS is the BSD one which is way different that the GNU one. I always have to read the man page for that, but I have been using more Python these days than bash.

Good work on getting that going, and this is what I recommend if you need to track something by days. Get the date value to an Epoch date stamp, subtract the current epoch date stamp, then divide by 86,400 and that will get you the number of days for the time between. That way you don't have to deal with date stamps if you want to actually track days left, or days since reboot, or days since x happened, etc.

Edit - sorry tagged the wrong person I was replying to

sdagley
Esteemed Contributor II

@tlarkin The BSD versus GNU date differences can make for interesting times (pun intended) when "borrowing" script snippets from Linux. And yes, Epoch time for dates would have been cleaner than the human readable dates in the Q&D script I originally posted, so edit coming up.

tlarkin
Honored Contributor

@sdagley

Oh datetime is a problem in Python 2 vs Python 3 as well. So I just assume working with dates, times, and datestamps in general it just isn't going to be fun at all. Just like parsing XML is never fun. I also manage our Linux servers so porting bash code isn't always that straight forward with BSD tool-chain Vs. GNU tool-chain.

Also guess what, we are actually using math to do this, looks like our middle school math teachers were right! We will use math in our jobs.

sdagley
Esteemed Contributor II

@tlarkin I can't seem to escape from having to deal with time & date code. In a previous career incarnation I was responsible for handling problems in that area on the Mac version of Netscape Communicator. Some of the fun ones were adding support for time zones that weren't on one hour boundaries, and making Netscape's internal date function re-sync with the system clock after a wake from sleep rather than assuming no time had passed while the Mac was asleep.

tlarkin
Honored Contributor

@sdagley That is why I typically just use epoch date stamps but that gets tricky too, if talking to a different system. If you are going all local though on a Mac it makes it a lot easier than trying to parse date stamps. Then you just track days for what you whatever you are tracking.

sdagley
Esteemed Contributor II

@bbot Did that modified EA work for you?

bbot
Contributor

@sdagley @tlarkin

worked perfect!! Thanks!

Where does the 86400 come from?

Edit:; I googled date epoch and think I found what I'm looking for.

dgreening
Valued Contributor II

One note on putting in Ext Attrs in date format: make sure that you are ONLY returning date format, and nothing such as "NA" or "Not Installed", as you will put serious hurt on the DB connections should you try to do date math on an Ext Attr which has data not in date format. Ask me how I know...

tlarkin
Honored Contributor

@bbot

86,400 is how many seconds are in a day, 24 hours.