Detect if policy was run through Self Service or not

lparnell
New Contributor II

I'm working on a script that is initiated through Self Service and Startup (ongoing). I want the script to know whether it was initiated from Self Service or if it just ran because of a restart. Right now I have the script detecting whether Self Service is running when the script starts which seems to work well, but I don't want Self Service to open up as soon as a user logs in and accidentally start the script. My question, is there an easy way for the script to know if it is being run from Self Service or not?

Additional Information:
I found that a process starts when a policy is run through Self Service called "JamfManagementService", but if I run

pgrep "JamfManagementService"

inside of the script, it doesn't find anything. If I run this same script through Terminal while a policy is running through Self Service it finds it every time. I'm not sure why this process can't be found when run from inside the policy, I think this would be the best way to resolve this issue if I could get it to work, but maybe there is a better solution that I don't know about.

If it helps, I can explain the purpose of the full script and how it works, but it is a bit lengthy.

What I currently have:

# If any user is logged in and Self Service is running, then...
if [ "$3" != "" ] && pgrep "Self Service" >/dev/null 2>&1; then
    echo "This script was run through Self Service" 
else
    echo "This script was run through Jamf trigger event" 
fi

What I would like to have:

# If the JamfManagementService process is running, then...
if pgrep "JamfManagementService" >/dev/null 2>&1; then
    echo "This script was run through Self Service" 
else
    echo "This script was run through Jamf trigger event" 
fi
1 ACCEPTED SOLUTION

lparnell
New Contributor II

I figured this out. I'm a little embarrassed at how simple this fix is, but I haven't used pgrep much. When running pgrep it will by default leave out itself and its parent processes unless you add -a. This is how it should look:

#!/bin/sh

if pgrep -a "JamfManagementService" >/dev/null 2>&1; then
    echo "This script was run through Self Service"
else
    echo "This script was run through terminal"
fi

I feel more confident checking if the process is running this way. I don't think it is likely that this process would be running during startup or login, but it is likely that Self Service could open at startup. As a safetynet I am also adding a user prompt, to ask if they want to continue the script or exit out, it will look something like this:

#!/bin/sh

currentUser=$3
userID=$(id -u "$currentUser")

/bin/launchctl asuser $userID sudo -iu $currentUser osascript -e 'display dialog "All account data will be deleted, press OK to continue. The computer will restart 3 times before it is finishes rebuilding the account." buttons {"OK", "Cancel"} default button "Cancel" giving up after 60'

View solution in original post

6 REPLIES 6

matin
New Contributor III

Interesting however you may want to consider a policy structure change to make it easier to determine if a policy is called by self service or by another trigger. Meaning, have you tried breaking up a single policy into 2 or more policies? For example, let's take an inventory update (aka recon).

Instead of a single policy with the trigger set to self service and the payload included, you can break it up to 2 policies:
- Payload Policy - Policy that is ongoing and with a custom trigger name enabled that has the 'payload'
- Trigger Policy - Policy that calls the Payload Policy and customized trigger. In this case, we enable just self service. Note, you can create additional trigger policies if you need to detect other triggers like reoccuring check-in, login, logout, etc.
d4fa7bdfe18d438eb50b5209e20754c7

This way you can grep the /var/log/jamf.log for any policy name that ends in this example with "- Self Service" in the policy title.

lparnell
New Contributor II

This isn't a bad idea and I hadn't thought about referencing this log. It might be difficult to accurately grep this policy in that log file when it is meant to run maybe twice a week so it will show up a lot in this log. Potentially, I could clear this log each time to make this easier. I originally started this script with multiple policies, but I also have 3 other variations of this policy. I'm basically trying to get 8 policies down to 4 policies (one for each variation).

