Login/Logout Hooks no longer working?

Doubletime
New Contributor

I've done some searching and haven't found anything in the discussions as recent regarding our issue, so wanted to see what others have been doing with this.

Our login and logout hook triggers have not been working since our recent update to 9.98 and we contacted JAMF support accordingly. The tech explained that Apple is no longer supporting login & logout hooks, and thus will no longer work for us. I'm trying to think of ways to replace our events that occurred with these such as granting admin rights on login or deleting keychains on logout. Anyone have this same issue or have any ideas?

24 REPLIES 24

Cornoir
Contributor II

Try using outset as a replacement:
https://github.com/chilcote/outset

grecopj
Contributor

Were these scripts local to the machines or did yo have them as polices to run at login?

hsekiv
Contributor

Interesting because I've been trying to implement the PaperCut login this week (using 9.98) and it hasn't worked yet.

Doubletime
New Contributor
by grecopj Were these scripts local to the machines or did yo have them as polices to run at login?

These were policies that ran scripts (loaded in our DP via Casper Admin) or commands on the "login" or "logout" triggers.

Doubletime
New Contributor
by Cornoir Try using outset as a replacement: https://github.com/chilcote/outset

Thank you for the link, this looks very promising. Will have to play around with this to see how well it can be integrated with JAMF Pro and our environment (College Higher-Ed). Was looking for examples of how it could be used in the GitHub page but will have to experiment with the usage options.

Doubletime
New Contributor
by hsekiv Interesting because I've been trying to implement the PaperCut login this week (using 9.98) and it hasn't worked yet.

Yep, same problem with us if you were using login and logout as triggers for a policy. Checked the logs and didn't see anything showing for those triggers, but oddly it would work here and there with some other policies we had. The JAMF support rep said he wasn't privy to any info on further development relating to these triggers but I would welcome anything that could replace their function with JAMF Pro.

mm2270
Legendary Contributor III

While I haven't seen this (yet) myself, some of the Apple articles I see on the subject from Fall of last year only state that Apple strongly discourages the use of login or logout hooks. It does not however, state that they will no longer work, period. Given the date of the article I saw was, I think, after Sierra was released, I would think it should still work as of today.
However, the Apple kb recommends using launchd jobs, which kind of makes sense since LaunchAgents will run at login and only at login, if designed to do so. Unfortunately, they cannot run as root, which loginhooks did, and which is why Jamf was using them to call policies at login. We can't run a jamf policy command with root using a LaunchAgent, so.... I'm not sure where that leaves us if they are not going to work anymore. Maybe outset as mentioned above? Or, there may be a way using a LaunchAgent/LaunchDaemon combination to get the same functionality back.

Doubletime
New Contributor
by mm2270 While I haven't seen this (yet) myself, some of the Apple articles I see on the subject from Fall of last year only state that Apple strongly discourages the use of login or logout hooks. It does not however, state that they will no longer work, period. Given the date of the article I saw was, I think, after Sierra was released, I would think it should still work as of today. However, the Apple kb recommends using launchd jobs, which kind of makes sense since LaunchAgents will run at login and only at login, if designed to do so. Unfortunately, they cannot run as root, which loginhooks did, and which is why Jamf was using them to call policies at login. We can't run a jamf policy command with root using a LaunchAgent, so.... I'm not sure where that leaves us if they are not going to work anymore. Maybe outset as mentioned above? Or, there may be a way using a LaunchAgent/LaunchDaemon combination to get the same functionality back.

Thanks for confirming some of our findings; it seems to be the case that it's not entirely non-functional as it still works "here and there". We also came to that same realization of your statement "I'm not sure where that leaves us if they are not going to work anymore" after seeing the documentation from Apple. Using Outset and launchd's seem to be a way so far, but would be great if JAMF and Apple find a way to incorporate an alternative replacement function for JSS to use. Guess I got too spoiled with just clicking a checkbox and figuring it's good to go. XD

