Help your users easily provide Microsoft Support their Office configuration files while maintaining user privacy
Background
After implementing Microsoft’s recommended macro security in Office for Mac settings via a Configuration Profile, then having affected users run Paul’s Office-Reset packages via Jamf Pro’s Self Service, some users are still observing the dreaded Run-time error 32815
triple-prompts for Visual Basic for Applications when opening blank documents in Word, Excel or PowerPoint.
While again re-running — or re-re-running — the Office-Reset policies suppress the error, we started working with Microsoft Support to determine root-cause as the issue seems to reemerge immediately after each Office update.
TL;DR: We’re currently convinced it’s Adobe Acrobat DC’s fault
Capture User’s Office Configuration
We started by focusing on Word and the request from Microsoft Support was to capture the content of the following folders both before and after the next Office upgrade:
~/Library/Containers/com.microsoft.Word
~/Library/Group Containers/UBF8T346G9.Office/User Content.localized/*
/Library/Application Support/Microsoft/Office365/User Content.localized/*
~/Library/Containers
Since a sandboxed app can only write to its own directories, the ~/Library/Containers/com.microsoft.Word/Data
folder contains aliases to several user folders, including ~/Desktop
, ~/Downloads
and the highly personal ~/Pictures
directory:
❯ ls -lah ~/Library/Containers/com.microsoft.Word/Data total 16 drwx------ 13 dan staff 416B Sep 2 01:15 . drwx------@ 5 dan staff 160B Sep 2 01:15 .. lrwxr-xr-x 1 dan staff 19B Jul 19 08:37 Desktop -> ../../../../Desktop drwx------ 2 dan staff 64B Jul 19 08:37 Documents lrwxr-xr-x 1 dan staff 21B Jul 19 08:37 Downloads -> ../../../../Downloads drwx------ 33 dan staff 1.0K Jul 28 14:52 Library lrwxr-xr-x 1 dan staff 18B Jul 19 08:37 Movies -> ../../../../Movies lrwxr-xr-x 1 dan staff 17B Jul 19 08:37 Music -> ../../../../Music lrwxr-xr-x 1 dan staff 20B Jul 19 08:37 Pictures -> ../../../../Pictures drwx------ 2 dan staff 64B Jul 19 08:37 SystemData drwx------ 2 dan staff 64B Jul 19 08:37 tmp
--symlinks
As entertaining as this Personally Identifiable Information (PII) may be to a Microsoft Support engineer, we elected to exclude the contents of aliased directories by adding the --symlinks
option to the zip
command.
--exclude
After a review by our internal Security team, we choose to also exclude the Cookies
and WebKit
directories:
The
Cookies
folder may contain authentication cookiesThe
Webkit
folder could include authentication data from our IdP
Note: While the user’s shortname
is plainly visible in the output, this is most likleyl already known to Microsoft.
Script
Add the following script to Jamf Pro, adjusting the workspace
URL as provided by Microsoft Support. (Latest version available on GitHub.)
#!/bin/bash #################################################################################################### # # ABOUT # # Microsoft Office User Configuration Capture # #################################################################################################### # # HISTORY # # Version 1.0.0, 02-Sep-2022, Dan K. Snelson # Original version # # Version 1.0.1, 02-Sep-2022, Dan K. Snelson # Exclude "Webkit" and "Cookies" (per Obi-Bryson) # #################################################################################################### #################################################################################################### # # Variables # #################################################################################################### scriptVersion="1.0.1" scriptResult="" export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin loggedInUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }' ) loggedInUserHome=$( dscl . -read /Users/$loggedInUser | grep NFSHomeDirectory: | cut -c 19- | head -n 1 ) serialNumber=$( system_profiler SPHardwareDataType | grep "Serial Number" | awk -F ": " '{ print $2 }' ) timestamp=$( date '+%Y-%m-%d-%H%M%S' ) filename="microsoft_case_86753099_${serialNumber}-${timestamp}" #################################################################################################### # # Functions # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Check for / install swiftDialog (thanks, @acodega!) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function dialogCheck(){ # Get the URL of the latest PKG From the Dialog GitHub repo dialogURL=$( curl --silent --fail "https://api.github.com/repos/bartreardon/swiftDialog/releases/latest" | awk -F '"' "/browser_download_url/ && /pkg\"/ { print \$4; exit }" ) # Expected Team ID of the downloaded PKG expectedDialogTeamID="PWA5E9TQ59" # Check for Dialog and install if not found if [[ ! -e "/Library/Application Support/Dialog/Dialog.app" ]]; then scriptResult+="Installing Dialog; " # Create temporary working directory workDirectory=$( basename "$0" ) tempDirectory=$( mktemp -d "/private/tmp/$workDirectory.XXXXXX" ) # Download the installer package curl --location --silent "$dialogURL" -o "$tempDirectory/Dialog.pkg" # Verify the download teamID=$( spctl -a -vv -t install "$tempDirectory/Dialog.pkg" 2>&1 | awk '/origin=/ {print $NF }' | tr -d '()' ) # Install the package if Team ID validates if [[ "$expectedDialogTeamID" = "$teamID" ]] || [[ "$expectedDialogTeamID" = "" ]]; then installer -pkg "$tempDirectory/Dialog.pkg" -target / else jamfDisplayMessage "Dialog Team ID verification failed." exit 1 fi # Remove the temporary working directory when done rm -Rf "$tempDirectory" else scriptResult+="Dialog version $(dialog --version) found; proceeding..." fi } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Display Message: Dialog # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function displayMessageDialog() { rm /var/tmp/dialog.log title="${1}" message="${2}" icon=$( defaults read /Library/Preferences/com.jamfsoftware.jamf.plist self_service_app_path ) scriptResult+="Display \"${title}\" message to ${loggedInUser}; " dialog --title "${title}" --message "${message}" --icon "${icon}" --ontop --moveable echo "quit:" >> /var/tmp/dialog.log } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # JAMF Display Message (for fallback in case swiftDialog fails to install) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function jamfDisplayMessage() { scriptResult+="${1}" jamf displayMessage -message "${1}" & } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Reveal File in Finder # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function revealMe() { /usr/bin/su - "${loggedInUser}" -c '/usr/bin/open -R "'"${1}"'" ' } #################################################################################################### # # Program # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Logging preamble # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # scriptResult+="Microsoft Office User Configuration Capture (${scriptVersion}); " # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Confirm script is running as root # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ $(id -u) -ne 0 ]]; then scriptResult+="This script should be run as root; exiting." echo "${scriptResult}" exit 1 fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Validate logged-in user # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ -z "${loggedInUser}" || "${loggedInUser}" == "loginwindow" ]]; then scriptResult+="No user logged-in; exiting." echo "${scriptResult}" exit 0 fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Validate swiftDialog is installed # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # dialogCheck # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Compress Microsoft Word-related directories # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # scriptResult+="Compress Microsoft Word-related directories; " zip --quiet --recurse-paths --symlinks "${loggedInUserHome}/Desktop/${filename}.zip" "/Library/Application Support/Microsoft/Office365/User Content.localized" "${loggedInUserHome}/Library/Group Containers/UBF8T346G9.Office/User Content.localized" "${loggedInUserHome}/Library/Containers/com.microsoft.Word" --exclude "${loggedInUserHome}/Library/Containers/com.microsoft.Word/Data/Library/Cookies/*" --exclude "${loggedInUserHome}/Library/Containers/com.microsoft.Word/Data/Library/WebKit/*" scriptResult+="Microsoft Word-related directories saved to: ${loggedInUserHome}/Desktop/${filename}.zip; " # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Display End-user Message # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # displayMessageDialog "Microsoft Case No. 86753099 (${scriptVersion})" "## Log Gathering Complete \n\nYour computer logs have been saved to your Desktop as: \n\n\`${filename}.zip\` \n\nPlease [upload](https://support.microsoft.com/files?workspace=ridiculously-long-URL-goes-here) the file to Microsoft." # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Reveal Compressed File # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # scriptResult+="Reveal Compressed File; " revealMe "${loggedInUserHome}/Desktop/${filename}.zip" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Exit # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # scriptResult+="Complete!" echo "${scriptResult}" exit 0
Policy
Create a new Jamf Pro policy, add the script and make the policy available in Self Service.
Self Service Description
Adjust the workspace
URL as provided by Microsoft Support.
## Office for Mac: Default templates' macros re-enabled with each upgrade Please click the **Capture** button to save the following directories to your Mac's Desktop: - `/Library/Application Support/Microsoft/Office365/User Content` - `~/Library/Containers/Microsoft Word` - `~/Library/Group Containers/UBF8T346G9.Office/User Content` Once complete, a compressed file with a name similar to `microsoft_case_86753099 … .zip` will be saved to your Mac's Desktop. Please [upload](https://support.microsoft.com/files?workspace=ridiculously-long-URL-goes-here) the `microsoft_case_86753099 … .zip` file to Microsoft.
User Message
The script will gather the directories and leverage swiftDialog (installing, if necessary) to display a Self Service-branded message to the users which includes a link to upload the output directly to Microsoft: