Also, what happens if you enroll and solely use the script to automate the permissions?
I will give that a try and report back. I am going to grab a second laptop that I have that also has this issue and bring it along with me as I setup these new Mac's. Work on it while provisioning... It's so frustrating.

 
I've never come across that message sorry.
At a bare minimum, all you need for all users to observe is the config profile scoped to the device and the enable remote desktop command sent once from Jamf. If that still fails on a freshly enrolled machine then there may be some restriction / policy preventing this from working.

@kwoodard
Ok well this is where we step through line by line, either the copied syntax will be wrong from what I posted or we will quickly find where things have gone wrong in the setup.
Start with copy pasting in your known values for;
encodedCredentials="somethingsoemthing!"
localUserName="username"
jamfpro_server_address="https://soemthing:8443"
machineUUID="findmeinjamfpro"
Then you can paste in the commands to be print on the screen to check their output. Once we know they are ok, re-run that command to store them inside the variable.
eg.
/usr/bin/curl "${jamfpro_server_address}/uapi/auth/tokens" \\
--silent \\
--request POST \\
--header "Authorization: Basic $encodedCredentials"
authToken=$( /usr/bin/curl "${jamfpro_server_address}/uapi/auth/tokens" \\
--silent \\
--request POST \\
--header "Authorization: Basic $encodedCredentials" )
/usr/bin/awk -F \\" '{ print $4 }' <<< "$authToken" | /usr/bin/xargs
token=$( /usr/bin/awk -F \\" '{ print $4 }' <<< "$authToken" | /usr/bin/xargs )
/usr/bin/curl --request GET \\
--url "${jamfpro_server_address}/api/v1/computers-inventory?section=USER_AND_LOCATION&filter=udid%3D%3D%22${machineUUID}%22" \\
--silent \\
--header "Authorization: Bearer $token"
computerrecord=$( /usr/bin/curl --request GET \\
--url "${jamfpro_server_address}/api/v1/computers-inventory?section=USER_AND_LOCATION&filter=udid%3D%3D%22${machineUUID}%22" \\
--silent \\
--header "Authorization: Bearer $token" )
/usr/bin/osascript -l 'JavaScript' -e "JSON.parse(\\`$computerrecord\\`).results[0].id"
computerID=$( /usr/bin/osascript -l 'JavaScript' -e "JSON.parse(\\`$computerrecord\\`).results[0].id" )
And then test the big boss;
/usr/bin/curl --request POST \\
--url "${jamfpro_server_address}/JSSResource/computercommands/command/EnableRemoteDesktop/id/$computerID" \\
--silent \\
--header "Authorization: Bearer $token"
Let us know what you find.
I wasn't able to do line-by-line, but I ran your script exactly as written and this is the results I got... The account I am trying to connect with is micro.
Script result: execution error: Error: TypeError: undefined is not an object (evaluating 'JSON.parse(`{
"httpStatus" : 401,
"errors" : [ ]
}`).results[0]') (-2700)
<html>
<head>
<title>Status page</title>
</head>
<body style="font-family: sans-serif;">
<p style="font-size: 1.2em;font-weight: bold;margin: 1em 0px;">Unauthorized</p>
<p>The request requires user authentication</p>
<p>You can get technical details <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2">here</a>.<br>
Please continue your visit at our <a href="/">home page</a>.
</p>
</body>
</html>setremotelogin: remote login is already On.
Starting...
Stopped ARD Agent.
Removed ARD System Preferences.
Removed ARD Agent Preferences.
Removed Remote Management System Preferences.
Removed remote control privileges for all users.
Done.
Starting...
Setting allow all users to NO.
Done.
Starting...
Activated Remote Management.
Stopped ARD Agent.
micro: Set user remote control privileges.
micro: Set user remote access.
Set the client options.
Done.
Screen sharing ACL members:
basicadminuser.
jamf.
micro.
root.
{
"httpStatus" : 401,
"errors" : [ ]
}
I wasn't able to do line-by-line, but I ran your script exactly as written and this is the results I got... The account I am trying to connect with is micro.
Script result: execution error: Error: TypeError: undefined is not an object (evaluating 'JSON.parse(`{
"httpStatus" : 401,
"errors" : [ ]
}`).results[0]') (-2700)
<html>
<head>
<title>Status page</title>
</head>
<body style="font-family: sans-serif;">
<p style="font-size: 1.2em;font-weight: bold;margin: 1em 0px;">Unauthorized</p>
<p>The request requires user authentication</p>
<p>You can get technical details <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2">here</a>.<br>
Please continue your visit at our <a href="/">home page</a>.
</p>
</body>
</html>setremotelogin: remote login is already On.
Starting...
Stopped ARD Agent.
Removed ARD System Preferences.
Removed ARD Agent Preferences.
Removed Remote Management System Preferences.
Removed remote control privileges for all users.
Done.
Starting...
Setting allow all users to NO.
Done.
Starting...
Activated Remote Management.
Stopped ARD Agent.
micro: Set user remote control privileges.
micro: Set user remote access.
Set the client options.
Done.
Screen sharing ACL members:
basicadminuser.
jamf.
micro.
root.
{
"httpStatus" : 401,
"errors" : [ ]
}
It looks like it's failing when passing the computer id number from Jamf;
computerID=$( /usr/bin/osascript -l 'JavaScript' -e "JSON.parse(\\`$computerrecord\\`).results[0].id" )
Navigate to the device record in Jamf and grab it's Computer ID number. eg. 824
Then add this to the variable and see if the line by line test successfully works after. We can sort the why out later if it's what I think it is.
eg.
computerID="824"
It looks like it's failing when passing the computer id number from Jamf;
computerID=$( /usr/bin/osascript -l 'JavaScript' -e "JSON.parse(\\`$computerrecord\\`).results[0].id" )
Navigate to the device record in Jamf and grab it's Computer ID number. eg. 824
Then add this to the variable and see if the line by line test successfully works after. We can sort the why out later if it's what I think it is.
eg.
computerID="824"
I got the same error when adding in the comuterID manually.
Here is the complete code I am using. It should mirror yours, with the line about computerID changed (I commented the original out).
#!/bin/bash
# B0L ARD Screen Share / Remote Desktop via Jamf Pro API
# - Added bearer token support as Classic API due for retirement
# - Added print of access group (to see who can ARD)
# - Removed hard code of Jamf Pro URL for plist preference
# - Overkill add Jamf Pro into groups / SSH / ScreenShare
# Note: -ShowObserve has no effect as of macOS 12.3
# https://ss64.com/osx/kickstart.html
error=0
jamfbin=$(/usr/bin/which jamf)
jamfpro_server_address=$(/usr/bin/defaults read /Library/Preferences/com.jamfsoftware.jamf jss_url); jamfpro_server_address=${jamfpro_server_address%%/}
localUserName="$4"
encodedCredentials="$5"
group=com.apple.access_screensharing
machineUUID=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk '/IOPlatformUUID/ { gsub(/"/,"",$3); print $3; }')
kickstart="/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart"
privs="-DeleteFiles -ControlObserve -TextMessages -OpenQuitApps -GenerateReports -RestartShutDown -SendFiles -ChangeSettings"
# Old one Liner
# $kickstart -activate -configure -access -on -users user -privs -all -clientopts -setmenuextra -menuextra no -restart -agent -menu
GenerateAuthToken () {
authToken=$( /usr/bin/curl "${jamfpro_server_address}/uapi/auth/tokens" \\
--silent \\
--request POST \\
--header "Authorization: Basic $encodedCredentials" )
token=$( /usr/bin/awk -F \\" '{ print $4 }' <<< "$authToken" | /usr/bin/xargs )
}
ExpireAuthToken () {
/usr/bin/curl "${jamfpro_server_address}/uapi/auth/invalidateToken" \\
--silent \\
--request POST \\
--header "Authorization: Bearer $token"
}
GetJamfProComputerID () {
computerrecord=$( /usr/bin/curl --request GET \\
--url "${jamfpro_server_address}/api/v1/computers-inventory?section=USER_AND_LOCATION&filter=udid%3D%3D%22${machineUUID}%22" \\
--silent \\
--header "Authorization: Bearer $token" )
#computerID=$( /usr/bin/osascript -l 'JavaScript' -e "JSON.parse(\\`$computerrecord\\`).results[0].id" )
computerID="1063"
}
SetJamfProConfig () {
/usr/sbin/dseditgroup -o edit -a "$localUserName" -t user admin
/usr/sbin/dseditgroup -o edit -a "$localUserName" -t user com.apple.access_ssh
/usr/sbin/dseditgroup -o edit -a "$localUserName" -t user com.apple.access_screensharing
/usr/sbin/systemsetup -f -setremotelogin on
$jamfbin startSSH
}
SetAppleRemoteDesktopViaAPI () {
/usr/bin/curl --request POST \\
--url "${jamfpro_server_address}/JSSResource/computercommands/command/EnableRemoteDesktop/id/$computerID" \\
--silent \\
--header "Authorization: Bearer $token"
}
SetAppleRemoteDesktopViaKickstart () {
# https://support.apple.com/en-au/HT201710
/usr/bin/defaults write /Library/Preferences/com.apple.RemoteManagement allowInsecureDH -bool TRUE
$kickstart -targetdisk / -verbose -uninstall -settings -prefs
$kickstart -targetdisk / -verbose -configure -allowAccessFor -specifiedUsers
$kickstart -targetdisk / -activate -configure -access -on -users $localUserName -privs $privs -clientopts -setmenuextra -menuextra no -setwbem -wbem yes -restart -agent -console -menu
}
GetGroupMembership () {
echo "Screen sharing ACL members:";
for i in $(dscl . list /users); do [[ $(id -nG "$i" | grep $group) ]] && echo "$i"". "; done
# $kickstart -computerinfo -1 "$text"
}
GenerateAuthToken
GetJamfProComputerID
SetAppleRemoteDesktopViaAPI
SetJamfProConfig
SetAppleRemoteDesktopViaKickstart
GetGroupMembership
ExpireAuthToken
exit $error
I agree 100%. These little changes have big impacts on workflow. Speaking of @kwoodard and @HappyTrails, have you found a solution?
Did you ever find a way to automate this? I tried multiple ways of the using the scripts in this post and haven't been able to make it work.
I still can’t get my Intel based Macs working. Your script works perfectly on M1 macs.
Well, they did until 12.4… Now nothing on that version work.
Thanks for the screenshot. I had missed the PPPC in these posts. Maybe that's what I'm missing. I never had to use it before. I'll give it a shot.
So how did the scrip look above?
So for specific users, should it look like this?
-users "USER1" "USER2"
Or without quotes?
-users USER1,USER2
12.4 definitely works, can use with or without the quotes. PPC is required to enable ARD so that would be it.
12.4 definitely works, can use with or without the quotes. PPC is required to enable ARD so that would be it.
In my fleet... Not a single computer on 12.4 is working. I get that strange error every time I try to screen share. M1 or Intel, laptop or iMac...makes no difference. If I go to an earlier OS, no problem. The upgrade (?) to 12.4 is breaking every computer.
@Bol , I did the testing you asked about below. No luck.
I got the same error when adding in the comuterID manually.
Here is the complete code I am using. It should mirror yours, with the line about computerID changed (I commented the original out).
#!/bin/bash
# B0L ARD Screen Share / Remote Desktop via Jamf Pro API
# - Added bearer token support as Classic API due for retirement
# - Added print of access group (to see who can ARD)
# - Removed hard code of Jamf Pro URL for plist preference
# - Overkill add Jamf Pro into groups / SSH / ScreenShare
# Note: -ShowObserve has no effect as of macOS 12.3
# https://ss64.com/osx/kickstart.html
error=0
jamfbin=$(/usr/bin/which jamf)
jamfpro_server_address=$(/usr/bin/defaults read /Library/Preferences/com.jamfsoftware.jamf jss_url); jamfpro_server_address=${jamfpro_server_address%%/}
localUserName="$4"
encodedCredentials="$5"
group=com.apple.access_screensharing
machineUUID=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk '/IOPlatformUUID/ { gsub(/"/,"",$3); print $3; }')
kickstart="/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart"
privs="-DeleteFiles -ControlObserve -TextMessages -OpenQuitApps -GenerateReports -RestartShutDown -SendFiles -ChangeSettings"
# Old one Liner
# $kickstart -activate -configure -access -on -users user -privs -all -clientopts -setmenuextra -menuextra no -restart -agent -menu
GenerateAuthToken () {
authToken=$( /usr/bin/curl "${jamfpro_server_address}/uapi/auth/tokens" \\
--silent \\
--request POST \\
--header "Authorization: Basic $encodedCredentials" )
token=$( /usr/bin/awk -F \\" '{ print $4 }' <<< "$authToken" | /usr/bin/xargs )
}
ExpireAuthToken () {
/usr/bin/curl "${jamfpro_server_address}/uapi/auth/invalidateToken" \\
--silent \\
--request POST \\
--header "Authorization: Bearer $token"
}
GetJamfProComputerID () {
computerrecord=$( /usr/bin/curl --request GET \\
--url "${jamfpro_server_address}/api/v1/computers-inventory?section=USER_AND_LOCATION&filter=udid%3D%3D%22${machineUUID}%22" \\
--silent \\
--header "Authorization: Bearer $token" )
#computerID=$( /usr/bin/osascript -l 'JavaScript' -e "JSON.parse(\\`$computerrecord\\`).results[0].id" )
computerID="1063"
}
SetJamfProConfig () {
/usr/sbin/dseditgroup -o edit -a "$localUserName" -t user admin
/usr/sbin/dseditgroup -o edit -a "$localUserName" -t user com.apple.access_ssh
/usr/sbin/dseditgroup -o edit -a "$localUserName" -t user com.apple.access_screensharing
/usr/sbin/systemsetup -f -setremotelogin on
$jamfbin startSSH
}
SetAppleRemoteDesktopViaAPI () {
/usr/bin/curl --request POST \\
--url "${jamfpro_server_address}/JSSResource/computercommands/command/EnableRemoteDesktop/id/$computerID" \\
--silent \\
--header "Authorization: Bearer $token"
}
SetAppleRemoteDesktopViaKickstart () {
# https://support.apple.com/en-au/HT201710
/usr/bin/defaults write /Library/Preferences/com.apple.RemoteManagement allowInsecureDH -bool TRUE
$kickstart -targetdisk / -verbose -uninstall -settings -prefs
$kickstart -targetdisk / -verbose -configure -allowAccessFor -specifiedUsers
$kickstart -targetdisk / -activate -configure -access -on -users $localUserName -privs $privs -clientopts -setmenuextra -menuextra no -setwbem -wbem yes -restart -agent -console -menu
}
GetGroupMembership () {
echo "Screen sharing ACL members:";
for i in $(dscl . list /users); do [[ $(id -nG "$i" | grep $group) ]] && echo "$i"". "; done
# $kickstart -computerinfo -1 "$text"
}
GenerateAuthToken
GetJamfProComputerID
SetAppleRemoteDesktopViaAPI
SetJamfProConfig
SetAppleRemoteDesktopViaKickstart
GetGroupMembership
ExpireAuthToken
exit $error
Ok well that's everything I have done to get my fleet working.
If I was in your situation, I would be starting from scratch;
- Enroll a new machine and exclude all profiles / restrictions apart from these two;


Also if you are using ARD to connect from your machine, remove any reference or saved computer from ARD before trying to connect again.
As of right now, I am able to use ARD or the screen sharing app to connect
In my fleet... Not a single computer on 12.4 is working. I get that strange error every time I try to screen share. M1 or Intel, laptop or iMac...makes no difference. If I go to an earlier OS, no problem. The upgrade (?) to 12.4 is breaking every computer.
@Bol , I did the testing you asked about below. No luck.
@kwoodard You beat me to it, i replied to your post!
In my fleet... Not a single computer on 12.4 is working. I get that strange error every time I try to screen share. M1 or Intel, laptop or iMac...makes no difference. If I go to an earlier OS, no problem. The upgrade (?) to 12.4 is breaking every computer.
@Bol , I did the testing you asked about below. No luck.
@kwoodard While I was testing on the weekend i did notice something I had forgotten. Any computers below macos 11+ eg. 10.15, their sharing preference pane for remote management shows the correct radio buttons and users. It was definitely a cosmetic issue on macos 11+ that they only show all users and the people listed.
I have several mac mini's (intel & m1) on 12.4 and they are ok. Very strange!
@HappyTrails @kwoodard
I went back and test, I believe only the PPPC profile was required for ARD. I couldn't find all the docs but from what I understand;
- Kickstart to setup privileges & users
- MDM / API to enable remote desktop
- Config profile to allow interaction of remote management via kickstart
Here's what I'm using in a policy triggered on startup, it will get applied soon after enrolment and can connect straight after. Please test before copy / pasting in your environment as I know there's some overkill elements to what I'm doing.
There was a lot of testing at the time and once it was all solid, i didn't get the chance to go back through and see what wasn't required. Also I removed the config profile and it did indeed break the workflow, so for me it was still a required step.
You can replace $4 / $5 with your own values, I enter these on the policy the script it added too.

#!/bin/bash
# B0L ARD Screen Share / Remote Desktop via Jamf Pro API
# - Added bearer token support as Classic API due for retirement
# - Added print of access group (to see who can ARD)
# - Removed hard code of Jamf Pro URL for plist preference
# - Overkill add Jamf Pro into groups / SSH / ScreenShare
# Note: -ShowObserve has no effect as of macOS 12.3
# https://ss64.com/osx/kickstart.html
error=0
jamfbin=$(/usr/bin/which jamf)
jamfpro_server_address=$(/usr/bin/defaults read /Library/Preferences/com.jamfsoftware.jamf jss_url); jamfpro_server_address=${jamfpro_server_address%%/}
encodedCredentials="$4"
localUserName="$5"
group=com.apple.access_screensharing
machineUUID=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk '/IOPlatformUUID/ { gsub(/"/,"",$3); print $3; }')
kickstart="/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart"
privs="-DeleteFiles -ControlObserve -TextMessages -OpenQuitApps -GenerateReports -RestartShutDown -SendFiles -ChangeSettings"
# Old one Liner
# $kickstart -activate -configure -access -on -users user -privs -all -clientopts -setmenuextra -menuextra no -restart -agent -menu
GenerateAuthToken () {
authToken=$( /usr/bin/curl "${jamfpro_server_address}/uapi/auth/tokens" \\
--silent \\
--request POST \\
--header "Authorization: Basic $encodedCredentials" )
token=$( /usr/bin/awk -F \\" '{ print $4 }' <<< "$authToken" | /usr/bin/xargs )
}
ExpireAuthToken () {
/usr/bin/curl "${jamfpro_server_address}/uapi/auth/invalidateToken" \\
--silent \\
--request POST \\
--header "Authorization: Bearer $token"
}
GetJamfProComputerID () {
computerrecord=$( /usr/bin/curl --request GET \\
--url "${jamfpro_server_address}/api/v1/computers-inventory?section=USER_AND_LOCATION&filter=udid%3D%3D%22${machineUUID}%22" \\
--silent \\
--header "Authorization: Bearer $token" )
computerID=$( /usr/bin/osascript -l 'JavaScript' -e "JSON.parse(\\`$computerrecord\\`).results[0].id" )
}
SetJamfProConfig () {
/usr/sbin/dseditgroup -o edit -a "$localUserName" -t user admin
/usr/sbin/dseditgroup -o edit -a "$localUserName" -t user com.apple.access_ssh
/usr/sbin/dseditgroup -o edit -a "$localUserName" -t user com.apple.access_screensharing
/usr/sbin/systemsetup -f -setremotelogin on
$jamfbin startSSH
}
SetAppleRemoteDesktopViaAPI () {
/usr/bin/curl --request POST \\
--url "${jamfpro_server_address}/JSSResource/computercommands/command/EnableRemoteDesktop/id/$computerID" \\
--silent \\
--header "Authorization: Bearer $token"
}
SetAppleRemoteDesktopViaKickstart () {
# https://support.apple.com/en-au/HT201710
/usr/bin/defaults write /Library/Preferences/com.apple.RemoteManagement allowInsecureDH -bool TRUE
$kickstart -targetdisk / -verbose -uninstall -settings -prefs
$kickstart -targetdisk / -verbose -configure -allowAccessFor -specifiedUsers
$kickstart -targetdisk / -activate -configure -access -on -users $localUserName -privs $privs -clientopts -setmenuextra -menuextra no -setwbem -wbem yes -restart -agent -console -menu
}
GetGroupMembership () {
echo "Screen sharing ACL members:";
for i in $(dscl . list /users); do [[ $(id -nG "$i" | grep $group) ]] && echo "$i"". "; done
# $kickstart -computerinfo -1 "$text"
}
GenerateAuthToken
GetJamfProComputerID
SetAppleRemoteDesktopViaAPI
SetJamfProConfig
SetAppleRemoteDesktopViaKickstart
GetGroupMembership
ExpireAuthToken
exit $error
ps. How do we format code script for bash!?
@Bol You are an absolute legend! Thank you for spending so much time and effort providing us with your workflows and information. Leveraging the plist to generate the jamf pro server address is a stroke of genius.
I am VERY new to JAMF administration, I apologize in advance for any dumb questions. I am having trouble wrapping my head around your script and where to plug-in my org's variables.
I want to implement 1 local user to be able to use remote management through ARD (we'll call it ARDuser).
And we have a JAMF specific api user (we'll call it APIuser) to be able to make calls to the API. I am having trouble figuring out where to plug this in as well.
is
encodedCredentials="$4"
Where you put in the API user? If so, where does the password go? I know the classic API's plain text passwords are getting phased-out, but how does the API-user authenticate to the JAMF Pro API without inputting the password somewhere? Something about this concept is not clicking for me with the bearer tokens/ auth tokens.
and is
localUserName="$5"
The user who will have ARD access to the remote computers?
We could probably have a teach piece for our helpdesk to walk through the enabling ARD through the JAMF commands, but it would be nice if we could get it going during the enrollment process.
Thank you again!
@Bol You are an absolute legend! Thank you for spending so much time and effort providing us with your workflows and information. Leveraging the plist to generate the jamf pro server address is a stroke of genius.
I am VERY new to JAMF administration, I apologize in advance for any dumb questions. I am having trouble wrapping my head around your script and where to plug-in my org's variables.
I want to implement 1 local user to be able to use remote management through ARD (we'll call it ARDuser).
And we have a JAMF specific api user (we'll call it APIuser) to be able to make calls to the API. I am having trouble figuring out where to plug this in as well.
is
encodedCredentials="$4"
Where you put in the API user? If so, where does the password go? I know the classic API's plain text passwords are getting phased-out, but how does the API-user authenticate to the JAMF Pro API without inputting the password somewhere? Something about this concept is not clicking for me with the bearer tokens/ auth tokens.
and is
localUserName="$5"
The user who will have ARD access to the remote computers?
We could probably have a teach piece for our helpdesk to walk through the enabling ARD through the JAMF commands, but it would be nice if we could get it going during the enrollment process.
Thank you again!
@kbreed27
Thank you very much for mentioning that, it's much appreciated.
Firstly, I have only borrowed the genius thoughts of some of the other community brains
eg. Jamf Pro Server Address via Plist is thanks to the Der Flounder blog. Again, many thanks!
You seem to have a good grasp on what is happening with the api calls in Jamf and really, if you take out the move to bearer tokens, you can get away with a single line command to turn on remote access for all users (using your api username as an example)
/usr/bin/curl -s -u ARDuser:$apiPass https://yourmdm.com:8443/JSSResource/computercommands/command/EnableRemoteDesktop/id/2327 -X POST
Perhaps try that command first and ensure it;
1. Enables remote access and you see this become enabled in the computer object in Jamf
2. Proves your api account has the correct access to then move on using bearer token as opposed to the classic api calls.
You should be able to set who and what privileges have access to remote management via the kickstart command.
@kbreed27
Thank you very much for mentioning that, it's much appreciated.
Firstly, I have only borrowed the genius thoughts of some of the other community brains
eg. Jamf Pro Server Address via Plist is thanks to the Der Flounder blog. Again, many thanks!
You seem to have a good grasp on what is happening with the api calls in Jamf and really, if you take out the move to bearer tokens, you can get away with a single line command to turn on remote access for all users (using your api username as an example)
/usr/bin/curl -s -u ARDuser:$apiPass https://yourmdm.com:8443/JSSResource/computercommands/command/EnableRemoteDesktop/id/2327 -X POST
Perhaps try that command first and ensure it;
1. Enables remote access and you see this become enabled in the computer object in Jamf
2. Proves your api account has the correct access to then move on using bearer token as opposed to the classic api calls.
You should be able to set who and what privileges have access to remote management via the kickstart command.
@Bol
So it does look like my API user is good to go! Using the above script in your reply enabled ARD for all users on my test Bench when I manually specified the Computer ID#.
When I try to incorporate all of my variables into your monster of a script, I keep getting JSON parse error. I think it's having trouble pulling the computer ID to drop in the call to the API. I'm going to keep playing with it, but maybe you had some tips?
Again, thank you for being so helpful to us JAMF Newbz.
Output from Jamf Pro:
Executing Policy testing ARD issue with black screen
Running script Restart ARD services Test...
Script exit code: 0
Script result: execution error: Error: SyntaxError: JSON Parse error:
Unexpected EOF (-2700)
setremotelogin: remote login is already On.
Starting...
Removed ARD Agent Preferences.
Removed Remote Management System Preferences.
Removed remote control privileges for all users.
Done.
Starting...
Setting allow all users to NO.
Done.
Starting...
[31mScreen recording might be disabled. Screen Sharing or
Remote Management must be enabled from System Preferences
or via MDM.
[0m[31mScreen control might be disabled. Screen Sharing or
Remote Management must be enabled from System Preferences
or via MDM.
[OmActivated Remote Management.
Stopped ARD Agent.
hadmin: Set user remote control privileges.
hadmin: Set user remote access.
Set the client options.
Restarted Menu Extra (System UI Server).
Done.
Screen sharing ACL members:
hadmin.
root.
teacher.
@Bol
So it does look like my API user is good to go! Using the above script in your reply enabled ARD for all users on my test Bench when I manually specified the Computer ID#.
When I try to incorporate all of my variables into your monster of a script, I keep getting JSON parse error. I think it's having trouble pulling the computer ID to drop in the call to the API. I'm going to keep playing with it, but maybe you had some tips?
Again, thank you for being so helpful to us JAMF Newbz.
Output from Jamf Pro:
Executing Policy testing ARD issue with black screen
Running script Restart ARD services Test...
Script exit code: 0
Script result: execution error: Error: SyntaxError: JSON Parse error:
Unexpected EOF (-2700)
setremotelogin: remote login is already On.
Starting...
Removed ARD Agent Preferences.
Removed Remote Management System Preferences.
Removed remote control privileges for all users.
Done.
Starting...
Setting allow all users to NO.
Done.
Starting...
[31mScreen recording might be disabled. Screen Sharing or
Remote Management must be enabled from System Preferences
or via MDM.
[0m[31mScreen control might be disabled. Screen Sharing or
Remote Management must be enabled from System Preferences
or via MDM.
[OmActivated Remote Management.
Stopped ARD Agent.
hadmin: Set user remote control privileges.
hadmin: Set user remote access.
Set the client options.
Restarted Menu Extra (System UI Server).
Done.
Screen sharing ACL members:
hadmin.
root.
teacher.
I have that same issue. I recently switched over to Jamf Cloud and noticed (while working with a Jamf engineer) that there can be lag. In a few of my scripts, I had to incorporate some sleep commands in the script to allow AWS to catch up. I wonder if that needs to happen here.
@Bol
So it does look like my API user is good to go! Using the above script in your reply enabled ARD for all users on my test Bench when I manually specified the Computer ID#.
When I try to incorporate all of my variables into your monster of a script, I keep getting JSON parse error. I think it's having trouble pulling the computer ID to drop in the call to the API. I'm going to keep playing with it, but maybe you had some tips?
Again, thank you for being so helpful to us JAMF Newbz.
Output from Jamf Pro:
Executing Policy testing ARD issue with black screen
Running script Restart ARD services Test...
Script exit code: 0
Script result: execution error: Error: SyntaxError: JSON Parse error:
Unexpected EOF (-2700)
setremotelogin: remote login is already On.
Starting...
Removed ARD Agent Preferences.
Removed Remote Management System Preferences.
Removed remote control privileges for all users.
Done.
Starting...
Setting allow all users to NO.
Done.
Starting...
[31mScreen recording might be disabled. Screen Sharing or
Remote Management must be enabled from System Preferences
or via MDM.
[0m[31mScreen control might be disabled. Screen Sharing or
Remote Management must be enabled from System Preferences
or via MDM.
[OmActivated Remote Management.
Stopped ARD Agent.
hadmin: Set user remote control privileges.
hadmin: Set user remote access.
Set the client options.
Restarted Menu Extra (System UI Server).
Done.
Screen sharing ACL members:
hadmin.
root.
teacher.
@kbreed27
Sorry, that's my bad. I forgot using the older api you can easily find the id of the computer by adding in the serial;
serial=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk -F'"' '/IOPlatformSerialNumber/{print $4}')
Then api call for the computer ID;
computerID=$(/usr/bin/curl -u "$apiuser":"$apipass" "$jssurl":8443/JSSResource/computers/serialnumber/"$serial" -H "accept: text/xml" | /usr/bin/xpath "/computer[1]/general/id/text()")
You don't have to use the monster script, in the beginning, I only had the kickstart one liner then I added the api ard call. That was it.
@kbreed27
Sorry, that's my bad. I forgot using the older api you can easily find the id of the computer by adding in the serial;
serial=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk -F'"' '/IOPlatformSerialNumber/{print $4}')
Then api call for the computer ID;
computerID=$(/usr/bin/curl -u "$apiuser":"$apipass" "$jssurl":8443/JSSResource/computers/serialnumber/"$serial" -H "accept: text/xml" | /usr/bin/xpath "/computer[1]/general/id/text()")
You don't have to use the monster script, in the beginning, I only had the kickstart one liner then I added the api ard call. That was it.
You can then remove the line you have commented out, plus the one where you declare the id underneath it.
You can then remove the line you have commented out, plus the one where you declare the id underneath it.
@Bol
Oh man, I think I (we, really) am so close. Something about the xpath part of the computer ID line is not working properly to isolate the computer ID#.
I did a bit of testing with echoing the variables because I wasn't getting the script to work all together.
If I echo the computerID variable without the xpath part of the line, it just dumps the entire contents of the XML file into the terminal. I get an error once the xpath command is put back in.
With this script:
#!/bin/bash
apiuser=myValue
apipass=myValue
jssurl=https://myValue
serial=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk -F'"' '/IOPlatformSerialNumber/{print $4}')
computerID=$(/usr/bin/curl -u $apiuser:$apipass $jssurl:8443/JSSResource/computers/serialnumber/$serial -H "accept: text/xml")
echo $computerID
It spits out the entire contents of that XML page in the terminal.
When i put back in the xpath I get this:
#!/bin/bash
apiuser=myValue
apipass=myValue
jssurl=https://myValue
serial=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk -F'"' '/IOPlatformSerialNumber/{print $4}')
computerID=$(/usr/bin/curl -u $apiuser:$apipass $jssurl:8443/JSSResource/computers/serialnumber/$serial -H "accept: text/xml" | /usr/bin/xpath "/computer/general/id/text()")
echo $computerID
terminal error/output:
Executing Policy testing ARD issue with black screen
Running script Restart ARD services Test...
Script exit code: 0
Script result:
% Total
% Received % Xferd Average Speed
Time
Time
Time Current
Dload Upload
Total
Spent
Left Speed
0
0
0
0
0 --:--:--
/usr/bin/xpath5.30 [options] -e query [-e query...] [filename...]
OUsage:
If no filenames are given, supply XML on STDIN. You must provide at
least one query. Each supplementary query is done in order, the
previous query giving the context of the next one.
Options:
-q quiet, only output the resulting PATH.
-S suffix, use suffix instead of linefeed.
-p postfix, use prefix instead of nothing.
-n Don't use an external DTD.
100 15900
0 15900
0
0
118k
0
--:--:-- --:--:--
126 k
curl: (23) Failure writing output to destination
I can see the ID number in the XML file through the terminal and if it's accessed through the browser as well, but it won't seem to isolate that ID value through the command.
@Bol
Oh man, I think I (we, really) am so close. Something about the xpath part of the computer ID line is not working properly to isolate the computer ID#.
I did a bit of testing with echoing the variables because I wasn't getting the script to work all together.
If I echo the computerID variable without the xpath part of the line, it just dumps the entire contents of the XML file into the terminal. I get an error once the xpath command is put back in.
With this script:
#!/bin/bash
apiuser=myValue
apipass=myValue
jssurl=https://myValue
serial=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk -F'"' '/IOPlatformSerialNumber/{print $4}')
computerID=$(/usr/bin/curl -u $apiuser:$apipass $jssurl:8443/JSSResource/computers/serialnumber/$serial -H "accept: text/xml")
echo $computerID
It spits out the entire contents of that XML page in the terminal.
When i put back in the xpath I get this:
#!/bin/bash
apiuser=myValue
apipass=myValue
jssurl=https://myValue
serial=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk -F'"' '/IOPlatformSerialNumber/{print $4}')
computerID=$(/usr/bin/curl -u $apiuser:$apipass $jssurl:8443/JSSResource/computers/serialnumber/$serial -H "accept: text/xml" | /usr/bin/xpath "/computer/general/id/text()")
echo $computerID
terminal error/output:
Executing Policy testing ARD issue with black screen
Running script Restart ARD services Test...
Script exit code: 0
Script result:
% Total
% Received % Xferd Average Speed
Time
Time
Time Current
Dload Upload
Total
Spent
Left Speed
0
0
0
0
0 --:--:--
/usr/bin/xpath5.30 [options] -e query [-e query...] [filename...]
OUsage:
If no filenames are given, supply XML on STDIN. You must provide at
least one query. Each supplementary query is done in order, the
previous query giving the context of the next one.
Options:
-q quiet, only output the resulting PATH.
-S suffix, use suffix instead of linefeed.
-p postfix, use prefix instead of nothing.
-n Don't use an external DTD.
100 15900
0 15900
0
0
118k
0
--:--:-- --:--:--
126 k
curl: (23) Failure writing output to destination
I can see the ID number in the XML file through the terminal and if it's accessed through the browser as well, but it won't seem to isolate that ID value through the command.
@kbreed27 Oh man, so close! Try adding the following option to xpath as below, I've just test with the same variable names you have used and it works.
computerID=$(/usr/bin/curl -u $apiuser:$apipass $jssurl/JSSResource/computers/serialnumber/$serial -H "accept: text/xml" | /usr/bin/xpath -e "/computer/general/id/text()")
@kbreed27 Oh man, so close! Try adding the following option to xpath as below, I've just test with the same variable names you have used and it works.
computerID=$(/usr/bin/curl -u $apiuser:$apipass $jssurl/JSSResource/computers/serialnumber/$serial -H "accept: text/xml" | /usr/bin/xpath -e "/computer/general/id/text()")
@Bol Huzzah! That was it. If you are ever in the DFW area I owe you a coffee, man.
Just as a follow-up. Since my script doesn't include the encoded credentials or the bearer token stuff, am I basically staring down this policy going by the way-side once they deprecate the classic API? I think I read that is slated for any time from August to the end of the year.
And I guess is there no way to leverage the Serial number with the Auth/Bearer Tokens?
For reference to anyone, this is my script working in my environment:
#!/bin/bash
apiuser=yourJamfApiUser
apipass=yourJamfAPIPass
jssurl=https://yourJamfUrl.com
kickstart="/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart"
localUserName=yourLocalAdminName
privs="-DeleteFiles -ControlObserve -TextMessages -OpenQuitApps -GenerateReports -RestartShutDown -SendFiles -ChangeSettings"
serial=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk -F'"' '/IOPlatformSerialNumber/{print $4}')
computerID=$(/usr/bin/curl -u $apiuser:$apipass $jssurl:8443/JSSResource/computers/serialnumber/$serial -H "accept: text/xml" | /usr/bin/xpath -e "/computer/general/id/text()")
/usr/bin/curl -s -u $apiuser:$apipass $jssurl:8443/JSSResource/computercommands/command/EnableRemoteDesktop/id/$computerID -X POST
/usr/bin/defaults write /Library/Preferences/com.apple.RemoteManagement allowInsecureDH -bool TRUE
$kickstart -targetdisk / -verbose -uninstall -settings -prefs
$kickstart -targetdisk / -verbose -configure -allowAccessFor -specifiedUsers
$kickstart -targetdisk / -activate -configure -access -on -users $localUserName -privs $privs -clientopts -setmenuextra -menuextra no -setwbem -wbem yes -restart -agent -console -menu
@Bol Huzzah! That was it. If you are ever in the DFW area I owe you a coffee, man.
Just as a follow-up. Since my script doesn't include the encoded credentials or the bearer token stuff, am I basically staring down this policy going by the way-side once they deprecate the classic API? I think I read that is slated for any time from August to the end of the year.
And I guess is there no way to leverage the Serial number with the Auth/Bearer Tokens?
For reference to anyone, this is my script working in my environment:
#!/bin/bash
apiuser=yourJamfApiUser
apipass=yourJamfAPIPass
jssurl=https://yourJamfUrl.com
kickstart="/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart"
localUserName=yourLocalAdminName
privs="-DeleteFiles -ControlObserve -TextMessages -OpenQuitApps -GenerateReports -RestartShutDown -SendFiles -ChangeSettings"
serial=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk -F'"' '/IOPlatformSerialNumber/{print $4}')
computerID=$(/usr/bin/curl -u $apiuser:$apipass $jssurl:8443/JSSResource/computers/serialnumber/$serial -H "accept: text/xml" | /usr/bin/xpath -e "/computer/general/id/text()")
/usr/bin/curl -s -u $apiuser:$apipass $jssurl:8443/JSSResource/computercommands/command/EnableRemoteDesktop/id/$computerID -X POST
/usr/bin/defaults write /Library/Preferences/com.apple.RemoteManagement allowInsecureDH -bool TRUE
$kickstart -targetdisk / -verbose -uninstall -settings -prefs
$kickstart -targetdisk / -verbose -configure -allowAccessFor -specifiedUsers
$kickstart -targetdisk / -activate -configure -access -on -users $localUserName -privs $privs -clientopts -setmenuextra -menuextra no -setwbem -wbem yes -restart -agent -console -menu
@kbreed27 Nice one!!!
I wish mate, I'm down under right now but hey, that's my first coffee kudo so I appreciate that :D
Not sure of the cut off date but it's optional now keeping classic going. Check here for all the commands and whats possible plus I think the new api isn't yet matching all the previously available commands from what I understand..
https://developer.jamf.com/jamf-pro/reference/jamf-pro-api
This is great reading also from Mr Purves, getting a handle on the newer token setup
https://richard-purves.com/2021/12/09/jamf-pro-api-for-fun-and-profit/
Well, I discovered a very strange work around for the issues I have been seeing. If I uncheck remote management, check "Screen Sharing and select all users" then check remote management again, and reselect all the options...I can connect with ARD. So strange.
I was recently able to get this working in Jamf Pro, and wanted to add a couple notes for anyone looking to enable Remote Management via script in the future.
First, thank you @Bol for providing your script! It was very helpful as a basis to set this up in our environment. However, some tweaks were required to get it to work. My notes are below.
- With Basic authentication being deprecated later this year, we decided to use the latest getBearerToken and invalidateToken functions instead. The latest bearer token functions can be found here: https://developer.jamf.com/jamf-pro/recipes
- The new getBearerToken and invalidateToken functions require login credentials for a user in Jamf Pro. An API account will need to be created for this purpose. While no account permissions are required to get a token or invalidate a token, some permissions are required to enable Remote Management using this script. The minimum required permissions are as follows: Create Computers, Read Computers, and Send Computer Remote Desktop Command
- When we tested deploying this policy to M1 Macs running Monterey, the SetAppleRemoteDesktopViaKickstart function used in conjunction with the SetRemoteDesktopViaAPI function did not allow VNC connections. It did work properly if we unchecked then checked Remote Management. By removing the SetAppleRemoteDesktopViaKickstart function from the script, Remote Management was properly enabled from the API, and we were able to connect via VNC without issue. @kwoodard Try removing the SetAppleRemoteDesktopViaKickstart function and see if that solves your problem.
I hope this helps! Thanks again to everyone in this thread for taking the time to help get this set up for others!
I was recently able to get this working in Jamf Pro, and wanted to add a couple notes for anyone looking to enable Remote Management via script in the future.
First, thank you @Bol for providing your script! It was very helpful as a basis to set this up in our environment. However, some tweaks were required to get it to work. My notes are below.
- With Basic authentication being deprecated later this year, we decided to use the latest getBearerToken and invalidateToken functions instead. The latest bearer token functions can be found here: https://developer.jamf.com/jamf-pro/recipes
- The new getBearerToken and invalidateToken functions require login credentials for a user in Jamf Pro. An API account will need to be created for this purpose. While no account permissions are required to get a token or invalidate a token, some permissions are required to enable Remote Management using this script. The minimum required permissions are as follows: Create Computers, Read Computers, and Send Computer Remote Desktop Command
- When we tested deploying this policy to M1 Macs running Monterey, the SetAppleRemoteDesktopViaKickstart function used in conjunction with the SetRemoteDesktopViaAPI function did not allow VNC connections. It did work properly if we unchecked then checked Remote Management. By removing the SetAppleRemoteDesktopViaKickstart function from the script, Remote Management was properly enabled from the API, and we were able to connect via VNC without issue. @kwoodard Try removing the SetAppleRemoteDesktopViaKickstart function and see if that solves your problem.
I hope this helps! Thanks again to everyone in this thread for taking the time to help get this set up for others!
Care to share your script? Would love to give it a try in my environment.