This whole script runs in a series of steps that are separated by restarts. When it is triggered by Self Service it needs to know that it should start step 1. After it finishes step 1 it leaves a trail that it can pick up after the next restart to know it is ready for step 2. This continues until it gets to the last step. The only real issue is verifying that the script should really start step 1 or not. Since it runs at each startup it needs to know if it is meant to run or just exit. If it is helpful, I included the whole script. It is meant to delete a user account and recreate it for our loaner computers. We may assign 10 loaners in a day and need to have a quick hands off method to clear the data off and set them back up.

#!/bin/zsh

# This script will run in a sequence of steps.

#  Issues... 
#   STEP 1: Script might run again if Self Service opens during login (Continuous loop)

#  STEP 1: Disable FileVault
#   Disables FileVault
#   Pulls AutoLogin data for student Account from Jamf
#   Removes AutoLogin User
#   Checks for cla Account and builds if needed
#   Setup for STEP 2 and Restart
#
#  STEP 2: Delete Student Account
#   Deletes Student Account
#   Enables FileVault
#   Setup for STEP 3 and Restart
#
#  STEP 3: Create Student Account
#   Creates Student Account
#   Sets student Account as AutoLogin User
#   Clean up Scripts and Restart


# Define variables
currentUser=$3
studentAccount=$4
studentPass=$5
claAccount=$6
claPass=$7
adminAccount=$8
adminPass=$9

filePath="/var/db/scripts/rebuild${studentAccount}M1"

# Run STEP 1 if any user is logged on, Self Service is running, and the filePath doesn't exist.
if [ "$currentUser" != "" ] && pgrep "Self Service" >/dev/null 2>&1 && [ ! -d "${filePath}" ]; then

    # Log Start of STEP 1
    echo "Starting STEP 1"

    # Disable FileVault
    /usr/bin/expect <<-EOF
    spawn fdesetup disable
    expect ":"
    sleep 1
    send -- "$studentAccount
"
    expect ":"
    sleep 1
    send -- "$studentPass
"
    expect ":"
    sleep 1
    send -- "
"
    EOF

    # Set Student as AutoLogin
    #  This stores the credentials for the student account autoLogin
    sudo jamf policy -event studentAutoLogin

    # Clear out autologin preferences
    #  This only clears out which user account is used for autoLogin, this can be set back by just setting the user account
    defaults delete /Library/Preferences/com.apple.loginwindow autoLoginUser
    echo "Removed autologin data"

    # Create cla account if it doesn't exist. studentAccount can't be deleted if it is the only account.
    if id "$claAccount" >/dev/null 2>&1; then
            echo "$claAccount account is present."
    else
            echo "$claAccount account is not present. Creating $claAccount account."
            sudo sysadminctl -adminUser "$adminAccount" -adminPassword "$adminPass" -addUser "$claAccount" -fullName "$claAccount" -password "$claPass" -admin
    fi

    # Create a folder in the tmp directory called scripts then create a directory inside that is called rebuild + $studentAccount
    mkdir /var/db/scripts
    mkdir "${filePath}"
    echo "Created '/var/db/scripts/'"

    # Create a text file in that directory called step2.txt
    touch "${filePath}/step2.txt"
    echo "Created ${filePath}/step2.txt"

    # Restart the computer
    shutdown -r now

# Run STEP 2 if ${filePath}/step2.txt exists.
elif [ -e "${filePath}/step2.txt" ]; then

    # Log Start of STEP 2
    echo "Starting STEP 2"

    # Remove studentAccount if it exists
    if id "$studentAccount" >/dev/null 2>&1; then
            echo "$studentAccount account is present. Deleting $studentAccount account."
            sudo sysadminctl -adminUser "$adminAccount" -adminPassword "$adminPass" -deleteUser "$studentAccount"
    else
            echo "$studentAccount account is not present. Cannot remove."
    fi

    # Enable FileVault
    sudo jamf policy -event EnableFVShared

    # Remove step2.txt
    rm "${filePath}/step2.txt"
    echo "Removed ${filePath}/step2.txt"

    # Create a text file called step3.txt
    touch "${filePath}/step3.txt"
    echo "Created ${filePath}/step3.txt"

    # Restart computer
    shutdown -r now

