def upload_mobileconfig( jamf_url, enc_creds, mobileconfig_name, description, category, mobileconfig_plist, computergroup_name, template_contents, profile_uuid, verbosity, obj_id=None, ): """Update Configuration Profile metadata.""" # if we find an object ID we put, if not, we post if obj_id: url = "{}/JSSResource/osxconfigurationprofiles/id/{}".format(jamf_url, obj_id) else: url = "{}/JSSResource/osxconfigurationprofiles/id/0".format(jamf_url) # remove newlines, tabs, leading spaces, and XML-escape the payload mobileconfig_plist = mobileconfig_plist.decode("UTF-8") mobileconfig_list = mobileconfig_plist.rsplit("\n") mobileconfig_list = [x.strip("\t") for x in mobileconfig_list] mobileconfig_list = [x.strip(" ") for x in mobileconfig_list] mobileconfig = "".join(mobileconfig_list) # substitute user-assignable keys replaceable_keys = { "mobileconfig_name": mobileconfig_name, "description": description, "category": category, "payload": mobileconfig, "computergroup_name": computergroup_name, "uuid": "com.github.grahampugh.jamf-upload.{}".format(profile_uuid), } # substitute user-assignable keys (escaping for XML) template_contents = actions.substitute_assignable_keys( template_contents, replaceable_keys, verbosity, xml_escape=True ) if verbosity > 2: print("Configuration Profile to be uploaded:") print(template_contents) print("Uploading Configuration Profile..") # write the template to temp file template_xml = curl.write_temp_file(template_contents) count = 0 while True: count += 1 if verbosity > 1: print("Configuration Profile upload attempt {}".format(count)) method = "PUT" if obj_id else "POST" r = curl.request(method, url, enc_creds, verbosity, template_xml) # check HTTP response if curl.status_check(r, "Configuration Profile", mobileconfig_name) == "break": break if count > 5: print( "ERROR: Configuration Profile upload did not succeed after 5 attempts" ) print("\nHTTP POST Response Code: {}".format(r.status_code)) break sleep(10) if verbosity > 1: api_get.get_headers(r) return r
def main(): """Do the main thing here""" print("\n** Jamf policy upload script") print("** Creates a policy in Jamf Pro.") # parse the command line arguments args, cli_custom_keys = get_args() verbosity = args.verbose # grab values from a prefs file if supplied jamf_url, _, _, enc_creds = api_connect.get_creds_from_args(args) # import computer group from file and replace any keys in the XML with open(args.template, "r") as file: template_contents = file.read() # substitute user-assignable keys template_contents = actions.substitute_assignable_keys( template_contents, cli_custom_keys, verbosity) # set a list of names either from the CLI args or from the template if no arg provided if args.names: names = args.names else: names = [get_policy_name(template_contents, verbosity)] # now process the list of names for policy_name in names: # where a policy name was supplied via CLI arg, replace this in the template if args.names: template_contents = replace_policy_name(policy_name, template_contents, verbosity) # check for existing policy print("\nChecking '{}' on {}".format(policy_name, jamf_url)) obj_id = api_get.check_api_obj_id_from_name(jamf_url, "policy", policy_name, enc_creds, verbosity) if obj_id: print("Policy '{}' already exists: ID {}".format( policy_name, obj_id)) if args.replace: r = upload_policy( jamf_url, enc_creds, policy_name, template_contents, cli_custom_keys, verbosity, obj_id, ) else: print( "Not replacing existing policy. Use --replace to enforce.") else: print("Policy '{}' not found - will create".format(policy_name)) r = upload_policy( jamf_url, enc_creds, policy_name, template_contents, cli_custom_keys, verbosity, ) # now upload the icon to the policy if specified in the args if args.icon: # get the policy_id returned from the HTTP response try: policy_id = ElementTree.fromstring(r.text).findtext("id") upload_policy_icon( jamf_url, enc_creds, policy_name, args.icon, args.replace_icon, verbosity, policy_id, ) except UnboundLocalError: upload_policy_icon( jamf_url, enc_creds, policy_name, args.icon, args.replace_icon, verbosity, ) print()
def main(): """Do the main thing here""" print("\n** Jamf computer group upload script") print("** Creates a computer group in Jamf Pro.") # parse the command line arguments args, cli_custom_keys = get_args() verbosity = args.verbose # grab values from a prefs file if supplied jamf_url, _, _, _, enc_creds = api_connect.get_creds_from_args(args) # import computer group from file and replace any keys in the XML with open(args.template, "r") as file: template_contents = file.read() # substitute user-assignable keys # pylint is incorrectly stating that 'verbosity' has no value. So... # pylint: disable=no-value-for-parameter template_contents = actions.substitute_assignable_keys(template_contents, cli_custom_keys, verbosity, xml_escape=True) # set a list of names either from the CLI args or from the template if no arg provided if args.names: names = args.names else: names = [get_computergroup_name(template_contents, verbosity)] # now process the list of names for computergroup_name in names: # where a group name was supplied via CLI arg, replace this in the template if args.names: template_contents = replace_computergroup_name( computergroup_name, template_contents, verbosity) # check for existing group print("\nChecking '{}' on {}".format(computergroup_name, jamf_url)) obj_id = api_get.get_api_obj_id_from_name(jamf_url, "computer_group", computergroup_name, enc_creds, verbosity) if obj_id: print("Computer Group '{}' already exists: ID {}".format( computergroup_name, obj_id)) if args.replace: upload_computergroup( jamf_url, enc_creds, computergroup_name, template_contents, cli_custom_keys, verbosity, obj_id, ) else: print( "Not replacing existing Computer Group. Use --replace to enforce." ) else: print("Computer Group '{}' not found - will create".format( computergroup_name)) upload_computergroup( jamf_url, enc_creds, computergroup_name, template_contents, cli_custom_keys, verbosity, ) print()
def upload_script( jamf_url, script_name, script_path, category_id, category_name, script_info, script_notes, script_priority, script_parameter4, script_parameter5, script_parameter6, script_parameter7, script_parameter8, script_parameter9, script_parameter10, script_parameter11, script_os_requirements, verbosity, token, cli_custom_keys, obj_id=None, ): """Update script metadata.""" # import script from file and replace any keys in the script # script_contents = Path(script_path).read_text() with open(script_path, "r") as file: script_contents = file.read() # substitute user-assignable keys # pylint is incorrectly stating that 'verbosity' has no value. So... # pylint: disable=no-value-for-parameter script_contents = actions.substitute_assignable_keys( script_contents, cli_custom_keys, verbosity) # priority has to be in upper case. Let's make it nice for the user if script_priority: script_priority = script_priority.upper() # build the object script_data = { "name": script_name, "info": script_info, "notes": script_notes, "priority": script_priority, "categoryId": category_id, "categoryName": category_name, "parameter4": script_parameter4, "parameter5": script_parameter5, "parameter6": script_parameter6, "parameter7": script_parameter7, "parameter8": script_parameter8, "parameter9": script_parameter9, "parameter10": script_parameter10, "parameter11": script_parameter11, "osRequirements": script_os_requirements, "scriptContents": script_contents, } # ideally we upload to the object ID but if we didn't get a good response # we fall back to the name if obj_id: url = "{}/uapi/v1/scripts/{}".format(jamf_url, obj_id) script_data["id"] = obj_id else: url = "{}/uapi/v1/scripts".format(jamf_url) if verbosity > 2: print("Script data:") print(script_data) print("Uploading script..") count = 0 script_json = curl.write_json_file(script_data) while True: count += 1 if verbosity > 1: print("Script upload attempt {}".format(count)) method = "PUT" if obj_id else "POST" r = curl.request(method, url, token, verbosity, script_json) # check HTTP response if curl.status_check(r, "Script", script_name) == "break": break if count > 5: print("ERROR: Script upload did not succeed after 5 attempts") print("\nHTTP POST Response Code: {}".format(r.status_code)) break sleep(10) if verbosity > 1: api_get.get_headers(r) # clean up temp files if os.path.exists(script_json): os.remove(script_json)
def upload_extatt( jamf_url, enc_creds, extatt_name, script_path, verbosity, cli_custom_keys, obj_id=None, ): """Update extension attribute metadata.""" # import script from file and replace any keys in the script with open(script_path, "r") as file: script_contents = file.read() # substitute user-assignable keys script_contents = actions.substitute_assignable_keys( script_contents, cli_custom_keys, verbosity) # XML-escape the script script_contents_escaped = escape(script_contents) # build the object extatt_data = ( "<computer_extension_attribute>" + "<name>{}</name>".format(extatt_name) + "<enabled>true</enabled>" + "<description/>" + "<data_type>String</data_type>" + "<input_type>" + " <type>script</type>" + " <platform>Mac</platform>" + " <script>{}</script>".format(script_contents_escaped) + "</input_type>" + "<inventory_display>Extension Attributes</inventory_display>" + "<recon_display>Extension Attributes</recon_display>" + "</computer_extension_attribute>") headers = { "authorization": "Basic {}".format(enc_creds), "Accept": "application/xml", "Content-type": "application/xml", } # if we find an object ID we put, if not, we post if obj_id: url = "{}/JSSResource/computerextensionattributes/id/{}".format( jamf_url, obj_id) else: url = "{}/JSSResource/computerextensionattributes/id/0".format( jamf_url) http = requests.Session() if verbosity > 2: http.hooks["response"] = [api_connect.logging_hook] print("Extension Attribute data:") print(extatt_data) print("Uploading Extension Attribute..") count = 0 while True: count += 1 if verbosity > 1: print("Extension Attribute upload attempt {}".format(count)) if obj_id: r = http.put(url, headers=headers, data=extatt_data, timeout=60) else: r = http.post(url, headers=headers, data=extatt_data, timeout=60) if r.status_code == 200 or r.status_code == 201: print("Extension Attribute uploaded successfully") break if r.status_code == 409: print("ERROR: Extension Attribute upload failed due to a conflict") break if count > 5: print( "ERROR: Extension Attribute upload did not succeed after 5 attempts" ) print("\nHTTP POST Response Code: {}".format(r.status_code)) break sleep(10) if verbosity > 1: api_get.get_headers(r) return r
def upload_ea( jamf_url, enc_creds, ea_name, script_path, verbosity, cli_custom_keys, obj_id=None, ): """Update extension attribute metadata.""" # import script from file and replace any keys in the script with open(script_path, "r") as file: script_contents = file.read() # substitute user-assignable keys # pylint is incorrectly stating that 'verbosity' has no value. So... # pylint: disable=no-value-for-parameter script_contents = actions.substitute_assignable_keys( script_contents, cli_custom_keys, verbosity ) # XML-escape the script script_contents_escaped = escape(script_contents) # build the object ea_data = ( "<computer_extension_attribute>" + "<name>{}</name>".format(ea_name) + "<enabled>true</enabled>" + "<description/>" + "<data_type>String</data_type>" + "<input_type>" + " <type>script</type>" + " <platform>Mac</platform>" + " <script>{}</script>".format(script_contents_escaped) + "</input_type>" + "<inventory_display>Extension Attributes</inventory_display>" + "<recon_display>Extension Attributes</recon_display>" + "</computer_extension_attribute>" ) # if we find an object ID we put, if not, we post if obj_id: url = "{}/JSSResource/computerextensionattributes/id/{}".format( jamf_url, obj_id ) else: url = "{}/JSSResource/computerextensionattributes/id/0".format(jamf_url) if verbosity > 2: print("Extension Attribute data:") print(ea_data) print("Uploading Extension Attribute..") # write the template to temp file template_xml = curl.write_temp_file(ea_data) count = 0 while True: count += 1 if verbosity > 1: print("Extension Attribute upload attempt {}".format(count)) method = "PUT" if obj_id else "POST" r = curl.request(method, url, enc_creds, verbosity, template_xml) # check HTTP response if curl.status_check(r, "Extension Attribute", ea_name) == "break": break if count > 5: print("ERROR: Extension Attribute upload did not succeed after 5 attempts") print("\nHTTP POST Response Code: {}".format(r.status_code)) break sleep(10) if verbosity > 1: api_get.get_headers(r) # clean up temp files if os.path.exists(template_xml): os.remove(template_xml)
def upload_script( jamf_url, script_name, script_path, category_id, category_name, script_info, script_notes, script_priority, script_parameter4, script_parameter5, script_parameter6, script_parameter7, script_parameter8, script_parameter9, script_parameter10, script_parameter11, script_os_requirements, verbosity, token, cli_custom_keys, obj_id=None, ): """Update script metadata.""" # import script from file and replace any keys in the script # script_contents = Path(script_path).read_text() with open(script_path, "r") as file: script_contents = file.read() # substitute user-assignable keys script_contents = actions.substitute_assignable_keys( script_contents, cli_custom_keys, verbosity) # priority has to be in upper case. Let's make it nice for the user if script_priority: script_priority = script_priority.upper() # build the object script_data = { "name": script_name, "info": script_info, "notes": script_notes, "priority": script_priority, "categoryId": category_id, "categoryName": category_name, "parameter4": script_parameter4, "parameter5": script_parameter5, "parameter6": script_parameter6, "parameter7": script_parameter7, "parameter8": script_parameter8, "parameter9": script_parameter9, "parameter10": script_parameter10, "parameter11": script_parameter11, "osRequirements": script_os_requirements, "scriptContents": script_contents, } headers = { "authorization": "Bearer {}".format(token), "content-type": "application/json", "accept": "application/json", } # ideally we upload to the object ID but if we didn't get a good response # we fall back to the name if obj_id: url = "{}/uapi/v1/scripts/{}".format(jamf_url, obj_id) script_data["id"] = obj_id else: url = "{}/uapi/v1/scripts".format(jamf_url) http = requests.Session() if verbosity > 2: http.hooks["response"] = [api_connect.logging_hook] print("Script data:") print(script_data) print("Uploading script..") count = 0 script_json = json.dumps(script_data) while True: count += 1 if verbosity > 1: print("Script upload attempt {}".format(count)) if obj_id: r = http.put(url, headers=headers, data=script_json, timeout=60) else: r = http.post(url, headers=headers, data=script_json, timeout=60) if r.status_code == 200 or r.status_code == 201: print("Script uploaded successfully") break if r.status_code == 409: print("ERROR: Script upload failed due to a conflict") break if count > 5: print("ERROR: Script upload did not succeed after 5 attempts") print("\nHTTP POST Response Code: {}".format(r.status_code)) break sleep(10) if verbosity > 1: api_get.get_headers(r) return r