Going to play with Outset for now but am grateful in advance (and to those who have already contributed) to anyone who has other approaches they are using to ensure actions invoke on login or logout in their environments.

mbezzo
Contributor III

Hi All,
We've been running into this a lot lately - as has been mentioned, it's not that login/logout hooks don't work, they just don't work RELIABLY. Which, is super frustrating and maybe even worse than just NOT working...

I've worked with our Jamf buddy to figure out a solution and we basically settled on this:

create a launchdaemon that starts a shell script with a while loop that waits for a user to be logged in AND the Dock process to exist (the trouble with the launchagents/daemons at least for us is that they simply start WAY too quickly/early) then calls whatever jamf policy once the while loop is exited. It seems to be working fairly well.

I really hope Jamf/Apple do figure out a solution soon though, as this is a fair bit of work to test/validate and then of course deploy and cleanup after the fact... Makes things pretty complex pretty quick!

Thanks,
Matt

Swift
New Contributor II

You could also use this to replace Login Hooks:

ConsoleUserWarden

Does not use login hooks. Uses a LaunchDaemon. Runs as root. Triggered at login, logout and fast user switch by changes to the 'State:/Users/ConsoleUser' key in the dynamic store.

seann
Contributor

guess we'll see... apple deprecated those hooks a while ago. :( given the current state of malware and their dependence on services there may be other things we can't do in the future

CCNapier
Contributor

@Doubletime Did you find a good solution? I'm looking at the same issue.

@Swift I've been playing with Launchdaemon with a watch; would you know if you just add the 'State:/Users/ConsoleUser' to the watchfolder in the plist? I'm not familiar with the State setting.

millersc
Valued Contributor

@CCNapier I know this is a continuation from the other thread, but we've been using Outset. I was working with the new version and found if you drop a script in the outset folder, you don't get any logging in JSS. But as of 1.0.4 version there is a "authenticated" folder which allows to drop a basic script to call a JSS policy number. Gives you logs then. Just an FYI.

CCNapier
Contributor

@millersc Thanks, just installing Outset now and trying to get to grips.
Was playing with a daemon (that was watching for a file update from a login launchagent script), and triggering a policy to mount a share, but was always trying to mount as root rather than the user. Hopefully Outset might resolve that...

CCNapier
Contributor

@millersc I am using Outset 2.0.6 and dropping a script that calls Jamf Policy -event ID into the "login-privileged-every" folder

