Python API

ats
New Contributor

Hello, I am just starting to use the API queries with python.

I am having some difficulty getting anything to 'PUT' changes for existing devices. I keep getting a HTTP Error 500: Internal Server Error.

I am unsure where to check for logs on the server side for API access attempts or if there even are any such logs.

I have tried multiple attributes but keep getting the same error, here is a sample below.

I have a test.xml file and in that test.xml I have the following
<mobile_device><location><username>testusername</username></location></mobile_device>

code as follows:
------
from urllib2 import urlopen, URLError, HTTPError, Request
from xml.dom import minidom
import base64

my_xml_doc = minidom.parse("test.xml")
url="https://myserver:8443/JSSResource/mobiledevices/id/9999"
req = Request(url, data=my_xml_doc.toprettyxml())
req.add_header('Content-Type','text/xml')
req.get_method=lambda: 'PUT'
base64string=base64.encodestring('myuseraccount:mypassword')
authheader="Basic %s" % base64string
req.add_header("Authorization", authheader)
xmldata = urlopen(req)
-----------------

Since I have never accessed the API before, I am unsure of what I am doing wrong. Does anyone see what I am doing wrong for the following updates? In this case I am trying to update the username to "testusername" on an existing device id 9999

Any assistance in this issue would be appreaciated.

1 ACCEPTED SOLUTION

BrysonTyrrell
Contributor II

500 errors can sometimes be attributed to the JSS trying to parse your input XML and failing.

This line here:

req = Request(url, data=my_xml_doc.toprettyxml())

You don't need to prettyprint the XML that you're passing to the request. The extra spacing and newline characters that are being added might be a factor in the error. The original XML string you used works fine.

Try the code below. Its a little simplified down and works against a test instance I have.

import urllib2
import base64

xml = "<mobile_device><location><username>new.user</username></location></mobile_device>"

request = urllib2.Request('https://myjss.com/JSSResource/..')
request.add_header('Authorization', 'Basic ' + base64.b64encode('jssusername:jsspassword'))
request.add_header('Content-Type', 'text/xml')
request.get_method = lambda: 'PUT'
response = urllib2.urlopen(request, xml)

View solution in original post

5 REPLIES 5

BrysonTyrrell
Contributor II

500 errors can sometimes be attributed to the JSS trying to parse your input XML and failing.

This line here:

req = Request(url, data=my_xml_doc.toprettyxml())

You don't need to prettyprint the XML that you're passing to the request. The extra spacing and newline characters that are being added might be a factor in the error. The original XML string you used works fine.

Try the code below. Its a little simplified down and works against a test instance I have.

import urllib2
import base64

xml = "<mobile_device><location><username>new.user</username></location></mobile_device>"

request = urllib2.Request('https://myjss.com/JSSResource/..')
request.add_header('Authorization', 'Basic ' + base64.b64encode('jssusername:jsspassword'))
request.add_header('Content-Type', 'text/xml')
request.get_method = lambda: 'PUT'
response = urllib2.urlopen(request, xml)

ats
New Contributor

Thank you, this definitely led me in the right direction. Your code worked for me.

I also tried changing my original code to .toxml() but it still did not work. After further examination I noticed you used base64.b64encode whereas I was using base64.encodestring.

I tested to the two and the difference turned out to be that the base64.encodestring actually appends a newline ' ' at the end.

m_green
New Contributor III

That moment when you've spent the last hour trying to figure out what the heck was wrong with your code..... and it was in jamfnation all along......

Thank you!

Also, @brysontyrrell I just finished watching the JNUC 2016 "Intro to Webhooks" on YouTube. It was very good! I can see where webhooks would be very useful but at this point it's a bit over my head. Something to look forward to though!

BrysonTyrrell
Contributor II

@mattgreen10

Glad you found it useful. If you're writing Python code that's running on your clients and you need to stay within the confines of the standard library, continue to use urllib2. If you're writing Python code that isn't going to run on your clients, use pip to install requests and use that. You'll find loads of examples all over the place on using it, it's much easier, and far more powerful a library!

If you're interested in learning more about webhooks you're going to have a couple of opportunities coming up. I'll be giving a workshop at Penn State MacAdmins this year all about building Jamf Pro integrations using webhooks.

m_green
New Contributor III

That's awesome, I looked all over Texas for conferences and always ended up back at MacAdmins so I pitched it to my supervisor and got it approved. I appreciate the heads up and the extra info. Apparently I've become fairly notorious at jamf for blowing our server up so I'm still very much a novice when it comes to management of iOS and macOS but I love to learn all the abilities of the JSS, especially anything that can be automated like the APIs, webhooks, etc.

I'll see you at MacAdmins.