Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save talkingmoose/520c79d8d0f9bc49c9e07ca43122225c to your computer and use it in GitHub Desktop.

Select an option

Save talkingmoose/520c79d8d0f9bc49c9e07ca43122225c to your computer and use it in GitHub Desktop.
Creates Moble Device Configuration Profiles in Jamf Pro to pair one iOS device with the Apple TV Remote app to one Apple TV. Useful for hospital or school environments to simplify the device list when browsing and increase security by enforcing which devices can communicate.
#!/bin/bash
<<ABOUT_THIS_SCRIPT
-----------------------------------------------------------------------
Written by:William Smith
Professional Services Engineer
Jamf
bill@talkingmoose.net
https://gist.github.com/talkingmoose/520c79d8d0f9bc49c9e07ca43122225c
Originally posted: June 7, 2019
Purpose: Reads a CSV file for mass creation of Moble Device
Configuration Profiles in Jamf Pro to pair one iPad running Apple
TV Remote app to one Apple TV. Useful for hospital or school
environments with multiple devices to reduce the device list
when browsing in the same area and increase security by not
allowing devices in one area to access devices in another area.
Instructions: First, create a CSV file with Unix line-feed (LF)
endings (use a plain text editor such as
BBEdit from https://barebones.com) and three columns of
information:
room number,Apple TV name,iPad name
Then, edit the script customizations below and run the script.
This script creates a log file in the same location as the script.
Possible HTTP result codes:
200 Request successful
201 Request to create or update object successful
400 Bad request
401 Authentication failed
403 Invalid permissions
404 Object/resource not found
409 Conflict
500 Internal server error
Except where otherwise noted, this work is licensed under
http://creativecommons.org/licenses/by/4.0/
"If you have built castles in the air, your work need not be lost;
that is where they should be. Now put the foundations under them."
-----------------------------------------------------------------------
ABOUT_THIS_SCRIPT
<<INFO
-----------------------------------------------------------------------
Script customizations
-----------------------------------------------------------------------
INFO
# Jamf Pro URL and credentials
URL="https://jamfpro.talkingmoose.net:8443"
userName="api-editor"
password="P@55w0rd"
# organization name that appears in the configuration profile
organizationName="Talking Moose Industries"
# path to the CSV file
CSVFilePath="/Users/talkingmoose/Desktop/OneToOneConfigs.csv"
# Jamf Pro site
siteName="None"
# Jamf Pro category
category="Security"
<<INFO
-----------------------------------------------------------------------
File locations
-----------------------------------------------------------------------
INFO
# path to this script
currentDirectory=$( /usr/bin/dirname "$0" )
# name of this script
currentScript=$( /usr/bin/basename -s .sh "$0" )
# create log file in same directory as script
logFile="$currentDirectory/$currentScript - $( /bin/date '+%y-%m-%d' ).log"
<<INFO
-----------------------------------------------------------------------
Functions
-----------------------------------------------------------------------
INFO
function logresult() {
if [ $? = 0 ] ; then
/bin/date "+%Y-%m-%d %H:%M:%S $1" >> "$logFile"
else
/bin/date "+%Y-%m-%d %H:%M:%S $2" >> "$logFile"
fi
}
<<INFO
-----------------------------------------------------------------------
Start the script
-----------------------------------------------------------------------
INFO
# read the CSV file
assignmentsList=$( /bin/cat "$CSVFilePath" )
# process each line in the CSV file
while IFS= read aLine
do
# read room number from assignments list
roomNumber=$( /usr/bin/awk -F ',' '{ print $1 }' <<< $aLine )
logresult "Room number: $roomNumber." "Failed retrieving room number."
# get MAC address of Apple TV by name
TVDeviceName=$( /usr/bin/awk -F ',' '{ print $2 }' <<< $aLine )
logresult "Apple TV name: $TVDeviceName." "Failed retrieving Apple TV name."
# create a URL encoded version of the device name
TVDeviceNameEncoded=$( /usr/bin/sed 's/ /%20/g' <<< $TVDeviceName )
logresult "URL encoding Apple TV name: $TVDeviceNameEncoded." "Failed URL encoding Apple TV name."
# read the device in Jamf Pro by name and return its MAC address for the profile
TVDeviceID=$( /usr/bin/curl -s "$URL/JSSResource/mobiledevices/name/$TVDeviceNameEncoded" \
--user "$userName":"$password" \
--header "Accept: text/xml" \
--request GET \
| /usr/bin/xpath '/mobile_device/general/wifi_mac_address/text()' )
logresult "MAC address for Apple TV '$TVDeviceName': $TVDeviceID." "Failed retrieving MAC address for Apple TV $TVDeviceName."
# get MAC address of iPad by name
remoteDeviceName=$( /usr/bin/awk -F ',' '{ print $3 }' <<< $aLine )
logresult "iOS device name: $remoteDeviceName." "Failed retrieving iOS device name."
# create a URL encoded version of the device name
remoteDeviceNameEncoded=$( /usr/bin/sed 's/ /%20/g' <<< $remoteDeviceName )
logresult "URL encoding iOS device name: $remoteDeviceNameEncoded." "Failed URL encoding iOS device name."
# read the device in Jamf Pro by name and return its MAC address for the profile
remoteDeviceID=$( /usr/bin/curl -s "$URL/JSSResource/mobiledevices/name/$remoteDeviceNameEncoded" \
--user "$userName":"$password" \
--header "Accept: text/xml" \
--request GET \
| /usr/bin/xpath '/mobile_device/general/wifi_mac_address/text()' )
logresult "MAC address for iOS device '$remoteDeviceName': $remoteDeviceID." "Failed retrieving MAC address for iOS device $remoteDeviceName."
# generate payload UUIDs
payloadUUID1=$( /usr/bin/uuidgen )
logresult "Generating configuration profile UUID: $payloadUUID1." "Failed generating configuration profile UUID."
payloadUUID2=$( /usr/bin/uuidgen )
logresult "Generating payload UUID: $payloadUUID2." "Failed generating payload UUID."
# create the XML for the configuration profile
profileXML="<configuration_profile>
<general>
<name>Apple TV Remote Patient - $roomNumber</name>
<description/>
<site>
<name>$siteName</name>
</site>
<category>
<name>$category</name>
</category>
<uuid>$payloadUUID1</uuid>
<deployment_method>Install Automatically</deployment_method>
<redeploy_on_update>Newly Assigned</redeploy_on_update>
<redeploy_days_before_certificate_expires>0</redeploy_days_before_certificate_expires>
<payloads>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;&lt;!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"&gt;&lt;plist version=\"1\"&gt;&lt;dict&gt;&lt;key&gt;PayloadUUID&lt;/key&gt;&lt;string&gt;$payloadUUID1&lt;/string&gt;&lt;key&gt;PayloadType&lt;/key&gt;&lt;string&gt;Configuration&lt;/string&gt;&lt;key&gt;PayloadOrganization&lt;/key&gt;&lt;string&gt;$organizationName&lt;/string&gt;&lt;key&gt;PayloadIdentifier&lt;/key&gt;&lt;string&gt;$payloadUUID1&lt;/string&gt;&lt;key&gt;PayloadDisplayName&lt;/key&gt;&lt;string&gt;Apple TV Remote Patient - $roomNumber&lt;/string&gt;&lt;key&gt;PayloadDescription&lt;/key&gt;&lt;string/&gt;&lt;key&gt;PayloadVersion&lt;/key&gt;&lt;integer&gt;1&lt;/integer&gt;&lt;key&gt;PayloadEnabled&lt;/key&gt;&lt;true/&gt;&lt;key&gt;PayloadRemovalDisallowed&lt;/key&gt;&lt;true/&gt;&lt;key&gt;PayloadContent&lt;/key&gt;&lt;array&gt;&lt;dict&gt;&lt;key&gt;PayloadUUID&lt;/key&gt;&lt;string&gt;$payloadUUID2&lt;/string&gt;&lt;key&gt;PayloadType&lt;/key&gt;&lt;string&gt;com.apple.tvremote&lt;/string&gt;&lt;key&gt;PayloadOrganization&lt;/key&gt;&lt;string&gt;$organizationName&lt;/string&gt;&lt;key&gt;PayloadIdentifier&lt;/key&gt;&lt;string&gt;$payloadUUID2&lt;/string&gt;&lt;key&gt;PayloadDisplayName&lt;/key&gt;&lt;string&gt;com.apple.tvremote&lt;/string&gt;&lt;key&gt;PayloadDescription&lt;/key&gt;&lt;string/&gt;&lt;key&gt;PayloadVersion&lt;/key&gt;&lt;integer&gt;1&lt;/integer&gt;&lt;key&gt;PayloadEnabled&lt;/key&gt;&lt;true/&gt;&lt;key&gt;AllowedRemotes&lt;/key&gt;&lt;array&gt;&lt;dict&gt;&lt;key&gt;RemoteDeviceID&lt;/key&gt;&lt;string&gt;$remoteDeviceID&lt;/string&gt;&lt;/dict&gt;&lt;/array&gt;&lt;key&gt;AllowedTVs&lt;/key&gt;&lt;array&gt;&lt;dict&gt;&lt;key&gt;TVDeviceID&lt;/key&gt;&lt;string&gt;$TVDeviceID&lt;/string&gt;&lt;/dict&gt;&lt;/array&gt;&lt;/dict&gt;&lt;/array&gt;&lt;/dict&gt;&lt;/plist&gt;</payloads>
</general>
<scope>
<all_mobile_devices>false</all_mobile_devices>
<all_jss_users>false</all_jss_users>
<mobile_devices>
<mobile_device>
<name>$TVDeviceName</name>
</mobile_device>
<mobile_device>
<name>$remoteDeviceName</name>
</mobile_device>
</mobile_devices>
</scope>
</configuration_profile>"
logresult "Generating profile XML." "Failed generating profile XML."
# flatten the XML for the configuration profile to upload to Jamf Pro
flatXML=$( /usr/bin/xmllint --noblanks - <<< "$profileXML" )
logresult "Flattening profile XML for upload." "Failed flattening profile XML for upload."
# upload and create configuration profile
result=$( /usr/bin/curl -s "$URL/JSSResource/mobiledeviceconfigurationprofiles/id/0" \
--write-out "%{http_code}" \
--user "$userName":"$password" \
--header "Content-Type: text/xml" \
--request POST \
--data "$flatXML" )
# evaluate HTTP status code
resultStatus=${result: -3}
[[ $resultStatus = 201 ]] # 201 is successful
logresult "Successfully created configuration profile 'Apple TV Remote Patient - $roomNumber'." "Failed to create configuration profile 'Apple TV Remote Patient - $roomNumber'. HTTP error code: $resultStatus."
done <<< "$assignmentsList"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment