02-25-2022 12:14 PM - edited 03-05-2022 06:27 AM
Hi all,
I'm really just posting this to document the long journey that I've had to creating a new enrollment workflow for our district.
Goal
To have one universal enrollment for new Mac's that auto name themselves based on the user logging in, with the least amount of signing in as possible.
Requirements
1. A Jamf Infrastructure Manager (JIM)
2. Microsoft Azure/Active Directory
3. Jamf Connect (Installed in Prestage Enrollment as well as config profiles)
4. PPPC Utility and TCC profiles covering Jamf (and jamfDaemon), osascript, including all system events and accessibility also installed with prestage enrollment
5. Configuration Profile for Microsoft SSO extension that includes apples setup assistant also installed with prestage enrollment
6. Microsoft Company Portal App (in Prestage Enrollment)
7. Managed Apple ID's that are federated to Microsoft logins
Steps
Prestage Enrollment:
After much testing our prestage enrollment includes all the installers for all the software the user may need.
1. JamfConnect2.9.1.pkg
2. JamfConnectLaunchAgent2.9.1.pkg
3. aanotify.sh.pkg (this is our jamfconnect notify script that runs on first login)
4. aaPPSLogo.jpg.pkg (our district logo)
5. CompanyPortal-Installer.pkg (for microsoft SSO)
6. Firefox
7. Chrome
8. Microsoft Office Pro (the installer from macadmins.software)
9. ZoomForIT installer and the managed zoom preference file
10. cocoaDialog.pkg (for our custom EULA for staff)
11. desktoppr-0.3.pkg (to set desktop patterns)
12. dockutil.pkg (to set custom dock)
We also push a ton of config profiles to allow notifications for zoom, team viewer, testnav and also tons of other TCC profiles to keep the privacy settings from prompting as much as possible.
We have a custom profile that just sets the first login actions for Jamf Connect and lists the path to the script to run during the login window process (Notify). This profile will fall off once the machine gets named as its excluded from named computers which keeps the notify script to only show once.
Enrollment
We are using 12.2.1 and are using the Erase-Install Script to help facilitate correct wipes of the device before enrollment. The mdm management "Wipe Computer" command only seems to install the same OS that is currently installed which works once the machine is updated.
Once Enrolled it takes up to about 12 min to install all the pre-stage software so we have made a script that pops a jamf helper timer that counts down the time (on the login window) and then has you click continue. This script does the initial policy check-in which runs the first recon if it hasn't run already then triggers a policy we have that installs rosetta (which is only scoped to Apple Silicon/M1 devices) and then triggers the creative cloud installer (which is only scoped to the machines who have a specific PO number indicating they are our one-to-one computers) while also running a caffeinate command to keep the screen active and then runs our time also simultaneously. We saw an issue where the jamf helper timer would close itself after the timer countdown which then didn't let the tech know that it ever ran if they didnt watch it, so we added another pop up right after the timer with a "Continue" button. If the timer does not Pop-Up then the machine is not correctly installed, which we have also seen happen on maybe 1 out of every 25 and then just needs to be wiped again (and or have its record deleted from Jamf).
#!/bin/sh
jamf policy
jamf policy -trigger rosetta
jamf policy -trigger creativecloud &
caffeinate -i -s -d -t 900 &
/Library/Application\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -lockHUD -icon /Library/Desktop\ Pictures/PPSLogo.jpg -title "Tech Office" -heading "Please wait for install to complete..." -description "Installing all needed software..." -countdown -timeout 720 -alignCountdown right
/Library/Application\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -lockHUD -icon /Library/Desktop\ Pictures/PPSLogo.jpg -title "Tech Office" -heading "Initial Setup Complete" -description "Click Continue for Login Screen" -button1 "Continue" -defaultButton 1
Once we continue to the next screen we are greeted with our Jamf Connect page (we are using Azure/Microsoft authentication which on first login will run the Connect Notify Script (as long as you set a profile with a path to the notify script and have it scoped in a way that will remove the profile after the user logs in, in our case the notify script is running a device naming script so we only scope the profile to computers without a correct name).
Right after the 1st sign-in the notify script runs (which was installed during prestage) which triggers any extra policies we want in Jamf and also gives a little overview of the computer.
#!/bin/zsh
#variables
NOTIFY_LOG="/var/tmp/depnotify.log"
#For TOKEN_BASIC, use same file path location as set for OIDCIDTokenPath in com.jamf.connect.login
TOKEN_BASIC="/tmp/token"
TOKEN_GIVEN_NAME=$(echo "$(cat $TOKEN_BASIC)" | sed -e 's/\"//g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | grep given_name | cut -d ":" -f2)
TOKEN_UPN=$(echo "$(cat $TOKEN_BASIC)" | sed -e 's/\"//g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | grep upn | cut -d ":" -f2)
/usr/bin/caffeinate -discu -t 3600&
echo $TOKEN_GIVEN_NAME
echo $TOKEN_UPN
echo "STARTING RUN" >> $NOTIFY_LOG # Define the number of increments for the progress bar
echo "Command: Determinate: 6" >> $NOTIFY_LOG
#1 - Introduction window with username and animation
echo "Command: Image: /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/com.apple.macbookair-2018-space-gray.icns" >> $NOTIFY_LOG
echo "Command: MainTitle: Welcome, $TOKEN_GIVEN_NAME" >> $NOTIFY_LOG
echo "Command: MainText: Your Mac is now enrolled and will be automatically configured for you." >> $NOTIFY_LOG
echo "Status: Preparing and naming your new Mac..." >> $NOTIFY_LOG
sleep 10
#2 - Setting up single sign-on passwords for local account
echo "Command: Image: /System/Applications/Contacts.app/Contents/Resources/Contacts.icns" >> $NOTIFY_LOG
echo "Command: MainTitle: Tired of multiple passwords? \n $TOKEN_GIVEN_NAME " >> $NOTIFY_LOG
echo "Command: MainText: We use single sign-on services to help you sign in to each of our district services.
Use your email address and account password to sign in to all necessary applications." >> $NOTIFY_LOG
echo "Status: Setting the password for your Mac..." >> $NOTIFY_LOG
sleep 10
#3 - Self Service makes the Mac life easier
echo "Command: Image: /Applications/Self Service.app/Contents/Resources/AppIcon.icns" >> $NOTIFY_LOG
echo "Command: MainTitle: Self Service makes Mac life easier" >> $NOTIFY_LOG
echo "Command: MainText: Self Service allows you to install software without the need for an admin password." >> $NOTIFY_LOG
echo "Status: Installing Self Service..." >> $NOTIFY_LOG
sleep 10
#4 - Everything you need for your first day
###Jamf Triggers
echo "Command: Image: /System/Library/CoreServices/Install in Progress.app/Contents/Resources/Installer.icns" >> $NOTIFY_LOG
echo "Command: MainTitle: Installing everything you need." >> $NOTIFY_LOG
echo "Command: MainText: All the apps you will need today are already being installed. When setup is complete, you'll find Microsoft Office and Zoom are all ready to go." >> $NOTIFY_LOG
echo "Status: Installing Apps..." >> $NOTIFY_LOG
/usr/local/bin/jamf policy -event "admindesktop"
sleep 5
#5 - Finishing up
echo "Command: Image: /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/ApplicationsFolderIcon.icns" >> $NOTIFY_LOG
echo "Status: Installing a few more apps..." >> $NOTIFY_LOG
/usr/local/bin/jamf policy -event "NameME"
sleep 5
echo "Status: Finishing up... We're almost ready for you, $TOKEN_GIVEN_NAME" >> $NOTIFY_LOG
sleep 3
###Clean Up
sleep 3
echo "Command: Quit" >> $NOTIFY_LOG
sleep 1
rm -rf $NOTIFY_LOG
#6 - Disable notify screen from loginwindow process
/usr/local/bin/authchanger -reset -JamfConnect
The biggest piece here is the script that actually names the computer by looking up the user who just logged in and changing the name based on the building, whether Student or Teacher, and finally adds the Asset Tag number to the end. Thanks again to master/legendary scripter @mm2270 for help making this script work correctly for our environment and my Jamf Customer Success Manager who kept working with me to help get this process nailed down.
This script looks at the last created home folder and grabs the name (since the user isn't fully created at this point) then runs a "recon -endUsername" and assigns the device to the user which also then looks up all of their info from the JIM then looks for OU info from the extension attribute for which building and if its a teacher or student.
#!/bin/sh
highest_uid=$(/usr/bin/dscl . list /Users UniqueID | /usr/bin/awk '$2 > 500 {print $2}' | /usr/bin/sort -n | /usr/bin/tail -1)
currentUser=$(/usr/bin/dscl . search /Users UniqueID $highest_uid | /usr/bin/awk '{print $1; exit}')
jamf recon -endUsername $currentUser
USERNAME="$4"
PASSWORD="$5"
JAMF_URL="$6"
EA_NAME="$7"
UUID=$(ioreg -rd1 -c IOPlatformExpertDevice | awk -F'"' '/IOPlatformUUID/{print $4}')
LDAP_EA_VALUE=$(/usr/bin/curl -H "Accept: application/xml" -su "$USERNAME:$PASSWORD" "${JAMF_URL}/JSSResource/computers/udid/${UUID}/subset/extension_attributes" | xpath -e "//extension_attribute[name='$EA_NAME']" 2>/dev/null | xmllint --format - | awk -F'>|<' '/<value>/{print $3}')
OU_VALUES=$(/bin/echo "$LDAP_EA_VALUE" | tr ',' '\n' | grep "^OU=" | tr '\n' ' ')
ASSETTAG=$(/usr/bin/curl -H "Accept: application/xml" -su "$USERNAME:$PASSWORD" "${JAMF_URL}/JSSResource/computers/udid/${UUID}/subset/general" | xmllint --format - 2>/dev/null | awk -F'>|<' '/<asset_tag>/{print $3}')
BUILDING=$(if grep -q "PHS" <<< "$OU_VALUES"];
then echo "HS"
fi
if grep -q "JW" <<< "$OU_VALUES"];
then echo "MS"
fi
if grep -q "CP" <<< "$OU_VALUES"];
then echo "CP"
fi
if grep -q "RS" <<< "$OU_VALUES"];
then echo "RS"
fi
if grep -q "JP" <<< "$OU_VALUES"];
then echo "JP"
fi
if grep -q "LB" <<< "$OU_VALUES"];
then echo "LB"
fi
if grep -q "VR" <<< "$OU_VALUES"];
then echo "VR"
fi
if grep -q "PMS" <<< "$OU_VALUES"];
then echo "MS"
fi
if grep -q "MS" <<< "$OU_VALUES"];
then echo "MS"
fi)
POSITION=$(if grep -q "Students" <<< "$OU_VALUES"];
then echo "-Student"
else echo "-Teacher"
fi)
COMPUTERNAME="$BUILDING""$POSITION""$ASSETTAG"
/usr/sbin/scutil --set ComputerName "${COMPUTERNAME}"
sleep 1
/usr/sbin/scutil --set LocalHostName "${COMPUTERNAME}"
sleep 1
/usr/sbin/scutil --set HostName "${COMPUTERNAME}"
sleep 1
dscacheutil -flushcache
echo "Computer name has been set to "${COMPUTERNAME}""
jamf recon
exit 0
The above script requires that there is an LDAP lookup in your environment and has the users in the correct OU's to indicate specific values and you would also need to have a JIM (Jamf Infrastructure Manager) for Jamf to be able to look up that info for you. It also requires an extension attribute that grabs the OU info using using the ldap manager:
This is currently a post in progress...More to come as i get more time...
Solved! Go to Solution.
04-18-2022 07:17 AM - edited 04-18-2022 07:18 AM
Hey @tommmy_s
1. DEP notify only runs once a user has logged in. However I tackle this with the earlier script of having installs trigger during enrollment so it should come up before the user logs in to set some things.
2. The Token_Basic isnt really used especially with o365 from what I've found. I asked my rep about this, but didnt get very far. All this does is use the actual user name to personalize the message during the Notify script. I was going to edit this to use the newly created user like I did with the naming script, but just never got around to it. More of a nice to do instead of a need to do though.
Hope that helps!
Posted on 03-03-2022 10:13 AM
Love this. Thank you!
Posted on 03-03-2022 10:33 AM
Thanks...I have to post all the scripts and go through the process completely...so watch for edits to the top when I can get a chance....
Posted on 04-13-2022 01:47 PM
Hi @GabeShack thanks for this article. We got Jamf Connect last week and we are planning to put something very similar to what you have. Two questions I got for you.
Q1: Your current setup looks like a user logs in and then the DEPNotify runs. Do you know if this DEPNotify can be trigger before a user even logs in?
Q2: (may or may not related to Q1) In your and also Jamf's documentation, I can see that TOKEN_BASIC is used. I'm not sure what that is what it does. We supplied the OIDCIDTokenPath in our com.jamf.connect.login but i'm not sure if it's in /tmp/token. How can I verify that it's the same path and/or what this TOKEN_BASIC is here for.
Thanks in advance!
#For TOKEN_BASIC, use same file path location as set for OIDCIDTokenPath in com.jamf.connect.login TOKEN_BASIC="/tmp/token" TOKEN_GIVEN_NAME=$(echo "$(cat $TOKEN_BASIC)" | sed -e 's/\"//g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | grep given_name | cut -d ":" -f2) TOKEN_UPN=$(echo "$(cat $TOKEN_BASIC)" | sed -e 's/\"//g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | grep upn | cut -d ":" -f2) echo $TOKEN_GIVEN_NAME echo $TOKEN_UPN
04-18-2022 07:17 AM - edited 04-18-2022 07:18 AM
Hey @tommmy_s
1. DEP notify only runs once a user has logged in. However I tackle this with the earlier script of having installs trigger during enrollment so it should come up before the user logs in to set some things.
2. The Token_Basic isnt really used especially with o365 from what I've found. I asked my rep about this, but didnt get very far. All this does is use the actual user name to personalize the message during the Notify script. I was going to edit this to use the newly created user like I did with the naming script, but just never got around to it. More of a nice to do instead of a need to do though.
Hope that helps!