grahampugh / jamf-upload

Scripts for uploading packages to Jamf Cloud
Apache License 2.0
148 stars 36 forks source link

JamfComputerProfileUploader fails when mobileconfigs contain an ampersand #129

Open jc0b opened 5 months ago

jc0b commented 5 months ago

Just stumbled across this - I am running into an issue where profiles that contain an ampersand in any field fail to upload to Jamf. It appears that this may be a Jamf bug, but I'm not completely sure.

XML escapes the & character to & in .mobileconfig files. JamfComputerProfileUploader escapes this ampersand again, to & in the file that gets POSTed to Jamf. I suspect that Jamf might be tripping over this, somehow.

To replicate

Using the minimum viable example that can be found in this gist (assuming all of these files are in the same directory, and its your working directory): autopkg run -vvvv com.jc0b.test.AmpersandBug

This leads to the following recipe output, containing this response from Jamf:

JamfComputerProfileUploader: Uploading Configuration Profile...
JamfComputerProfileUploader: Configuration Profile upload attempt 1
JamfComputerProfileUploader: Output file is:  /tmp/jamf_upload_4ezuxlz7/jamf_upload_5g8l9obg.txt
JamfComputerProfileUploader: curl command: /usr/bin/curl --dump-header /tmp/jamf_upload_4ezuxlz7/curl_headers_from_jamf_upload.txt https://SNIP.jamfcloud.com/JSSResource/osxconfigurationprofiles/id/0 --request POST --silent --show-error --header authorization: Bearer SNIP --upload-file /tmp/jamf_upload_4ezuxlz7/jamf_upload_srsvq6z3.txt --header Content-type: application/xml --output /tmp/jamf_upload_4ezuxlz7/jamf_upload_5g8l9obg.txt --cookie-jar /tmp/jamf_upload_4ezuxlz7/curl_cookies_from_jamf_upload.txt --cookie /tmp/jamf_upload_4ezuxlz7/curl_cookies_from_jamf_upload.txt
JamfComputerProfileUploader: API response:
b'<html>\n<head>\n   <title>Status page</title>\n</head>\n<body style="font-family: sans-serif;">\n<p style="font-size: 1.2em;font-weight: bold;margin: 1em 0px;">Conflict</p>\n<p>Unable to update the database</p>\n<p>You can get technical details <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10">here</a>.<br>\nPlease continue your visit at our <a href="/">home page</a>.\n</p>\n</body>\n</html>\n'
Traceback (most recent call last):
  File "/Library/AutoPkg/autopkglib/__init__.py", line 840, in process
    self.env = processor.process()
  File "/Library/AutoPkg/autopkglib/__init__.py", line 626, in process
    self.main()
  File "/Users/jacob.burley/Library/AutoPkg/RecipeRepos/com.github.autopkg.grahampugh-recipes/JamfUploaderProcessors/JamfComputerProfileUploader.py", line 600, in main
    self.upload_mobileconfig(
  File "/Users/jacob.burley/Library/AutoPkg/RecipeRepos/com.github.autopkg.grahampugh-recipes/JamfUploaderProcessors/JamfComputerProfileUploader.py", line 346, in upload_mobileconfig
    self.status_check(
  File "/Users/jacob.burley/Library/AutoPkg/RecipeRepos/com.github.autopkg.grahampugh-recipes/JamfUploaderProcessors/JamfUploaderLib/JamfUploaderBase.py", line 523, in status_check
    f"conflict: {parser.error.replace('Error: ', '')}"
AttributeError: 'NoneType' object has no attribute 'replace'
  File "/Library/AutoPkg/autopkglib/__init__.py", line 840, in process
    self.env = processor.process()
'NoneType' object has no attribute 'replace'
Failed.

At the same time, you can find this output in the Jamf Pro server logs (edited for length):

2024-02-08 12:37:08,218 [ERROR] [Tomcat-42  ] [figurationProfileResource] - There was problem creating config profilecom.jamfsoftware.configurationprofiles.api.exceptions.ConfigProfileReadException: File cannot be processed.
com.jamfsoftware.configurationprofiles.api.exceptions.ConfigProfileReadException: File cannot be processed.
    ...
Caused by: java.io.IOException: Failed to parse property list
    ...
Caused by: org.xml.sax.SAXParseException: The entity name must immediately follow the '&' in the entity reference.
    ...

Removing the ampersand from the profile causes this issue to go away.

Workaround is to indeed not have ampersands in profiles, but importing profiles from elsewhere may unexpectedly lead to this issue.

grahampugh commented 5 months ago

I think it's expected that the escaping gets doubled - it has to really, because the mobileconfig is all escaped inside the XML - so for example all the less-than and greater-than symbols also get escaped.

I just want to check that you tried it with a profile that actually has a payload? I'm not sure it's valid to upload a profile with no payload.

jc0b commented 5 months ago

Yes, I initially stumbled across this with the ampersand in a payload (for a Google Chrome managed bookmark), rather than just in the title. I could upload the profile through the UI just fine, but uploading it via the API didn't work, which is what caused me to look at the escaping.