Policy in Loop till user is logged in

G_M_
New Contributor III

Because in my deployment I'm launching policies which need to have the local user logged in, I must put on standby all "Enrollment Complete" trigger policies before they start, waiting for the Local User to be created and then logged in.

My idea is to set a first policy which will stop the rest of policies from being launched just looping into a script.

In this script I would call this variable:

CURRENTUSER=stat -f "%Su" /dev/console

and then loop while

[ "$CURRENTUSER" = "_mbsetupuser" ] or [ "$CURRENTUSER" = "root" ] (in this I need help)

finally, I would let the loop stop and begin the rest of the policies flow as soon as the condition changes (e.g. [ "$CURRENTUSER" != "_mbsetupuser" ] )

Please help me getting a script that can achieve what I need..!

Thanks in advance for you effort guys, I really appreciate!!!

7 REPLIES 7

vinu_thankachan
Contributor

Please see the below discussion
https://www.jamf.com/jamf-nation/discussions/29048/run-policies-on-enrollment-after-user-logs-in

ryan_ball
Valued Contributor

@G.M. Here you go.

#!/bin/bash

function wait_for_gui () {
    # Wait for the dock to determine the current user
    DOCK_STATUS=$(pgrep -x Dock)
    echo "Waiting for Desktop..."

    while [[ "$DOCK_STATUS" == "" ]]; do
        echo "Desktop is not loaded; waiting..."
        sleep 5
        DOCK_STATUS=$(pgrep -x Dock)
    done

    CURRENT_USER=$(/usr/bin/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 + "
");')
    echo "$CURRENT_USER is logged in and at the desktop; continuing."
}

wait_for_gui

# Code below here runs after a user is logged in

exit 0

mm2270
Legendary Contributor III

Here's something I've used to get to this type of functionality. The first thing you would need to do is either add a custom event trigger to any of the policies you wish to run on the Mac after enrollment, or get their policy IDs. Scope is important, since it can't be forced if the machine is not in scope of the policies, so be sure to set each policy up in a way that it uses a Smart Group or some other criteria to ensure the Mac will be in scope to run it.

From there, you can pass the custom triggers and/or the policy IDs into parameter 4 in the main policy, which would be run on enrollment. Just separate each one by a space. Example of what $4 might look like:

installNoMAD installOffice 34 20 installFonts bindToAD enableFV2

It can be a mix of the custom triggers or just the IDs as shown. It will parse them out and run the appropriate trigger or ID in the order you add them into Parameter 4.

The script will check to see that at least one item was added to $4 before it will run at all. It also waits until the Dock is running, which is typically the best indicator that the initial user has logged in. This can be used in a DEP workflow, and in fact, I was originally using something like this, but am working now with using products like DEPNotify, since those give a GUI around the running policies so we can see what's going on.

Here's the script.

#!/bin/bash

## Populate parameter 4 with the policy IDs or their custom triggers
## Add them in the exact order (first to last) that you want them to run in

## Check to make sure we received at least one item in parameter 4
if [ -z "$4" ]; then
    echo "No items were passed to parameter 4. Add at least one or more policy ids and/or custom triggers to it for this script to work."
    exit 1
fi

## Add Param 4 to a POLICY_IDS array
POLICY_IDS=($4)

function runPolicies ()
{

## Establish a pattern to check for integer or standard string
patt='^[0-9]+$'

## Loop over the IDS/triggers and...
while read POLICY_ID; do
    ## check each to see if it's an integer or a string
    if [[ "$POLICY_ID" =~ $patt ]]; then
        ## If an integer, set the trigger to -id
        TRIG="-id"
    else
        ## If a string, set the trigger to -event
        TRIG="-event"
    fi
    ## Run the policy
    /usr/local/bin/jamf policy $TRIG $POLICY_ID
done < <(printf '%s
' "${POLICY_IDS[@]}")

exit 0

}

## Check to make sure the Dock is running before we start the policies
DOCK_PROCESS=$(pgrep -l "Dock")
until [ "$DOCK_PROCESS" != "" ]; do
    sleep 1
    DOCK_PROCESS=$(pgrep -l "Dock")
done

## Now that the Dock is running, we can run the policies
runPolicies

G_M_
New Contributor III

@ryan.ball That sounds great..

Just a question..

what does your CURRENT_USER do

(/usr/bin/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 + " ");')

instead of my CURRENTUSER

CURRENTUSER=stat -f "%Su" /dev/console

..?

Sorry for my ignorance but I feel the need to understand :)

G_M_
New Contributor III

@ryan.ball

The script seems to work well, I've noticed that all polcies get launched as _mbsetupuser..I guess is a side effect of the Enrollment Complete Policy which stands pending with that user through your script..is there a way to make the local user calling the policies instead of _mbsetupuser?

Another question at this point..

I've made the way that, all Policies for the first deploy are simply triggered by "Enrollment Complete" and because those are launched in alphabetical order, the first policy (which simply contains your script) holds on standby the policy flow as expected.

Should I launch through your script a "jamf policy -event..." in order to launch the flow, and should I then use the same for each policy?

My choice to launch all the scripts through the "Enrollment Complete" trigger instead of flowing through custom trigger is that the custom triggered policies seems to get stucked pretty easy and the whole process become really slow..or even not able to be completed.

Thanks for your great support

ryan_ball
Valued Contributor

My enrollment complete policies for DEP machines are just to set the timeserver, and create an account basically. Once a user logs in, I do a loop of jamf policy -event $trigger for all of the policies that I want to run and in what order followed by a few other things like recon softwareupdate -ia then restart.

There are shades of what I do in the DEPNotify-Starter repo and basically this is the same workflow as what @mm2270 has posted above as well.