Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
import base64
import urllib2
import re
from time import time
import xml.etree.ElementTree as etree
from CoreFoundation import CFPreferencesCopyAppValue # pylint: disable=no-name-in-module
def read_jamf_api_creds():
'''Reads Jamf credentials from a stored preference file.'''
pref_domains = ['com.github.autopkg', 'com.yourcompany.jamf']
jss_url = jss_usr = jss_pwd = None
for domain in pref_domains:
jss_url = CFPreferencesCopyAppValue('JSS_URL', domain)
jss_usr = CFPreferencesCopyAppValue('API_USERNAME', domain)
jss_pwd = CFPreferencesCopyAppValue('API_PASSWORD', domain)
if all((jss_url, jss_usr, jss_pwd)):
if not all((jss_url, jss_usr, jss_pwd)):
print ('[ERROR] Please check to make sure your Jamf credentials are '
'stored in the designated preference(s): {}'.format(pref_domains))
return jss_url, base64.b64encode(jss_usr + ':' + jss_pwd)
def jamf_api_call(url, credentials, method='', data=None):
'''Makes a Jamf API call.'''
request = urllib2.Request(url)
request.add_header('Authorization', 'Basic ' + credentials)
if method.upper() in ('POST', 'PUT', 'DELETE'):
request.get_method = lambda: method
if method.upper() in ('POST', 'PUT') and data is not None:
request.add_header('Content-Type', 'application/xml')
return urllib2.urlopen(request, data)
request.add_header('Accept', 'application/xml')
return urllib2.urlopen(request)
def main():
'''Main function.'''
# Get Jamf credentials.
jss_url, credentials = read_jamf_api_creds()
# Set name pattern for Jamf Remote policies.
policy_name_pattern = r'[\d\-]+ at [\d:]+ (A|P)M \| [\w\.@]+ \| [\d]+ Computers?'
# Get names and IDs of all policies.
url = '{}/JSSResource/policies'.format(jss_url)
response = jamf_api_call(url, credentials)
policies_xml = etree.fromstring(
policies = policies_xml.findall('policy')
print 'Found {} total Jamf policies.'.format(len(policies))
# Iterate through policies and remove the ones that match the Jamf Remote naming pattern.
for policy in policies:
rmatch =, policy.find('name').text)
if rmatch:
print 'Removing policy ID {}: "{}"...'.format(
url = '{}/JSSResource/policies/id/{}'.format(jss_url, policy.find('id').text)
start_time = time()
response = jamf_api_call(url, credentials, 'DELETE')
end_time = time()
print 'Completed in {:0.2f} seconds.'.format(end_time - start_time)
except urllib2.HTTPError as err:
print 'HTTP error:', err.code
except KeyboardInterrupt:
print '\nReceived Control-C, stopping now.'
if __name__ == '__main__':
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.