Historical policy logs

AVmcclint
Honored Contributor

Is there a way to see a single log of all the Policies that have been installed? In chronological order? With logged in user and computer name? I'd like to see something that tells me something like this:

date              time        user       computer           policy
4/1/2016     8:00am           jsmith    LabMac01         TextWrangler 4.1      Completed
4/1/2016     7:58am           cjones    OfficeMac03      Office 2016 15.19.1   Failed
4/1/2016     6:33am           bbunny  LabMac02         Clear user caches     Completed
3/31/2016   5:22pm           jkirk       BridgeMac1       XQuartz 2.7.8    Completed
3/31/2016   5:00pm           admin    CallCenter6       iWork          Failed

Primarily so I can get a feel for the day's activity in one glance. The closest I can figure out is to click on each Policy one at a time to see who installed it and when OR click on each computer and see what they installed and when. Surely this already exists, right? Or maybe a Feature Request is in order?

2 REPLIES 2

mm2270
Legendary Contributor III

No, there isn't an easy way right now. Sadly, there was once a way to do this, back in the Casper Suite 8.x series, there was a global Logs section that would allow you to get a more birds eye view of all policies that are running across your fleet, and other things too were in that Logs section. Unfortunately, the global Logs section was a casualty of the move to Casper Suite 9, and many have asked for it to be brought back. A few items have returned in a fashion, but there is still no centralized policy logs section (See the relevant FR here) So JAMF has yet to deliver on that.
Maybe later this year though?

jholland
New Contributor III

I get most of the way there, minus the completion status. I deployed a script via a policy to all machines that creates a script that runs locally (logpush.sh) from a launchdaemon every 10min. The script takes the contents of /var/log/jamf.log, parses relevant logs out, sends it to a central syslog server in the office using the logger command, and then relays the data to SumoLogic in the cloud. The script only does this if the host is in the office (which has specific RFC1918 addresses), so the logs don't get purged when outside the office. They just queue up and syslog once the laptop is back in the office.

If you don't have a SIEM, you can at least get the consolidated events on the syslog server and then import them into a DB of your choice so you can sort it as desired. Script and screenshot of my laptop's policy logs in a SumoLogic dashboard below. a38583c8c2e0416f86fafea3114c50af

#!/bin/sh
#####################################################
# Name: Client Syslog'ing Config
# Purpose: Configure syslog config on laptops that 
#          reside in the Corporate office
# Tested on: 10.10 and 10.11
#####################################################

# get logged-in user and assign it to a variable
LOGGEDINUSER=$( ls -l /dev/console | awk '{print $3}' )

# get user home directory
HOMEDIR=$(dscl . -read /Users/$LOGGEDINUSER NFSHomeDirectory | cut -d' ' -f2)

#create $HOMEDIR/LaunchAgents if it does not exist
if [ ! -d $HOMEDIR/Library/LaunchAgents ]; then
    mkdir $HOMEDIR/Library/LaunchAgents
    chown $LOGGEDINUSER:staff $HOMEDIR/Library/LaunchAgents
    chmod 700 $HOMEDIR/Library/LaunchAgents
fi

#create $HOMEDIR/Library/Scripts if it does not exist
if [ ! -d $HOMEDIR/Library/Scripts ]; then
    mkdir $HOMEDIR/Library/Scripts
    chown $LOGGEDINUSER:staff $HOMEDIR/Library/Scripts
    chmod 700 $HOMEDIR/Library/Scripts
fi

##### echo com.acme.cron_log.plist to Library/LaunchDaemons
echo "<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.acme.cron_log</string>

  <key>ProgramArguments</key>
  <array>
    <string>$HOMEDIR/Library/Scripts/logpush.sh</string>
  </array>

  <key>Nice</key>
  <integer>1</integer>

  <key>StartInterval</key>
  <integer>600</integer>

  <key>RunAtLoad</key>
  <true/>

</dict>
</plist>" > /Library/LaunchDaemons/com.acme.cron_log.plist
#####