It seems to call the policy [script that mounts a share] OK, but tries to mount the share as "root" - is pops up the username/password box to the user with "root" filled in as the user. This is obviously different behaviour than before [as it always mounted as the user and didn't ask for authentication].

Although I can see Outset is going to be handy moving ahead.

millersc
Valued Contributor

@CCNapier I'd have to see the script, but you should be able to use $3 or system calls with python to call out the user. Obviously your going to have to re-engineer your workflow and scripts to make this work with outset vs JSS builtin tools.

We are using an old apple script Rich made for AD, but modified it some for our needs. Saved it as an app and use it with a launch agent for all users logging in. It's been working great for drive mappings, plus we can call the app from NoMAD in the menubar in the latest versions.

I do like keeping our scripts in the JSS for modifications and just having a script called by outset by ID #. Plus this does give us the logs in JSS as I mentioned before.

CCNapier
Contributor

@millersc The script we are using can see the logged in user using $3, but we are using osascript command to mount SMB and seems to be doing this in root context (the script shows root with a whoami command, although it also does that with a loginhook).

I preferred using osascript when we built the script as it seemed more reliable than other SMB mount commands in our environment.
It could well be that osascript is having the issue.

I guess the launchdaemon runs as root, whereas the loginhooks run elevated as the logged in user (sudo style) which may make a difference in the way that the the jamf command interacts.

I don't expect you to pick over my code, but just for completeness, here is the basic idea:

#!/bin/sh

echo $(whoami)
#This always shows as root

echo $3
#This always shows the logged in user

domnt()
{
    serverName="myserver"
    if (( $# > 1 )); then 
        serverName=$2
    fi
    protocol="smb"
    if (( $# > 2 )); then 
        protocol=$3
    fi
    shareName=$1

    echo "Attempting Mount $protocol://${serverName}/${shareName}"

    # Mount the drive
    mount_script=`/usr/bin/osascript > /dev/null << EOT
        tell application "Finder" 
        activate
        mount volume "$protocol://${serverName}/${shareName}"
        end tell
EOT`
}

domnt "thisarea/shared"

So essentially mount volume $protocol://${serverName}/${shareName} tries to mount as root.

edit-
just changed this to a smb_mount command and received an authentication error, so I would assume it's not an osascript limitation.

joshuaaclark
Contributor

Ours quit working, too. By accident today, I went to modify a config profile to adjust our screensaver times and noticed that in text of the profile was the words skip loginhook = true and skip logouthook = true. I adjusted the profile under login window, under the fourth tab "Script"; I checked the box for Also execute the client computer's LoginHook script and Also execute the client computer's LogoutHook script. When I refreshed the profiles, the skip hooks were gone, and my logout policies worked again.

CCNapier
Contributor

I've now created a mount drive script with a recursive function that loops through all group memberships and maps the correct drive accordingly. I've deployed this along side Outset and it runs as the user in "login-every" folder.

Pain that we couldn't use the JSS built in group membership to trigger, but a nice exercise in bash function etc.
So, ditched JSS policy with login trigger and manual trigger and scripted the whole lot.

ctarbox
Contributor II

I do have some success in getting the Policies triggered by Login Hooks to run by unscoping, then rescoping the smart group that the policy is assigned to.

Cheryl

spraguga
Contributor

@mbezzo Can you provide the LaunchDaemon and script that JAMF gave you? I'd rather implement this than another 3rd party tool.

mbezzo
Contributor III

@spraguga Jamf didn't hand me files - just bits of code to inject into my scripts. I'll see if I can pull it out and clean it up and post it here soonish.

Thanks!
Matt

spraguga
Contributor

@mbezzo Awesome, thank you!

mbezzo
Contributor III

@spraguga Okay, took a look through my older stuff and couldn't find the launchDaemon part, and I'm no longer using that these days anyway, but I am still using this bit of code which makes the process/policy/whatever wait until the correct user is fully logged in. Maybe it'll help:

#!/bin/bash

# Function to add date to log entries
log(){
NOW="$(date +"*%Y-%m-%d %H:%M:%S")"
echo "$NOW": "$1"
}

# Logging for troubleshooting - view the log at /var/log/nameofloghere.log
touch /var/log/nameofloghere.log
exec 2>&1>/var/log/nameofloghere.log

# Find the currently logged in user
loggedInUser=$(python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "
");')
log "loggedInUser is $loggedInUser"

# get UID for current User
currentUID=$(dscl . -list /Users UniqueID | grep $loggedInUser | awk '{print $2;}')

# Check and see if we're currently running as the user we want to setup - pause and wait if not
log "Current UID is $currentUID"
while [ "$currentUID" -lt 1000 ] || [ -z "$currentUID" ]; do
  log "Currently logged in user is NOT the correct user. Waiting."
  sleep 5
  loggedInUser=`python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "
");'`
  currentUID=$(dscl . -list /Users UniqueID | grep $loggedInUser | awk '{print $2;}')
  log "Current user is $loggedInUser with UID $currentUID"
done

# Now that we have the correct user logged in - need to wait for the login to complete so we don't start too early
dockStatus=$(pgrep -x Dock)
log "Waiting for Desktop"
while [ "$dockStatus" == "" ]; do
  log "Desktop is not loaded. Waiting."
  sleep 5
  dockStatus=$(pgrep -x Dock)
done

# Start policy
log "Desktop has loaded, starting policy"
jamf policy -event youreventhere

Just give the log a name, and adjust the UID part for what makes sense in your environment.

Good luck!
Matt