Create Smart Group from API - Powershell

statusBrew
New Contributor III

My organisation has recently procured Jamf, and it's a majority Windows org.

I'm quite new to Jamf, but familiar with MDMs, and most of my day is spent using a Windows machine.

 

We have a number of applications that we have API access to, and I've been successful in setting up API access within powershell using client credentials, and able to make basic GET calls, and some simple POST commands - such as creating departments, or categories.

 

I have a list of departments I need to create, and want to also create smart groups for each of those departments, pulling in computers where the department is set to a specific value.

I've created a smart group manually and able to GET the configuration options in an API output.

My familiarity with API is using JSON for the POST calls, but looking at the GET output, it's an XML format, in a single string (weird to me, but maybe that's shell standard?)


However, I cannot get it to POST and create a group, when I modify the specific options from the GET output.

Even if I export the array as an XML file, and import it and pass that in the body, it rejects the format of the request.

 

For example, if a department is "Medical", I want the smart group to pull in if the department of the computer record says "Medical"

I've even tried passing that in a string as the request body, TNA:

 

New-JamfComputerSmartGroup -body "<computer_group><id>25</id><name>Department-Medical</name><is_smart>true</is_smart><site><id>-1</id><name>None</name></site><criteria><size>1</size><criterion><name>Department</name><priority>0</priority><and_or>and</and_or><search_type>is</search_type><value>Medical</value><opening_paren>false</opening_paren><closing_paren>false</closing_paren></criterion></criteria><computers><size>0</size></computers></computer_group>"

 

Anyone else had some success with this?

1 ACCEPTED SOLUTION

statusBrew
New Contributor III

Good news, managed to get this one resolved!
Took me a little while, but I'll document it here so that it's recorded for anyone else who might find it useful.

 

Initially, I had a look at the reference documentation, and copied the receipe into Shell on one of my test macs. When passing the XML body, it worked! So, I set about trying a few things in translation from curl to Powershell commands.

I took a guess at changing the content type in the Invoke-RestMethod call to "application/xml", because this is what the curl command was using, and the body being passed was in an XML format. And this worked too!

So, good news is that now Powershell is creating the group, but relies on a full, hardcoded XML body being passed to the function, which for repeat scripting and multiple group creation calls, is not ideal.

 

Working with a colleague (who is far better at PS stuff than I believe I am), we came up with the theory of storing an XML template in a file, and calling that into the function.
I copied the sample body from the Jamf API reference documentation and saved this in a separate file. Then imported that using 

[xml]$xmlTemplate = Get-Content -path .\path\to\template.xml

My PS function contained a few parameters, namely one for the group name, and one for the search string.

I then used these parameter values to modify specific strings in the XML template, to update it to what I wanted the group to look like in Jamf

$xmlTemplate.computer_group.name = $groupName
$xmlTemplate.computer_group.criteria.criterion.value = $searchValue

And then, pass the modified XML in the body of the API call

Invoke-RestMethod -uri $URI -method $METHOD -headers $Headers -body $xmlFromFile -ContentType "application/xml"

 

And it worked!

I've gone back in and added many more parameters to the function since - things like

  • and_or
  • siteID
  • siteName
  • is_smart
  • openParen
  • closeParen

etc - this will give me more flexibility to create groups in the future not constrained to this specific use case.

I've given a lot of these parameters a default value where I think it's suitable for my setup, but these can be overwritten when passing the parameter.

 

We got there!

View solution in original post

3 REPLIES 3

mm2270
Legendary Contributor III

I don't know much Powershell, so I can't help you there, but one thing I see that you need to change is, the ID for a new group should be "0" not a specific number like you have there. 0 designates a new object to be made when used in conjunction with a POST command.

The rest of the XML format looks ok to me at first glance, but it's been a while since I've used it to create new groups.

statusBrew
New Contributor III

Thanks mm2270

 

I've changed the ID to 0, and also modified the API URI to be https://jssname.jamfcloud.com/JSSResource/computergoups/id/0, but still getting an error.

"<computer_group><id>0</id><name>Department-Medical</name><is_smart>true</is_smart><site><id>-1</id><name>None</name></site><criteria><size>1</size><criterion><name>Department</name><priority>0</priority><and_or>and</and_or><search_type>is</search_type><value>Medical</value><opening_paren>false</opening_paren><closing_paren>false</closing_paren></criterion></criteria><computers><size>0</size></computers></computer_group>"

At the moment, the error (when using the body above) is:

 

Unsupported Media Type
The server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method

 

I did have a -ContentType parameter with the value as "application/json", but even when removing that, and trying again, I get the same result.

statusBrew
New Contributor III

Good news, managed to get this one resolved!
Took me a little while, but I'll document it here so that it's recorded for anyone else who might find it useful.

 

Initially, I had a look at the reference documentation, and copied the receipe into Shell on one of my test macs. When passing the XML body, it worked! So, I set about trying a few things in translation from curl to Powershell commands.

I took a guess at changing the content type in the Invoke-RestMethod call to "application/xml", because this is what the curl command was using, and the body being passed was in an XML format. And this worked too!

So, good news is that now Powershell is creating the group, but relies on a full, hardcoded XML body being passed to the function, which for repeat scripting and multiple group creation calls, is not ideal.

 

Working with a colleague (who is far better at PS stuff than I believe I am), we came up with the theory of storing an XML template in a file, and calling that into the function.
I copied the sample body from the Jamf API reference documentation and saved this in a separate file. Then imported that using 

[xml]$xmlTemplate = Get-Content -path .\path\to\template.xml

My PS function contained a few parameters, namely one for the group name, and one for the search string.

I then used these parameter values to modify specific strings in the XML template, to update it to what I wanted the group to look like in Jamf

$xmlTemplate.computer_group.name = $groupName
$xmlTemplate.computer_group.criteria.criterion.value = $searchValue

And then, pass the modified XML in the body of the API call

Invoke-RestMethod -uri $URI -method $METHOD -headers $Headers -body $xmlFromFile -ContentType "application/xml"

 

And it worked!

I've gone back in and added many more parameters to the function since - things like

  • and_or
  • siteID
  • siteName
  • is_smart
  • openParen
  • closeParen

etc - this will give me more flexibility to create groups in the future not constrained to this specific use case.

I've given a lot of these parameters a default value where I think it's suitable for my setup, but these can be overwritten when passing the parameter.

 

We got there!