Posted on 01-29-2020 09:40 AM
Has anyone successfully deployed the following script to add a computer to a static group. Goal: Have buttons in Self Service to add a computer to a static group.
$4 is the group ID.
#!/bin/sh
#API login info
apiuser="apiaccount"
apipass='apiaccountpassword'
jamfProURL="https://myjamfinstance.jamfcloud.com"
ComputerName=$(hostname)
#Group to update
GroupID="$4"
apiURL="JSSResource/computergroups/id/${GroupID}"
#XML header stuff
xmlHeader="<?xml version="1.0" encoding="UTF-8" standalone="no"?>"
apiData="<computer_group><id>${GroupID}</id><name>Whatever the GroupName Is</name><computer_additions><computer><name>$ComputerName</name></computer></computer_additions></computer_group>"
curl -sSkiu ${apiuser}:${apipass} "${jamfProURL}/${apiURL}"
-H "Content-Type: text/xml"
-d "${xmlHeader}${apiData}"
-X PUT > /dev/null
Posted on 01-29-2020 12:15 PM
Just out of curiosity why wouldn't a Smart Group work for the scope of what you're trying to accomplish?
Posted on 01-29-2020 12:23 PM
I have a goal of phasing this out in hopes of using a drop down extension attribute instead. But we do currently do this.
It has a few preset parameters:
$4 = Group ID#
$5 = 'additions' or 'deletions'
It has to be just either of those strings with no quotes, or this won't function. This will control if it adds the computer or deletes the computer from the group.
$6 = APIUserName
$7 = APIPassword
if API username and Password are not given it will prompt the user for the JSS ID and Password.
$8 = Silent
anystring will make this run silent. If this is left blank then the user will get an alert of success or failure joining the group.
#! /bin/bash
jamfproURL="https://yoururlhere.jamfcloud.com"
default_group="856"
computer_name="$2"
current_user="$3"
silent="$8"
if [ -z $4 ]
then
groupid="$default_group"
else
groupid="$4"
fi
if [ -z $5 ]
then
action="additions"
else
action="$5"
fi
if [ -z $6 ]
then
APIUser=$(/usr/bin/osascript<<END
tell application "System Events"
activate
set the answer to text returned of (display dialog "Please enter your Jamf Username:" default answer "" buttons {"Continue"} default button 1)
end tell
END)
else
APIUser="$6"
fi
if [ -z $7 ]
then
APIPass=$(/usr/bin/osascript<<END
tell application "System Events"
activate
set the answer to text returned of (display dialog "Please enter your Jamf Password:" default answer "" with hidden answer buttons {"Continue"} default button 1)
end tell
END)
else
APIPass="$7"
fi
xml="<computer_group><computer_${action}><computer><name>$computer_name</name></computer></computer_${action}></computer_group>"
fullURL="${jamfproURL}/JSSResource/computergroups/id/${groupid}"
echo "Created XML"
echo $xml
echo "Jamf API URL"
echo $fullURL
result=$`curl "$fullURL" -u "$APIUser:$APIPass" -H "Content-Type: text/xml" -X PUT -d "$xml"`
echo "result"
echo "$result"
if [ -z $silent ] ; then
if [[ "$result" == *"<p>The request requires user authentication</p>"* ]] ; then
echo "Showing Fail message"
/usr/bin/osascript -e 'tell app "System Events" to display dialog "Failed to update Static Group. Please check your network connection and try again."'
else
echo "Showing success message"
dialog="${action} for the Static Group probably successful."
cmd="Tell app "System Events" to display dialog "$dialog""
/usr/bin/osascript -e "$cmd"
fi
else
echo "running silent No user notifications"
fi
exit 0
Posted on 01-29-2020 12:44 PM
This may be more than you bargained:
#!/bin/bash
# While static groups within JAMF PRO are typically thought of as
# less-uesful than their more dynamic counterparts known as smart
# groups, I have found they still serve a critical role. This is
# especially so for those who extract the most from JAMF PRO via a
# series of API scripts. Those API script often return a list of
# computer IDs or names. But those lists usually need to be acted
# upon in some way. Being able to easily create a static group within
# JAMF PRO can make that happen.
# That is why I wrote this script. It allows for the quick creation
# and/or re-population of a static group based on a string of computer
# IDs or names
# Author: Andrew Thomson
# Date: 02-10-2017
# GitHub: https://github.com/thomsontown
# Version: 1.02 (12-11-2019)
# uncomment to override variables
# JSS_USER=""
# JSS_PASSWORD=""
# JSS_AUTH=""
function addGroupMembers() {
local GROUP_ID="$1"
local GROUP_NAME="$2"
local COUNT=1
# create opening xml for replacing members of the static group
XML_COMPUTER_TEMPLATE="<computer_group><id>$GROUP_ID</id><name>$GROUP_NAME</name><computers>"
# enumerate computers to re-populate static group
for COMPUTER in ${COMPUTERS[@]}; do
progressBar "${#COMPUTERS[@]}" "$((COUNT++))"
# derermine if computer id (integer) or name (alpha) was provided
if isInteger "$COMPUTER"; then
XML_COMPUTER=$(/usr/bin/curl -X GET -H "Content-Type: application/xml" -H "Authorization: Basic $JSS_AUTH" -s "${JSS_URL%/}/JSSResource/computers/id/$COMPUTER/subset/general" 2> /dev/null)
COMPUTER_NAME=$(echo $XML_COMPUTER | /usr/bin/xpath "/computer/general/name/text()" 2> /dev/null)
COMPUTER_SN=$(echo $XML_COMPUTER | /usr/bin/xpath "/computer/general/serial_number/text()" 2> /dev/null)
COMPUTER_ID="$COMPUTER"
else
XML_COMPUTER=$(/usr/bin/curl -X GET -H "Content-Type: application/xml" -H "Authorization: Basic $JSS_AUTH" -s "${JSS_URL%/}/JSSResource/computers/name/$COMPUTER/subset/general" 2> /dev/null)
COMPUTER_ID=$(echo $XML_COMPUTER | /usr/bin/xpath "/computer/general/id/text()" 2> /dev/null)
COMPUTER_SN=$(echo $XML_COMPUTER | /usr/bin/xpath "/computer/general/serial_number/text()" 2> /dev/null)
COMPUTER_NAME="$COMPUTER"
COMPUTER_NAME=$(encodeUrl "$COMPUTER_NAME")
fi
# verify computer details were found
if [ -z "$COMPUTER_SN" ] || [ -z "$COMPUTER_ID" ] || [ -z "$COMPUTER_NAME" ]; then
echo -e "
ERROR: Unable to retrieve info for computer [$COMPUTER]." >&2
continue
fi
# insert xml requied for each computer be a member of the static group
XML_COMPUTER_TEMPLATE+="<computer><id>$COMPUTER_ID</id><name>$COMPUTER_NAME</name><serial_number>$COMPUTER_SN</serial_number></computer>"
done
# close out the xml for re-populating members of the static group
XML_COMPUTER_TEMPLATE+="</computers></computer_group>"
# verify xml formatting before submitting
if ! XML_COMPUTER_TEMPLATE=$(echo $XML_COMPUTER_TEMPLATE | /usr/bin/xmllint --format -); then
echo "ERROR: Imporperly formatted data structure found." >&2
return $LINENO
fi
# upload xml to re-populate the computers in the static group
HTTP_CODE=$(/usr/bin/curl -X PUT -H "Content-Type: application/xml" -w "%{http_code}" -H "Authorization: Basic $JSS_AUTH" -d "$XML_COMPUTER_TEMPLATE" -o /dev/null -s "${JSS_URL%/}/JSSResource/computergroups/id/$GROUP_ID" 2> /dev/null)
if [ "$HTTP_CODE" -ne "201" ]; then
echo "ERROR: Unable to replace computers in static group." >&2
return $LINENO
fi
}
function createStaticGroup() {
# $1 = Name of static group to create. (My Amazing Group)
local GROUP_NAME="$1"
# query jss for existing group name to get id
GROUP_ID=$(/usr/bin/curl -X GET -H "Accept: application/xml" -H "Authorization: Basic $JSS_AUTH" -s "${JSS_URL%/}/JSSResource/computergroups/name/$GROUP_NAME" | /usr/bin/xpath "//computer_group/id/text()" 2> /dev/null)
# create new group if no existing one can be found
if [ -z "$GROUP_ID" ]; then
# minimal xml required to create static group
XML_GROUP_TEMPLATE="<computer_group><id>0</id><name>$GROUP_NAME</name><is_smart>false</is_smart></computer_group>"
# upload xml to create static group
GROUP_ID=$(/usr/bin/curl -X POST -H "Content-Type: application/xml" -H "Authorization: Basic $JSS_AUTH" -d "${XML_GROUP_TEMPLATE}" -s "${JSS_URL%/}/JSSResource/computergroups/id/0" | /usr/bin/xpath "//computer_group/id/text()" 2> /dev/null)
# display error or return group id
if [ -z "$GROUP_ID" ]; then
echo "ERROR: Unable to create JSS computer group." >&2
return $LINENO
fi
fi
echo "$GROUP_ID"
return 0
}
function encodeBasicAuthorization() {
# $1 = User name for JSS query. (jsmith)
# $2 = Password for JSS query. (itisasecret)
local USERNAME="$1"
local PASSWORD="$2"
if [ -z "$USERNAME" ] || [ -z "$PASSWORD" ]; then
writeLog "ERROR: Missing parameter(s)." >&2
return $LINENO
fi
if ! AUTHORIZATION=$(/usr/bin/printf "$USERNAME:$PASSWORD" | /usr/bin/iconv -t ISO-8859-1 2> /dev/null | /usr/bin/base64 -i - 2> /dev/null); then
writeLog "ERROR: Unable to encode authorization credentials [$?]." >&2
return $LINENO
else
echo "$AUTHORIZATION"
return 0
fi
}
function encodeUrl() {
# $1 = Universal Resource Locator to be encoded. (https://www.company.com/some/path/index.htm)
local URL="$1"
local PREFIX=$(echo $URL | /usr/bin/grep -Eoi "^(afp|file|ftp|http|https|smb)://" 2> /dev/null)
local LENGTH=${#PREFIX}
local SUFFIX=${URL:$LENGTH}
local ENCODED=""
if [ -z "$SUFFIX" ]; then
echo "ERROR: Specified URL is incomplete."
return $LINENO
fi
while [ -n "$SUFFIX" ]; do
TAIL=${SUFFIX#?}
HEAD=${SUFFIX%$TAIL}
case $HEAD in
[-._~0-9A-Za-z/:]) ENCODED+=$(/usr/bin/printf %c "$HEAD");; # encoding not required
*) ENCODED+=$(/usr/bin/printf %%%02x "'$HEAD") # encoding required
esac
SUFFIX=$TAIL
done
echo "${PREFIX}$ENCODED"
}
function initJamf() {
# verify encoded authorization
if [ -z "$JSS_AUTH" ]; then
# verify username and password for jss
if [ -n "$JSS_USER" ] || [ -z "$JSS_PASSWORD" ]; then
echo "ERROR: A username or password to access to the JSS was not specified." >&2
return $LINENO
fi
if declare -f encodeBasicAuthorization &> /dev/null; then
if ! JSS_AUTH=$(encodeBasicAuthorization "$JSS_USER" "$JSS_PASSWORD"); then
return $LINENO
fi
else
echo "ERROR: Unable to encode username and password to access the JSS." >&2
return $LINENO
fi
fi
# get jss url
JSS_URL=$(/usr/bin/defaults read /Library/Preferences/com.jamfsoftware.jamf.plist jss_url 2> /dev/null)
if [ -z "JSS_URL" ]; then
echo "ERROR: A a valid URL to the JSS was not specified [JSS_URL]." >&2
return $LINENO
fi
# verify jss is available
JSS_CONNECTION=$(/usr/bin/curl --connect-timeout 10 -H "Authorization: Basic $JSS_AUTH" -sw "%{http_code}" ${JSS_URL%/}/JSSCheckConnection -o /dev/null)
if [ $JSS_CONNECTION -ne 200 ] && [ $JSS_CONNECTION -ne 403 ] ; then
echo "ERROR: Unable to connect to JSS [$JSS_URL]." >&2
return $LINENO
fi
}
function isInteger() {
return $([ "$@" -eq "$@" ] 2> /dev/null)
}
function main() {
while [ -n "$1" ]; do
case $1 in
-n | --name ) shift;GROUP_NAME="$1" ;;
-f | --file ) shift;FILE_PATH="$1" ;;
-u | --user ) shift;JSS_USER="$1" ;;
-p | --pass ) shift;JSS_PASSWORD="$1" ;;
-a | --auth ) shift;JSS_AUTH="$1" ;;
-h | --help ) shift;usage ;;
* ) COMPUTERS+=( "$1" )
esac
shift
done
# load common source variables
if [ -f ~/.bash_source ]; then
source ~/.bash_source
fi
# prompt for password if missing
if [ -z "$JSS_AUTH" ] && [ -n "$JSS_USER" ] && [ -z "$JSS_PASSWORD" ]; then
echo "Please enter JSS password for account [$JSS_USER]: "
read -s JSS_PASSWORD
fi
# verify user and password or encoded authorization
if [ -z "$JSS_USER" ] || [ -z "$JSS_PASSWORD" ] && [ -z "$JSS_AUTH" ]; then
echo "ERROR: A JSS user name and password are required if no encoded authorization is provided." >&2
usage
exit $LINENO
fi
# verify group name was specified
if [ -z "$GROUP_NAME" ]; then
echo "Please enter a name for the group you wish to create/populate: "
read GROUP_NAME
if [ -z "$GROUP_NAME" ]; then
echo "ERROR: No group name was specified." >&2
exit $LINENO
fi
fi
# verify member source
if [ ! -r "$FILE_PATH" ] && [ "${#COMPUTERS[@]}" -eq "0" ]; then
echo "Please drag-n-drop or enter the path to a line-seperated file containing computer names or IDs: "
read FILE_PATH
if [ ! -r "$FILE_PATH" ]; then
echo "ERROR: The path to the specified readable file cound not be found [$FILE_PATH]." >&2
exit $LINENO
fi
fi
# populate array with computer names from file
if [ -r "$FILE_PATH" ]; then
while IFS= read -r COMPUTER; do
COMPUTERS+=($COMPUTER)
done < "$FILE_PATH"
fi
# obsure password for debug
for ((i=1; i<${#JSS_PASSWORD}; i++)); do
JSS_OBSURED+="◦"
done
# display parameters for debug
if $DEBUG; then
echo -e "NAME: $GROUP_NAME
FILE: $FILE_PATH
USER: $JSS_USER
PASS: $JSS_OBSURED
AUTH: $JSS_AUTH
COMPUTERS: ${COMPUTERS[@]}"
fi
# initialize and verify jamf connection
if ! initJamf; then exit $LINENO; fi
# create/get computer group id
if ! GROUP_ID=$(createStaticGroup "$GROUP_NAME"); then exit $LINENO; fi
# add each computer to group
addGroupMembers "$GROUP_ID" "$GROUP_NAME"
# play sound to signal completion
playSound
}
function playSound() {
# $1 = Path to sound file. (/System/Library/Sounds/Glass.aiff)
local SOUND_FILE_PATH="$1"
if [ -z "$SOUND_FILE_PATH" ] && [ -f "/System/Library/Sounds/Glass.aiff" ]; then
local SOUND_FILE_PATH="/System/Library/Sounds/Glass.aiff"
fi
if [ -f "$SOUND_FILE_PATH" ]; then
/usr/bin/afplay "$SOUND_FILE_PATH" &> /dev/null
fi
}
function progressBar() {
# $1 = Maximum count of progress. (75)
# $2 = Current count of progress. (10)
local MAX="$1"
local COUNT="$2"
# verify required parameters
if [ -z "$MAX" ] || [ -z "$COUNT" ]; then
echo "ERROR: Missing parameter."
return $LINENO
fi
# verify parameters are integers
if [ "$MAX" -ne "$MAX" ] 2> /dev/null || [ "$COUNT" -ne "$COUNT" ] 2> /dev/null; then
echo "ERROR: Integer expression expected." >&2
return $LINENO
fi
if [ "$COUNT" -lt "$MAX" ]; then
# display progress
PERCENT_COMPLETE=$(echo "(100/$MAX)*$COUNT" | /usr/bin/bc -l | /usr/bin/awk '{print int($1+0.5)}')
PROGRESS_DONE=$(echo "$PERCENT_COMPLETE/2" | /usr/bin/bc -l | /usr/bin/awk '{print int($1+0.5)}')
PROGRESS_LEFT=$(( 50 - $PROGRESS_DONE ))
DONE_PATTERN=$(/usr/bin/printf "%${PROGRESS_DONE}s") # % number "done" of blanks
LEFT_PATTERN=$(/usr/bin/printf "%${PROGRESS_LEFT}s") # % number "left" of blanks
/usr/bin/printf "
Processing: [${DONE_PATTERN// /#}${LEFT_PATTERN// /-}] ${PERCENT_COMPLETE}%%" # replace blanks with patterns
else
/usr/bin/printf "
Processing: [##################################################] 100%%
"
fi
}
function usage() {
echo
echo "Usage: ./${0##*/} -n "NAME" -f "FILE" -u "USER" -p "PASSWORD" -a "AUTHENTICATION" -h <computer_name> <computer_name>... OR <computer_id> <computer_id>..."
echo
echo -e " -n | --name Specify a static group name to create (required)"
echo -e " -f | --file Specify a line-seperated file containing computer names or ids (optional)"
echo -e " -u | --user Specify a JSS user name with access to create computer groups (required)"
echo -e " -p | --pass Specify a JSS password for the user name specified above (optional)"
echo -e " -a | --auth Specify encoded JSS authorization credentials (optional)"
echo -e " If --auth is spcified then user and password are optional."
echo -e " <computer_name> Computer names can be included as parameters on the command line (optional)"
echo -e " <computer_id> Computer ids can be included as parameters on the command line (optional)"
echo -e " -h | --help Display help"
}
# run main if called directly
if [[ "$BASH_SOURCE" == "$0" ]]; then
main $@
fi
Posted on 01-29-2020 01:02 PM
Not super fancy nor the best code but this is what we use to add devices to a particular static group. It's not pretty but it gets the job done.
#! /bin/sh
######################################################################
############## Define Variable Block #################################
######################################################################
groupID="$4"
utilityName="$5"
jamfAuthKey="$6" //Basic Base64 encoded
jamfBaseURL="https://your.jamf.pro:8443"
allComputersFile="/path/to/localfile.txt"
filePath="/file/path/root"
loop="Continue"
oops1Dialog="SORRY! Either the Asset Tag entered: "
oops2Dialog=" was incorrect or that device is not currently being managed by Jamf Pro. Please check the device and try again."
addAnotherDialog="Would you like to add another device?"
mainDialog="Please Enter the Asset Tag of the Mac to add to the "$utilityName" Group (format: XX123456)"
appTitle="Company Name "$utilityName" Utility"
xmlContentType="Content-Type: application/xml"
computersAPI="/JSSResource/computers"
computerIDAPI="/JSSResource/computergroups/id/"
######################################################################
################# Define Functions Block #############################
######################################################################
file_Check() {
mkdir -p "$filePath"
if [ -f "$allComputersFile" ]
then
rm -rf "$allComputersFile"
fi
}
get_List() {
curl -X GET "$jamfBaseURL""$computersAPI" -H "$xmlContentType" -H "${jamfAuthKey}" > "$allComputersFile"
}
add_Devices() {
assetTag=$(osascript <<EOT
tell app "System Events"
text returned of (display dialog "${mainDialog}" buttons {"Cancel", "Continue"} default button "Continue" default answer "" with title "${appTitle}")
end tell
EOT
)
if ! grep -i ${assetTag} "$allComputersFile"
then
osascript <<EOT
tell app "System Events"
display dialog "${oops1Dialog} ${assetTag} ${oops2Dialog}" buttons {"Done"} default button "Done" with title "${appTitle}"
end tell
EOT
else
echo "<computer_group><computer_additions><computer><name>$assetTag</name></computer></computer_additions></computer_group>" | curl -X PUT -d @- "$jamfBaseURL""$computerIDAPI""$groupID" -H "$xmlContentType" -H "$jamfAuthKey"
fi
}
device_Loop() {
loop=$(osascript <<EOT
tell app "System Events"
button returned of (display dialog "${addAnotherDialog}" buttons {"Cancel", "Continue", "Done" } default button "Done" with title "${appTitle}")
end tell
EOT
)
}
######################################################################
################# Script Run Block ###################################
######################################################################
while [ "${loop}" = "Continue" ]
do
file_Check
get_List
add_Devices
device_Loop
file_Check
done
Posted on 01-29-2020 04:15 PM
@jhuls The majority of our scopes are based on PreStage and auto-assigned or moved at purchasing. We have static groups that emulate those PreStages and I want buttons for our techs to add machines to these groups.
We try to leverage a Smart Groups 97% of the time but these static groups pick up their slack.
Posted on 01-29-2020 10:04 PM
@strayer Your script looks perfect for us. I have the URL defined on the actual script for Jamf Cloud, and the following attributes defined. That being said, the computer is not porting to a static group.
I am getting ": No such file or directory" when it is looking for the group id, which I grabbed from the JSS URL when I am in the static group. I believe that is the correct method?
Thanks for your help!
Jared
Posted on 01-30-2020 06:34 AM
@jared_f Could be this. I put it in as a quote instead of as a script so the backtics areound result=$`curl "$fullURL" -u "$APIUser:$APIPass" -H "Content-Type: text/xml" -X PUT -d "$xml"
didn't translate correctly
i've edited my comment above. let me know if that does it.
Posted on 01-30-2020 08:52 AM
@strayer That did the trick. Thanks for the script, it is perfect for our needs
Posted on 01-30-2020 09:51 AM
If you're trying to add a single computer to a Static Group, the <computer_additions>
mechanism is much simpler:
#!/bin/sh
#API login info
apiuser="USERNAME"
apipass='PASSWORD'
jamfProURL="https://jamfproserver:8443"
ComputerName=$(/usr/sbin/scutil --get ComputerName)
GroupID="1234"
GroupName="Whatever the Group Name is"
apiURL="JSSResource/computergroups/id/${GroupID}"
#XML header stuff
xmlHeader="<?xml version="1.0" encoding="UTF-8"?>"
apiData="<computer_group><id>${GroupID}</id><name>${GroupName}</name><computer_additions><computer><name>$ComputerName</name></computer></computer_additions></computer_group>"
curl -sSkiu ${apiuser}:${apipass} "${jamfProURL}/${apiURL}"
-H "Content-Type: text/xml"
-d "${xmlHeader}${apiData}"
-X PUT > /dev/null
Posted on 03-24-2022 09:10 AM
I'm trying to use this and the command completes but I get bad request in the return when removing the > /dev/null and the computer doesn't post to the group. Could you take a look and see what I'm doing wrong? I have both the serial and computer group in my script but currently have it running off the serial number to post. I get the same return either way. Here is the return when running from terminal.
+ apiuser=api_user
+ apipass='XXXX'
+ jamfProURL=https://mdm.company.org:8443
++ hostname
+ ComputerName=localcomputername
++ ioreg -rd1 -c IOPlatformExpertDevice
++ awk '-F"' '/IOPlatformSerialNumber/{print $4 tail}'
+ ComputerSerial=localcomputerserial
+ GroupID=1234
+ GroupName=APITest
+ apiURL=JSSResource/computergroups/id/1234
+ xmlHeader='<?xml version=1.0 encoding=UTF-8?>'
+ apiData='
<computer_group>
<id>1234</id>
<name>APITest</name>
<computer_additions>
<computer>
<serial_number>localcomputerserial</serial_number>
</computer>
</computer_additions>
</computer_group>'
+ curl -sSkiu 'api_user:XXXX' https://mdm.company.org:8443/JSSResource/computergroups/id/1234 -H 'Content-Type: text/xml' -d '<?xml version=1.0 encoding=UTF-8?>
<computer_group>
<id>1234</id>
<name>APITest</name>
<computer_additions>
<computer>
<serial_number>localcomputerserial</serial_number>
</computer>
</computer_additions>
</computer_group>' -X PUT
HTTP/2 400
date: Thu, 24 Mar 2022 15:56:29 GMT
content-type: text/html;charset=UTF-8
content-length: 400
set-cookie: LongStringOfCharacters; Expires=Thu, 31 Mar 2022 15:56:28 GMT; Path=/
set-cookie: LongStringOfCharacters; Expires=Thu, 31 Mar 2022 15:56:28 GMT; Path=/; SameSite=None; Secure
x-frame-options: DENY
cache-control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0
strict-transport-security: max-age=31536000;includeSubDomains
x-xss-protection: 1; mode=block
accept-ranges: bytes
server: Jamf Cloud Node
vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
<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;">Bad Request</p>
<p>Error in XML file</p>
<p>You can get technical details <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1">here</a>.<br>
Please continue your visit at our <a href="/">home page</a>.
</p>
</body>
</html>
Thanks!
Posted on 03-24-2022 11:19 AM
Disregard. After reading this thread a little more thoroughly and comparing some other scripts, it seems that removing the {xmlHeader} from -d "${xmlHeader}{apiData}" solved the issue.
Posted on 03-24-2022 11:25 AM
@GGInquisitor I would strongly advise you to look at @dlondon 's updated script which uses Bearer Token Auth which will be required for API calls later this year: https://community.jamf.com/t5/jamf-pro/bearer-token-api-and-adding-computer-to-static-group/m-p/2614...
Posted on 07-05-2023 04:47 AM
Hello ,
I try to use this commands but every time I have error like
-X: command not found
-d: command not found
Do you have any idea ?
Posted on 07-05-2023 05:49 AM
@kdpk Do not use the scripts in this thread. You should refer to @dlondon 's updated version which uses Bearer Token Auth (and corrects the formatting of the curl command to include the line continuation characters missing in the script you tried): https://community.jamf.com/t5/jamf-pro/bearer-token-api-and-adding-computer-to-static-group/m-p/2614...
Posted on 03-18-2020 03:37 PM
After much testing, I found we can simplify the command. You don't need to include the xmlHeader, GroupID, or GroupName in the XML data you send.
This command works to PUT the computers with ID 777 and 888 into the $GroupID Group:
curl -u "$apiUsername":"$apiPassword"
https://jss.url.com:8443/JSSResource/computergroups/id/$GroupID
-H "Content-Type: text/xml"
-X PUT -s
-d "<computer_group><computer_additions>
<computer><id>777</id></computer>
<computer><id>888</id></computer>
</computer_additions></computer_group>"
Posted on 03-18-2020 07:03 PM
@tim.c.arnold Thanks for doing the research on trimming that command, but you might want to correct your statement
You don't need to include the xmlHeader, GroupID, or GroupName
as you do need the GroupID.
Posted on 03-19-2020 01:29 PM
Ah, yes... I meant - You don't need to supply the GroupID in the XML Data.
You do still need the GroupID in the URL. edited initial post to add clarity.
Posted on 09-03-2020 10:46 PM
@mrheathjones whats the jamfAuthKey? You not using an username and password?