# Run STEP 3 if ${filePath}/step3.txt exists
elif [ -e "${filePath}/step3.txt" ]; then

    # Log Start of STEP 3
    echo "Starting STEP 3"

    # Create studentAccount if it doesn't exist
    if id "$studentAccount" >/dev/null 2>&1; then
            echo "$studentAccount account is present. Unable to create."
    else
            echo "$studentAccount account is not present. Creating $studentAccount."
            sudo sysadminctl -adminUser "$adminAccount" -adminPassword "$adminPass" -addUser "$studentAccount" -fullName "$studentAccount" -password "$studentPass" -standard
    fi

    # Set studentAccount to Auto Login
    /usr/bin/defaults write /Library/Preferences/com.apple.loginwindow.plist autoLoginUser $studentAccount
    echo "$studentAccount is now the default Auto Login user."

    # Remove the scripts directory
    rm -r "${filePath}"
    echo "Removed the rebuild${studentAccount} directory"

    # Restart the computer
    shutdown -r now

fi

echo "Exiting script."

exit 0

alexjdale
Valued Contributor III

I handle this sort of thing by simply having two policies, and the script would use a parameter to determine how it should behave. I'd then enter the appropriate parameter for each policy.

lparnell
New Contributor II

That might also be a good way to go. I could have another parameter that sets whether it is erasing an elementary computer, a secondary computer, a staff computer, or an encrypted computer. That way I am down to potentially just one script and a handful of policies. This seems to be the safe route.
I'm still wondering if anyone knows why pgrep is unable to see the JamfManagementService when being run from a jamf script? I feel like I could just be using it incorrectly. I have also tried running it as the currently logged-in user to see if that would help, but I still get the same output.

#!/bin/sh

pgrep -lu $3 .

Here are some outputs I have received. I trimmed it down to just the end where the JamfManagementService is listed. I'm confused why they are different at all. See process 63063, it cut off the line a little bit but the whole process is called JamfManagementService.

#!/bin/sh

pgrep -l .

When run from Jamf policy:
42871 PerfPowerServic
63048 sleep
63049 sleep
63051 mdworker_shared
63052 mdworker_shared
63053 mdworker_shared
63054 mdworker_shared
63055 mdworker_shared
63056 sleep
63057 CoreServicesUIA
63058 sleep
63059 sleep
63060 sleep
63061 sleep
63094 mdworker_shared

When run on the computer through Terminal while a Self Service policy is running:
42871 PerfPowerServic
63048 sleep
63049 sleep
63051 mdworker_shared
63052 mdworker_shared
63053 mdworker_shared
63054 mdworker_shared
63055 mdworker_shared
63056 sleep
63057 CoreServicesUIA
63058 sleep
63059 sleep
63060 sleep
63061 sleep
63063 JamfManagementS
63065 jamf

user-oXZRyAaFbe
New Contributor

I highly appreciate your hard-working skills as the post you published have some great information which is quite beneficial for me, I hope you will post more like that in the future

lparnell
New Contributor II

I figured this out. I'm a little embarrassed at how simple this fix is, but I haven't used pgrep much. When running pgrep it will by default leave out itself and its parent processes unless you add -a. This is how it should look:

#!/bin/sh

if pgrep -a "JamfManagementService" >/dev/null 2>&1; then
    echo "This script was run through Self Service"
else
    echo "This script was run through terminal"
fi

I feel more confident checking if the process is running this way. I don't think it is likely that this process would be running during startup or login, but it is likely that Self Service could open at startup. As a safetynet I am also adding a user prompt, to ask if they want to continue the script or exit out, it will look something like this:

#!/bin/sh

currentUser=$3
userID=$(id -u "$currentUser")

/bin/launchctl asuser $userID sudo -iu $currentUser osascript -e 'display dialog "All account data will be deleted, press OK to continue. The computer will restart 3 times before it is finishes rebuilding the account." buttons {"OK", "Cancel"} default button "Cancel" giving up after 60'