├── .gitignore ├── rescue_account ├── screenshots │ ├── CreateRescueAccount.png │ ├── Rescue_Password_EA.png │ ├── RescueAccount_Cleanup.png │ ├── adjective.txt_example.png │ ├── Rescue_Password_Local_EA.png │ ├── passphrase_folder_setup.png │ ├── ChangeRescuePassword_scope.png │ ├── JamfConnect_userswithlocalauth.png │ ├── RescueAccount_Installed_group.png │ ├── RescueAccount_EA_ComputerRecord.png │ ├── RescueAccount_NeedsCleaned_group.png │ ├── RescueAccount_passwordNeedsReset_group.png │ ├── RescueAccount_InstalledNotEncrypted_group.png │ └── JamfConnect_prohibitedfromnetworkaccountconnection.png ├── Rescue Password - Local - EA.sh ├── pass_phrase.sh ├── rescue_account_cleanup.sh ├── README.md └── Rescue_Account_Password_Change.sh ├── SentinelOne ├── screenshots │ ├── SentinelOne_Policy_Packages.png │ ├── SentinelOne_Policy_Scripts.png │ └── SentinelOne_registration_token.png ├── SentinelOne_Version_EA.sh ├── README.md └── sentineone_postinstall.sh ├── README.md ├── update_safari_if_closed ├── Deprecated ├── Lastpass - Install Latest version.sh ├── BraveBrowser - Install Latest version.sh ├── Cisco Webex - install latest version.sh ├── Update_keychain_password.sh └── pass_phrase.py ├── Add Username Spelling.sh ├── Cert Cleaner - sanitized.sh ├── Update_local_password_for_jamf_connect ├── remote_AD_user_creation.sh ├── add localadmin to filevault.sh ├── Reset GlobalProtect - Multiple Portals.sh └── remove_and_readd_user_to_filevault /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | .DS_Store 4 | .DS_Store 5 | .DS_Store 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /rescue_account/screenshots/CreateRescueAccount.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/rescue_account/screenshots/CreateRescueAccount.png -------------------------------------------------------------------------------- /rescue_account/screenshots/Rescue_Password_EA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/rescue_account/screenshots/Rescue_Password_EA.png -------------------------------------------------------------------------------- /rescue_account/screenshots/RescueAccount_Cleanup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/rescue_account/screenshots/RescueAccount_Cleanup.png -------------------------------------------------------------------------------- /rescue_account/screenshots/adjective.txt_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/rescue_account/screenshots/adjective.txt_example.png -------------------------------------------------------------------------------- /SentinelOne/screenshots/SentinelOne_Policy_Packages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/SentinelOne/screenshots/SentinelOne_Policy_Packages.png -------------------------------------------------------------------------------- /SentinelOne/screenshots/SentinelOne_Policy_Scripts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/SentinelOne/screenshots/SentinelOne_Policy_Scripts.png -------------------------------------------------------------------------------- /rescue_account/screenshots/Rescue_Password_Local_EA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/rescue_account/screenshots/Rescue_Password_Local_EA.png -------------------------------------------------------------------------------- /rescue_account/screenshots/passphrase_folder_setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/rescue_account/screenshots/passphrase_folder_setup.png -------------------------------------------------------------------------------- /SentinelOne/screenshots/SentinelOne_registration_token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/SentinelOne/screenshots/SentinelOne_registration_token.png -------------------------------------------------------------------------------- /rescue_account/screenshots/ChangeRescuePassword_scope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/rescue_account/screenshots/ChangeRescuePassword_scope.png -------------------------------------------------------------------------------- /rescue_account/screenshots/JamfConnect_userswithlocalauth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/rescue_account/screenshots/JamfConnect_userswithlocalauth.png -------------------------------------------------------------------------------- /rescue_account/screenshots/RescueAccount_Installed_group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/rescue_account/screenshots/RescueAccount_Installed_group.png -------------------------------------------------------------------------------- /rescue_account/screenshots/RescueAccount_EA_ComputerRecord.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/rescue_account/screenshots/RescueAccount_EA_ComputerRecord.png -------------------------------------------------------------------------------- /rescue_account/screenshots/RescueAccount_NeedsCleaned_group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/rescue_account/screenshots/RescueAccount_NeedsCleaned_group.png -------------------------------------------------------------------------------- /rescue_account/screenshots/RescueAccount_passwordNeedsReset_group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/rescue_account/screenshots/RescueAccount_passwordNeedsReset_group.png -------------------------------------------------------------------------------- /rescue_account/screenshots/RescueAccount_InstalledNotEncrypted_group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/rescue_account/screenshots/RescueAccount_InstalledNotEncrypted_group.png -------------------------------------------------------------------------------- /rescue_account/screenshots/JamfConnect_prohibitedfromnetworkaccountconnection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theadamcraig/jamf-scripts/HEAD/rescue_account/screenshots/JamfConnect_prohibitedfromnetworkaccountconnection.png -------------------------------------------------------------------------------- /SentinelOne/SentinelOne_Version_EA.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -f "/usr/local/bin/sentinelctl" ] ; then 4 | RESULT=$( /usr/local/bin/sentinelctl version | awk '{print $2 $3}' ) 5 | else 6 | RESULT="not installed" 7 | fi 8 | 9 | echo "$RESULT" -------------------------------------------------------------------------------- /rescue_account/Rescue Password - Local - EA.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | passLocation="/Library/Application Support/COMPANYNAME/rescue" 4 | 5 | if [[ -e "$passLocation" ]] ;then 6 | echo "temp file exists! Continue" 7 | result=$(cat "$passLocation") 8 | else 9 | echo "Temp file missing" 10 | result="" 11 | fi 12 | 13 | echo "$result" 14 | exit 0 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jamf-scripts 2 | 3 | These are some of the scripts that i've used in jamf. 4 | I try to notate where i'm sourcing things from other people as I did not figure all of this out from scratch. 5 | I mostly put things here when I'm using it to answer a post on JamfNation or if it's something I worked really hard on and want to put out there. 6 | 7 | I'm not the best about keeping things here up to date as I edit them and update them in my Jamf environment. 8 | 9 | Let me know if things need explanation or aren't working for you and I'll try to help. 10 | -------------------------------------------------------------------------------- /update_safari_if_closed: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # written by theadamcraig 4 | # https://github.com/theadamcraig/jamf-scripts/blob/master/update_safari_if_closed 5 | 6 | appName="Safari Web Content" 7 | 8 | function updateSafari () { 9 | updateName=$(softwareupdate -l | grep "Safari" | grep "Label" | awk '{ print $3 }') 10 | if [ -z "$updateName" ] ; then 11 | echo "update not found." 12 | echo "listing software updates to make sure there is not an error:" 13 | echo $( softwareupdate -l ) 14 | exit 1 15 | fi 16 | softwareUpdate -i "$updateName" 17 | sleep 5 18 | exit 0 19 | } 20 | 21 | appRunning=`ps aux | grep -i "$appName" | grep -v "grep"` 22 | echo "Checking if $appName is running" 23 | echo "$appRunning" 24 | 25 | if [ -z "$appRunning" ] ; then 26 | echo "update Safari" 27 | updateSafari 28 | else 29 | echo "$appName is open. skipping Update" 30 | fi 31 | 32 | exit 0 33 | -------------------------------------------------------------------------------- /Deprecated/Lastpass - Install Latest version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ## I stopped using this. Installomator does it way better 4 | 5 | # https://github.com/Installomator/Installomator 6 | 7 | #based on a script that installs the latest version of Chrome 8 | 9 | 10 | dmgfile="LastPass.dmg" 11 | volname="LastPass Installer" 12 | logfile="/Library/Logs/LastPassInstallScript.log" 13 | 14 | url='https://lastpass.com/safariAppExtension.php?source=download' 15 | 16 | 17 | /bin/echo "--" >> ${logfile} 18 | /bin/echo "`date`: Downloading latest version." >> ${logfile} 19 | /usr/bin/curl -s -o /tmp/${dmgfile} ${url} 20 | /bin/echo "`date`: Mounting installer disk image." >> ${logfile} 21 | /usr/bin/hdiutil attach /tmp/${dmgfile} -nobrowse -quiet 22 | /bin/echo "`date`: Installing..." >> ${logfile} 23 | ditto -rsrc "/Volumes/${volname}/LastPass.app" "/Applications/LastPass.app" 24 | /bin/sleep 10 25 | /bin/echo "`date`: Unmounting installer disk image." >> ${logfile} 26 | /usr/bin/hdiutil detach $(/bin/df | /usr/bin/grep "${volname}" | awk '{print $1}') -quiet 27 | /bin/sleep 10 28 | /bin/echo "`date`: Deleting disk image." >> ${logfile} 29 | /bin/rm /tmp/"${dmgfile}" 30 | 31 | exit 0 -------------------------------------------------------------------------------- /Deprecated/BraveBrowser - Install Latest version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ## I stopped using this. Installomator does it way better 4 | 5 | # https://github.com/Installomator/Installomator 6 | 7 | #based on a script that installs the latest version of Chrome 8 | 9 | dmgfile="Brave-Broswer.dmg" 10 | volname="Brave Browser" 11 | logfile="/Library/Logs/BraveInstallScript.log" 12 | 13 | url='https://brave-browser-downloads.s3.brave.com/latest/Brave-Browser.dmg' 14 | 15 | 16 | /bin/echo "--" >> ${logfile} 17 | /bin/echo "`date`: Downloading latest version." >> ${logfile} 18 | /usr/bin/curl -s -o /tmp/${dmgfile} ${url} 19 | /bin/echo "`date`: Mounting installer disk image." >> ${logfile} 20 | /usr/bin/hdiutil attach /tmp/${dmgfile} -nobrowse -quiet 21 | /bin/echo "`date`: Installing..." >> ${logfile} 22 | ditto -rsrc "/Volumes/${volname}/Brave Browser.app" "/Applications/Brave Browser.app" 23 | /bin/sleep 10 24 | /bin/echo "`date`: Unmounting installer disk image." >> ${logfile} 25 | /usr/bin/hdiutil detach $(/bin/df | /usr/bin/grep "${volname}" | awk '{print $1}') -quiet 26 | /bin/sleep 10 27 | /bin/echo "`date`: Deleting disk image." >> ${logfile} 28 | /bin/rm /tmp/"${dmgfile}" 29 | 30 | exit 0 -------------------------------------------------------------------------------- /SentinelOne/README.md: -------------------------------------------------------------------------------- 1 | # SentinelOne 2 | 3 | These are instructions on how to use the SentinelOne post install script with Jamf 4 | 5 | the advantage of this workflow is that you can use one policy to install and update SentinelOne 6 | 7 | ### 1. Upload the SentinelAgent_macos_vXX_XX_X_XXXX_.pkg as downloaded from SentinelOne to Jamf 8 | 9 | ### 2. Add the script to Jamf. 10 | Change the line where it says "YOURREGISTRATIONTOKENHERE" to your sentinelone token. 11 | 12 | ![SentinelOne Token](https://github.com/theadamcraig/jamf-scripts/blob/master/SentinelOne/screenshots/SentinelOne_registration_token.png) 13 | 14 | ### 3. Create a new policy with whatever Scope and Trigger desired. 15 | 16 | ### 4. Add the package for SentinelOne to the policy. 17 | 18 | Make sure to set the Action to Cache 19 | 20 | ![SentinelOne Package Cache](https://github.com/theadamcraig/jamf-scripts/blob/master/SentinelOne/screenshots/SentinelOne_Policy_Packages.png) 21 | 22 | ### 5. Add the sentinelone_postinstall.sh script to the policy 23 | 24 | set the Priority to After 25 | 26 | As variable $4 add the full name of the .pkg that is being cached. 27 | 28 | ![SentinelOne Script](https://github.com/theadamcraig/jamf-scripts/blob/master/SentinelOne/screenshots/SentinelOne_Policy_Scripts.png) 29 | 30 | ### 6. Save the policy 31 | 32 | Caching the package puts it into /Library/Application Support/JAMF/Waiting Room/ 33 | 34 | the postinstall script will look for it there and install/upgrade it with your token as needed. 35 | 36 | I've also included an Extension attribute that can be used to create smartgroups for scoping sentinel one Updates. 37 | -------------------------------------------------------------------------------- /Deprecated/Cisco Webex - install latest version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## I stopped using this. Installomator does it way better 4 | 5 | # https://github.com/Installomator/Installomator 6 | 7 | # Based on a script that installs the latest version of chrome. 8 | 9 | loggedInUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ && ! /loginwindow/ { print $3 }' ) 10 | 11 | if [[ -z "$loggedInUser" ]] || [[ "$loggedInUser" == 'root' ]] || [[ "$loggedInUser" == "loginwindow" ]] ; then 12 | echo "Failed to gather loggedInUser correctly" 13 | exit 1 14 | else 15 | echo "loggedInUser is $loggedInUser" 16 | fi 17 | loggedInUID=$(id -u "$loggedInUser") 18 | 19 | 20 | dmgfile="webexapp.dmg" 21 | volname="Cisco Webex Meetings" 22 | logfile="/Library/Logs/WebexInstallScript.log" 23 | installerName="Cisco Webex Meetings.pkg" 24 | 25 | url='https://akamaicdn.webex.com/client/webexapp.dmg' 26 | 27 | 28 | /bin/echo "--" >> ${logfile} 29 | /bin/echo "`date`: Downloading latest version." >> ${logfile} 30 | /usr/bin/curl -s -o /tmp/${dmgfile} ${url} 31 | /bin/echo "`date`: Mounting installer disk image." >> ${logfile} 32 | /usr/bin/hdiutil attach /tmp/${dmgfile} -nobrowse -quiet 33 | /bin/echo "`date`: Installing..." >> ${logfile} 34 | 35 | ### run the installer as the user 36 | /bin/launchctl asuser "$loggedInUID" /usr/sbin/installer -pkg "/Volumes/${volname}/${installerName}" -target / 37 | /bin/sleep 10 38 | /bin/echo "`date`: Unmounting installer disk image." >> ${logfile} 39 | /usr/bin/hdiutil detach $(/bin/df | /usr/bin/grep "${volname}" | awk '{print $1}') -quiet 40 | /bin/sleep 10 41 | /bin/echo "`date`: Deleting disk image." >> ${logfile} 42 | /bin/rm /tmp/"${dmgfile}" 43 | 44 | exit 0 45 | -------------------------------------------------------------------------------- /Add Username Spelling.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## We are going to add a list of words to the users dictionary so that they are not autocorrected in an annoying way. 4 | ## this will hopefully prevent the thing where Okta login windows try to autocorrect usernames 5 | 6 | # started off with script from 7 | # https://macadmins.slack.com/archives/C07MGJ2SD/p1504615636000539 8 | 9 | companyName="YourCompanyNameHere" 10 | 11 | ######################################################################################### 12 | ## Get logged in user from Console. 13 | loggedInUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ && ! /loginwindow/ { print $3 }' ) 14 | 15 | ## make sure there is a value and that it's not any of the accounts that can occasionally be a result of the console method and have an error. 16 | if [[ -z "$loggedInUser" ]] || [[ "$loggedInUser" == 'root' ]] || [[ "$loggedInUser" == "loginwindow" ]] || [[ "$loggedInUser" == "_mbsetupuser" ]] ; then 17 | ## if it's not a valid user let's' take the result from jamf 18 | loggedInUser="$3" 19 | fi 20 | ## convert logged in user to lowercase 21 | ## sometimes we get an mixed case user and it can create inconsistent results 22 | if [ -n "$BASH_VERSION" ]; then 23 | # assume Bash 24 | loggedInUser=$( echo "$loggedInUser" | tr [:upper:] [:lower:] ) 25 | else 26 | # assume something else 27 | echo "script not written in bash, leaving as mixedcase." 28 | fi 29 | ## Make sure again that the user is valid. It's possible that $3 from Jamf is also an invalid user. 30 | if [[ -z "$loggedInUser" ]] || [[ "$loggedInUser" == 'root' ]] || [[ "$loggedInUser" == "loginwindow" ]] || [[ "$loggedInUser" == "_mbsetupuser" ]] ; then 31 | echo "Failed to gather loggedInUser correctly" 32 | exit 1 33 | else 34 | echo "loggedInUser is $loggedInUser" 35 | fi 36 | 37 | fullName=$( id -P $(stat -f%Su /dev/console) | awk -F '[:]' '{print $8}' ) 38 | 39 | LocalDictionary="/Users/${loggedInUser}/Library/Spelling/LocalDictionary" 40 | words=("${companyName}" "$loggedInUser" "$fullName") 41 | 42 | # Backup LocalDictionary 43 | cp $LocalDictionary ${LocalDictionary}.backup 44 | 45 | # Append each word from the list 46 | for word in "${words[@]}" 47 | do 48 | echo "$word" >> $LocalDictionary 49 | done 50 | 51 | # Sort case-insensitive out to the same file 52 | sort -f $LocalDictionary -o $LocalDictionary 53 | 54 | chown -R "$loggedInUser" "$LocalDictionary" 55 | chmod -R 644 "$LocalDictionary" 56 | 57 | exit 0 -------------------------------------------------------------------------------- /SentinelOne/sentineone_postinstall.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | ## script is written by the adamcraig and sourced from https://github.com/theadamcraig/jamf-scripts/tree/master/SentinelOne 4 | 5 | 6 | # Unlike other sentinel installs this script will either Install on a new computer OR upgrade if sentinel is already installed. 7 | #I manage sentinel versions entirely from Jamf and only use one policy for both installs and upgrades. 8 | 9 | ## MAKE SURE TO ADD IN YOUR TOKEN TO REPLACE "YOURTOKENGOESHERE" 10 | 11 | ##Originally I was packaging up the SentinelAgent_macos installer and putting it in /tmp/ 12 | ## then I changed to cache it so I didn't need to repackage it, so this script will check both /tmp and the waiting room. 13 | 14 | PKG_NAME="$4" 15 | ## ex: SentinelAgent_macos_v3_0_4_2657.pkg 16 | ## ex: SentinelAgent_macos_v3_2_0_2671.pkg 17 | 18 | if [ `id -u` != 0 ]; then 19 | /bin/echo "Error: You must run this command as root" 20 | exit 1 21 | fi 22 | 23 | if [[ "$PKG_NAME" == "" ]]; then 24 | /bin/echo "Error: The parameter 'SentinelOne .pkg Name' is blank. Please specify a value." 25 | exit 1 26 | fi 27 | 28 | REGISTRATION_TOKEN="/tmp/com.sentinelone.registration-token" 29 | S1_BINARY="/Library/Sentinel/sentinel-agent.bundle/Contents/MacOS/sentinelctl" 30 | WAITING_ROOM="/Library/Application Support/JAMF/Waiting Room/" 31 | INSTALL_DIRECTORY="/tmp/" 32 | 33 | 34 | ## check for the $PKG_NAME in the waiting room. if it exists then redefine INSTALL_PKG to that location 35 | ## this will allow the .pkg from sentinel one to be downloaded with out having to be repackaged 36 | ## this will also allow me to transition to doing this without needing to have 2 scripts. 37 | 38 | if [[ -e "${WAITING_ROOM}${PKG_NAME}" ]] ; then 39 | echo "Installer found in Waiting room" 40 | INSTALL_DIRECTORY="$WAITING_ROOM" 41 | fi 42 | 43 | INSTALL_PKG="${INSTALL_DIRECTORY}${PKG_NAME}" 44 | cd "${INSTALL_DIRECTORY}" 45 | 46 | echo "Install Package" 47 | echo "${INSTALL_PKG}" 48 | 49 | if [ ! -f "${INSTALL_PKG}" ]; then 50 | /bin/echo "Error: ${INSTALL_PKG} does not exist, exiting" 51 | exit 1 52 | fi 53 | 54 | ## if sentinelctl exists Upgrade sentinel one 55 | if [[ -f ${S1_BINARY} ]]; then 56 | echo "sentinel on computer. Upgrading sentinel" 57 | /usr/local/bin/sentinelctl upgrade-pkg "${INSTALL_PKG}" 58 | else 59 | #if not then install sentinel one 60 | ## create registration token 61 | cat > "${INSTALL_DIRECTORY}com.sentinelone.registration-token" << END 62 | YOURREGISTRATIONTOKENHERE 63 | END 64 | chmod -R 777 "${INSTALL_DIRECTORY}com.sentinelone.registration-token" 65 | /bin/echo "sentinel not on computer, beginning sentinel install" 66 | /usr/sbin/installer -pkg "${INSTALL_PKG}" -target / 67 | 68 | #clean up registration token 69 | sleep 10 70 | rm "${INSTALL_DIRECTORY}com.sentinelone.registration-token" 71 | fi 72 | 73 | #Clean up the installer and the jamf cache file 74 | rm -f "${INSTALL_PKG}" 75 | # also remove the cache.xml file 76 | rm -f "${INSTALL_PKG}"* 77 | 78 | exit 0 79 | -------------------------------------------------------------------------------- /rescue_account/pass_phrase.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | ## written by theadamcraig https://github.com/theadamcraig/jamf-scripts/ 4 | ## this script should be in the same directory as three text files 5 | ## adjectives.txt 6 | ## nouns.txt 7 | ## verbs.txt 8 | 9 | ## Optional arguments 10 | # --min Minimum characters for words default is 1 11 | # --max Maximum characters for words default is 9 12 | # --debug show full logging 13 | # --caps capitalize the first letter of every word. Default is no 14 | 15 | # Goal is to re-write pass_phrase.py in a way that will allow it to be used without python. 16 | #https://stackoverflow.com/questions/59895/how-can-i-get-the-source-directory-of-a-bash-script-from-within-the-script-itsel 17 | 18 | #hard code the default 19 | 20 | debug=0 21 | # do you want to capitalize the first letter of each word 22 | capitals="no" 23 | ## So we could easily change the divider between space - or none. 24 | div="" 25 | 26 | 27 | debugEcho() { 28 | local text="${1}" 29 | if [[ $debug = 1 ]] ; then 30 | echo "${text}" 31 | fi 32 | } 33 | 34 | ## process flags 35 | while test $# -gt 0 ; do 36 | case "${1}" in 37 | --min) 38 | shift 39 | minLength="$1" 40 | ;; 41 | --max) 42 | shift 43 | maxLength="$1" 44 | ;; 45 | --debug) debug=1 46 | ;; 47 | --caps) capitals="yes" 48 | ;; 49 | esac 50 | shift 51 | done 52 | 53 | debugEcho "DEBUG=$debug" 54 | 55 | workingDirectory=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) 56 | debugEcho "Working Directory Is: ${workingDirectory}" 57 | 58 | adjList="${workingDirectory}/adjectives.txt" 59 | nounList="${workingDirectory}/nouns.txt" 60 | verbList="${workingDirectory}/verbs.txt" 61 | 62 | if [[ ! -e "${adjList}" ]] ; then 63 | debugEcho "Adjective List not found" 64 | exit 1 65 | fi 66 | 67 | if [[ ! -e "${nounList}" ]] ; then 68 | debugEcho "Noun List not found" 69 | exit 1 70 | fi 71 | 72 | if [[ ! -e "${verbList}" ]] ; then 73 | debugEcho "Verb List not found" 74 | exit 1 75 | fi 76 | 77 | debugEcho "Raw min: $minLength"; 78 | debugEcho "Raw max: $maxLength"; 79 | 80 | ##Make sure minLength is an int. set it to 1 if it is empty or not an int 81 | case $minLength in 82 | ''|*[!0-9]*) debugEcho bad ; minLength=1 ;; 83 | *) debugEcho good ;; 84 | esac 85 | 86 | ## makesure maxLength is an int. set it to 9 if it is empty or not an int. 87 | case $maxLength in 88 | ''|*[!0-9]*) debugEcho bad ; maxLength=9 ;; 89 | *) debugEcho good ;; 90 | esac 91 | 92 | 93 | if [[ $minLength -gt $maxLength ]] ; then 94 | debugEcho "minLength greater than maxLength. swithgin varibales" 95 | tempVar=$minLength 96 | minLength=$maxLength 97 | maxLength=$tempVar 98 | fi 99 | 100 | debugEcho "min: $minLength"; 101 | debugEcho "max: $maxLength"; 102 | 103 | #Let's get our words into arrays 104 | declare -a adjArray 105 | adjArray=($(cat "$adjList")) 106 | debugEcho "loaded ${#adjArray[@]} Adjectives" 107 | 108 | declare -a nounArray 109 | nounArray=($(cat "$nounList")) 110 | debugEcho "loaded ${#nounArray[@]} Nouns" 111 | 112 | declare -a verbArray 113 | verbArray=($(cat "$verbList")) 114 | debugEcho "loaded ${#verbArray[@]} Verbs" 115 | 116 | ## ELIMINATE ALL WORDS THAT DON"T FIT THE Min/max length requirements and spit the array back out 117 | checkWordLength(){ 118 | local array=("$@") 119 | for i in "${!array[@]}" ; do 120 | #debugEcho "checking ${array[i]}" 121 | ## ${#string} prints the length 122 | if [[ ${#array[i]} -lt $minLength ]] || [[ ${#array[i]} -gt $maxLength ]] ; then 123 | #debugEcho "removing ${array[i]}" 124 | ##invalid length remove item 125 | unset 'array[i]' 126 | fi 127 | done 128 | #debugEcho "arrayCount= ${#array[@]}" 129 | echo "${array[@]}" 130 | } 131 | 132 | adjArray=($(checkWordLength "${adjArray[@]}")) 133 | debugEcho "refined ${#adjArray[@]} Adjectives" 134 | #declare -p adjArray 135 | 136 | nounArray=($(checkWordLength "${nounArray[@]}")) 137 | debugEcho "refined ${#nounArray[@]} Nouns" 138 | 139 | verbArray=($(checkWordLength "${verbArray[@]}")) 140 | debugEcho "refined ${#verbArray[@]} Verbs" 141 | 142 | getRandomWord(){ 143 | local array=("$@") 144 | # the random range excludes the top end of the range so we don't need to subtract 1. 145 | randMax=${#array[@]} 146 | #debugEcho "maximum index is $randMax" 147 | index=$(( $RANDOM % $randMax + 0 )) 148 | #debugEcho "random index is $index" 149 | local word="${array[$index]}" 150 | # Enfocre Lower case 151 | word=$(echo $word | tr '[:upper:]' '[:lower:]') 152 | #Capitalize first letter of each word 153 | if [[ "${capitals}" == "yes" ]] ; then 154 | word="$(tr '[:lower:]' '[:upper:]' <<< ${word:0:1})${word:1}" 155 | fi 156 | echo $word 157 | } 158 | 159 | ### Example command to get a random word 160 | # word=$(getRandomWord "${adjArray[@]}") 161 | 162 | ## Now let's make a password 163 | 164 | ## adjective noun verb digit adjective noun 165 | adj1=$(getRandomWord "${adjArray[@]}") 166 | debugEcho "$adj1" 167 | noun1=$(getRandomWord "${nounArray[@]}") 168 | debugEcho "$noun1" 169 | verb=$(getRandomWord "${verbArray[@]}") 170 | debugEcho "$verb" 171 | digit=$(( $RANDOM % 10 + 0 )) 172 | debugEcho "$digit" 173 | adj2=$(getRandomWord "${adjArray[@]}") 174 | debugEcho "$adj2" 175 | noun2=$(getRandomWord "${nounArray[@]}") 176 | debugEcho "$noun2" 177 | 178 | password="${adj1}${div}${noun1}${div}${verb}${div}${digit}${div}${adj2}${div}${noun2}" 179 | echo "$password" 180 | 181 | exit 0 182 | -------------------------------------------------------------------------------- /Cert Cleaner - sanitized.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## Based on script found at https://macadmins.slack.com/archives/CAL8UHH1N/p1576618800010400?thread_ts=1576576382.005200&cid=CAL8UHH1N 3 | 4 | ## Update the Cert Subject on line 28 and the email address format on line 51 5 | 6 | loggedInUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ && ! /loginwindow/ { print $3 }' ) 7 | 8 | if [[ -z "$loggedInUser" ]] || [[ "$loggedInUser" == 'root' ]] || [[ "$loggedInUser" == "loginwindow" ]] || [[ "$loggedInUser" == "_mbsetupuser" ]] ; then 9 | loggedInUser="$3" 10 | fi 11 | 12 | loggedInUser=$( echo "$loggedInUser" | tr [:upper:] [:lower:] ) 13 | 14 | if [[ -z "$loggedInUser" ]] || [[ "$loggedInUser" == 'root' ]] || [[ "$loggedInUser" == "loginwindow" ]] ; then 15 | echo "Failed to gather loggedInUser correctly" 16 | exit 1 17 | else 18 | echo "loggedInUser is $loggedInUser" 19 | fi 20 | # 21 | loggedInUID=$(id -u "$loggedInUser") 22 | 23 | userKeychain="/Users/$loggedInUser/Library/Keychains/login.keychain-db" 24 | 25 | # This script will remove all instances of a system keychain cert where: 26 | # 1) The certificate subject matches the cert subject below. 27 | # 2) It does not have the latest expiration date. 28 | certSubject="YOURDOMAINHERE" 29 | #certList=$( /bin/launchctl asuser "$loggedInUID" sudo -iu "$loggedInUser" security find-certificate -c "${certSubject}" -p -a "${userKeychain}") 30 | 31 | ## find all certs 32 | certList=$( /bin/launchctl asuser "$loggedInUID" sudo -iu "$loggedInUser" security find-certificate -p -a "${userKeychain}") 33 | 34 | #echo "$certList" 35 | 36 | # Get each cert into an array element 37 | # Remove spaces 38 | certList=$( echo "$certList" | sed 's/ //g' ) 39 | # Put a space after the end of each cert 40 | certList=$( echo "$certList" | sed 's/-----ENDCERTIFICATE-----/-----ENDCERTIFICATE----- /g' ) 41 | # echo "$certList" 42 | OIFS="$IFS" 43 | IFS=' ' 44 | # read -a certArray <<< "${certList}" 45 | declare -a certArray=($certList) 46 | IFS="$OIFS" 47 | i=-1 48 | dateHashList='' 49 | 50 | ## get a list of all keychain identities 51 | identityList=`/bin/launchctl asuser "$loggedInUID" sudo -iu "$loggedInUser" security find-identity -p smime -s @YOURDOMAINHHERE.com $userKeychain` 52 | ## remove all newlines 53 | identityList=${identityList//[$'\t\r\n']} 54 | 55 | 56 | declare -a deleteArray=() 57 | 58 | ## Go through the certs and add all the certs in the certArray to a deleteArray if the are in the identityList string 59 | 60 | for rawCert in "${certArray[@]}"; do 61 | let "i++" 62 | echo '--------' 63 | 64 | # Fix the begin/end certificate 65 | cert=$( echo "$rawCert" | sed 's/-----BEGINCERTIFICATE-----/-----BEGIN CERTIFICATE-----/g' ) 66 | cert=$( echo "$cert" | sed 's/-----ENDCERTIFICATE-----/-----END CERTIFICATE-----/g' ) 67 | certMD5=$( echo "$cert" | openssl x509 -noout -fingerprint -sha1 -inform pem | cut -d "=" -f 2 | sed 's/://g' ) 68 | 69 | echo "" 70 | echo "searching identity list" 71 | echo "${identityList}" 72 | echo "" 73 | 74 | if [[ "${identityList}" == *"${certMD5}"* ]] ; then 75 | echo "Item found in identity list" 76 | echo " " 77 | else 78 | deleteArray+=( "$rawCert" ) 79 | echo "adding '${certMD5}' to deleteArray" 80 | fi 81 | done 82 | 83 | echo "There are ${#certArray[@]} items in certArray" 84 | echo "There are ${#deleteArray[@]} items in deleteArray" 85 | 86 | for target in "${deleteArray[@]}"; do 87 | echo "" 88 | echo "parsing Delete Array Item" 89 | #echo "$target" 90 | for item in "${!certArray[@]}"; do 91 | if [[ ${certArray[item]} == $target ]]; then 92 | echo "item being unset from certArray" 93 | unset 'certArray[item]' 94 | fi 95 | done 96 | done 97 | 98 | echo "There are now ${#certArray[@]} items in certArray" 99 | 100 | 101 | ######################################################################################### 102 | ## go through the remaining certs and 103 | i=-1 104 | # Print what we got... 105 | for cert in "${certArray[@]}"; do 106 | let "i++" 107 | echo '---------' 108 | # echo "$cert" 109 | # echo '--' 110 | # Fix the begin/end certificate 111 | cert=$( echo "$cert" | sed 's/-----BEGINCERTIFICATE-----/-----BEGIN CERTIFICATE-----/g' ) 112 | cert=$( echo "$cert" | sed 's/-----ENDCERTIFICATE-----/-----END CERTIFICATE-----/g' ) 113 | # echo "$cert" 114 | # echo "$cert" | openssl x509 -text 115 | certMD5=$( echo "$cert" | openssl x509 -noout -fingerprint -sha1 -inform pem | cut -d "=" -f 2 | sed 's/://g' ) 116 | certDate=$( echo "$cert" | openssl x509 -text | grep 'Not After' | sed -E 's|.*Not After : ||' ) 117 | certDateFormatted=`date -jf "%b %d %T %Y %Z" "${certDate}" +%Y%m%d%H%M%S` 118 | echo "Cert ${i} : ${certDate} => $certDateFormatted" 119 | echo "Cert ${i} : ${certMD5}" 120 | NL=$'\n' 121 | dateHashList="${dateHashList}${NL}${certDateFormatted} ${certMD5}" 122 | done 123 | echo 124 | dateHashList=$( echo "$dateHashList" | sort | uniq ) 125 | lines=$( echo "$dateHashList" | wc -l | tr -d ' ' ) 126 | let "lines--" 127 | echo "[info] There are $lines lines in the certificate date-hash list." 128 | echo 129 | i=0 130 | OIFS="$IFS" 131 | IFS=$'\n' # make newlines the only separator 132 | for dateHash in $dateHashList; do 133 | let "i++" 134 | dateNum="${dateHash%% *}" 135 | hash="${dateHash##* }" 136 | echo "${i}| Hash : \"$hash\" | dateNum : \"$dateNum\"" 137 | if [[ i -ne $lines ]]; then 138 | echo "=> This cert will be removed" 139 | /bin/launchctl asuser "$loggedInUID" sudo -iu "$loggedInUser" security delete-identity -Z $hash "${userKeychain}" 140 | echo 141 | else 142 | echo "=> This cert will not be touched because it has the latest expiration date." 143 | fi 144 | done 145 | IFS="$OIFS" 146 | exit 0 147 | -------------------------------------------------------------------------------- /Update_local_password_for_jamf_connect: -------------------------------------------------------------------------------- 1 | 2 | adminName=$4 3 | adminPass=$5 4 | rescueUser="rescue" 5 | 6 | if [[ -z "$adminName" ]] || [[ -z "$adminPass" ]] ; then 7 | echo "admin name or admin pass missing" 8 | exit 1 9 | fi 10 | 11 | #Get logged in user 12 | 13 | loggedInUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ && ! /loginwindow/ { print $3 }' ) 14 | 15 | if [[ -z "$loggedInUser" ]] || [[ "$loggedInUser" == 'root' ]] || [[ "$loggedInUser" == "loginwindow" ]] ; then 16 | echo "Failed to gather loggedInUser correctly" 17 | exit 1 18 | else 19 | echo "loggedInUser is $loggedInUser" 20 | fi 21 | loggedInUID=$(id -u "$loggedInUser") 22 | 23 | if [[ "$loggedInUser" == "$adminName" ]] ; then 24 | PROCEED="button returned:Yes" 25 | else 26 | DESCRIPTION="WARNING: This is designed to be used when the password the the primary account for this computer has been forgotten. Please use only with the assistance of Helpdesk." 27 | 28 | PROCEED="$(osascript -e 'display dialog "'"$DESCRIPTION"'" buttons {"Yes", "No"} default button "Yes"')" 29 | fi 30 | 31 | if [ "$PROCEED" = "button returned:Yes" ]; then 32 | echo "Yes, continue with script." 33 | else 34 | echo "No, cancel script." 35 | exit 1 36 | fi 37 | 38 | 39 | 40 | #### SET UP DISPLAY DIALOG FUNCTION 41 | #### SET UP DISPLAY DIALOG FUNCTION 42 | DisplayDialog(){ 43 | local dialogText="$1" 44 | echo "$dialogText" 45 | #Log "Display Dialog: $dialogText" 46 | cmd="display dialog \"$dialogText\" buttons {\"Continue\"} default button 1 giving up after 180" 47 | if [[ -z "$loggedInUID" ]] || [[ -z "$loggedInUser" ]] ; then 48 | /usr/bin/osascript -e "$cmd" 49 | else 50 | /bin/launchctl asuser "$loggedInUID" sudo -iu "$loggedInUser" /usr/bin/osascript -e "$cmd" 51 | fi 52 | } 53 | 54 | 55 | ### MAKE SURE WE HAVE BOTH VARIABLES 56 | if [[ -z "$adminName" ]] || [[ -z "$adminPass" ]] ; then 57 | DisplayDialog "Either admin username or admin password is missing" 58 | exit 1 59 | fi 60 | 61 | 62 | 63 | echo " " 64 | echo "Checking admin passsword" 65 | adminPassCheck=$(/usr/bin/dscl /Local/Default -authonly "$adminName" "$adminPass") 66 | if [[ -z "$adminPassCheck" ]]; then 67 | echo "Continue" 68 | else 69 | DisplayDialog "admin Password not set correctly" 70 | exit 1 71 | fi 72 | 73 | 74 | echo " " 75 | echo "Making sure password is eligible for Jamf Connect password reset" 76 | 77 | check4AD="$(/usr/bin/dscl localhost -list . | grep "Active Directory")" 78 | 79 | jamfConnect="/Applications/Jamf Connect.app" 80 | 81 | NETACCLIST=$(dscl . list /Users OriginalNodeName | awk '{print $1}' 2>/dev/null) 82 | 83 | if [ "${check4AD}" != "Active Directory" ]; then 84 | echo "computer not bound to AD" 85 | else 86 | DisplayDialog "Computer bound to AD" 87 | exit 1 88 | fi 89 | 90 | if [[ -e "$jamfConnect" ]] ; then 91 | echo "jamf connect installed" 92 | else 93 | DisplayDialog "Jamf connect not installed" 94 | exit 1 95 | fi 96 | 97 | if [[ -n "$NETACCLIST" ]] ; then 98 | DisplayDialog "mobile accounts found." 99 | exit 1 100 | else 101 | echo "no mobile accounts" 102 | fi 103 | 104 | 105 | # 106 | ## get username to change 107 | echo "prompting user for Account Username" 108 | userName=$(/bin/launchctl asuser "$loggedInUID" sudo -iu "$loggedInUser" /usr/bin/osascript<