echo '#!/bin/bash
#####################################################
# Name: logpush.sh
# Purpose: Push logs from client when they are on
#          the office network to syslog server
#####################################################

## Get IP
IP=`/sbin/ifconfig | /usr/bin/grep "inet " | /usr/bin/egrep "10.13.10.|10.13.20." | /usr/bin/awk @{print $2}@ | head -1`

## Get Hostname
HN=`scutil --get LocalHostName`

## Check to see if office
if [[ "$IP" =~ 10.13.10 || "$IP" =~ 10.13.20  ]]; then
  while read line
  do
    ## Get rid of noisy non security relevant logs
    if [[ "$line" =~ ^.*recurring check-in.* || "$line" =~ ^.*Executing Policy Update Inventory.* || "$line" =~ ^.*Could not connect to the JSS. Looking for cached policies.* || "$line" =~ ^.*Network state changed, checking for policies.* || "$line" =~ ^.*Checking for policies triggered by "networkStateChange".* ]]; then
      /bin/echo "" > /dev/null;
    else
      ## send logs to syslog server using logger command and syslog.conf file setting
      /usr/bin/logger -p local1.info "$line";
    fi
  done < /var/log/jamf.log

  # Format events so can create a user/DHCP table in SumoLogic
  /usr/bin/logger -p local1.info "jamf[1]: Client Hostname: $HN Client Office IP: $IP";

  ## cleanup and recreation
  /bin/rm -f /var/log/jamf.log
  /usr/bin/touch /var/log/jamf.log
  /usr/sbin/chown root:admin /var/log/jamf.log
  /bin/chmod 640 /var/log/jamf.log
fi' > $HOMEDIR/Library/Scripts/logpush.sh

#replace all @ with ' (required for echoing using ' to echo)
/usr/bin/sed -i .back "s/@/'/g" $HOMEDIR/Library/Scripts/logpush.sh
rm -rf $HOMEDIR/Library/Scripts/logpush.sh.back

# set permissions/ownership of /Library/LaunchDaemons/com.acme.cron_log.plist
chown root:wheel /Library/LaunchDaemons/com.acme.cron_log.plist
chmod 644 /Library/LaunchDaemons/com.acme.cron_log.plist

# get logged-in user and assign it to a variable
LOGGEDINUSER=$( ls -l /dev/console | awk '{print $3}' )

# set permissions/ownership of $HOMEDITR/Library/Scripts
chown $LOGGEDINUSER:staff $HOMEDIR/Library/Scripts/logpush.sh
chmod 744 $HOMEDIR/Library/Scripts/logpush.sh

# this section sets up the logger
/bin/mv /etc/syslog.conf /etc/syslog_conf_orig
/usr/bin/touch /etc/syslog.conf
/usr/sbin/chown root:wheel /etc/syslog.conf
/bin/chmod 644 /etc/syslog.conf

/bin/echo "##Custom syslog.conf file for security and compliance. Do not remove or modify." >> /etc/syslog.conf
/bin/echo "" >> /etc/syslog.conf

## office syslog.conf tweak, 10.13.20.5 is the syslog server listening on UDP/514
/bin/echo "*.*             @10.13.20.5:514" >> /etc/syslog.conf

## restart syslog
/bin/launchctl unload /System/Library/LaunchDaemons/com.apple.syslogd.plist
/bin/launchctl load /System/Library/LaunchDaemons/com.apple.syslogd.plist


# create running cron log variable
JOB=$(launchctl list | grep com.acme.cron_log | sed -e 's/^.*com/com/g')

# check if cron job is running, if not, load, if so, exit
if [ "$JOB" == "com.acme.cron_log" ]; then
    echo "Cron job running already."
else
    # set up cron job
    /bin/launchctl load /Library/LaunchDaemons/com.acme.cron_log.plist
fi

echo ""
echo "Script and launch plist deployed successfully. Restarting syslogd and loading com.acme.cron_log.plist..."
echo "..."
echo "done."
exit 0