def UpdatePatchserver(updSftwreDict, log): userPrefs = AutomationPreferences("PATCH_REPO", "PATCH_URL", "PATCH_TOKEN") gitRepo = userPrefs["PATCH_REPO"] patchURL = userPrefs["PATCH_URL"] apiToken = userPrefs["PATCH_TOKEN"] # Make sure the endpoint is pointing to the correct URL for updating if "/api/v1/title" not in patchURL: patchURL = patchURL + "/api/v1/title" GithubActions(gitRepo) for software in updSftwreDict: jsonFilepath = UpdateJSON(software, updSftwreDict[software]) patchServer = patchURL + "/" + software + "/version" if pathlib.Path.exists(jsonFilepath): jsonFile = open(jsonFilepath, "r") patchResponse = requests.post( patchServer, data=jsonFile, headers={ "Content-type": "application/json", "Authorization": "Bearer " + apiToken, }, ) if patchResponse.status_code != 201: Logging( log, software + ": Patch update failed with error code " + str(patchResponse.status_code), ) Logging(log, str(patchResponse.content)) else: Logging(log, str(jsonFilepath) + " doesn't exist.") GithubActions(gitRepo, "commit")
def Main(): userPrefs = AutomationPreferences("JSS_URL", "API_USERNAME", "API_PASSWORD") if "https://" not in userPrefs["JSS_URL"]: userPrefs["JSS_URL"] = "https://" + userPrefs["JSS_URL"] jssApi = userPrefs["JSS_URL"] + "/JSSResource" apiUser = userPrefs["API_USERNAME"] apiPass = userPrefs["API_PASSWORD"] todayDate = date.today() packagesList = "JPSPackages.txt" logFile = "newpackage.log" Logging(logFile, "********************" + str(todayDate) + "********************") packageNames = CreateSoftwareIDList(jssApi, apiUser, apiPass) if len(packageNames) == 0: updatedSoftware = {} else: updatedSoftware = FindUpdatedSoftware(packageNames, packagesList) if len(updatedSoftware) == 0: Logging(logFile, "No Updates") SlackNotification(logFile, "No New Software") WriteToSoftwareList(packageNames, packagesList) else: WriteToSoftwareList(packageNames, packagesList) UpdatePatchserver(updatedSoftware, logFile) Logging(logFile, printLogLocation=True)
def UpdateJSON(title, version): logFile = "JSONUpdate.log" currUser = getuser() userPrefs = AutomationPreferences("PATCH_REPO") try: gitRepo = pathlib.Path(userPrefs["PATCH_REPO"]) except: gitRepo = pathlib.Path("/Users/" + currUser + "/Documents/GitHub") print("No patch repo set. Using default path: " + str(gitRepo)) JSONFile = title + "-patch.json" if pathlib.Path.exists(gitRepo / JSONFile): ModifyJSON(gitRepo / JSONFile, title, version, logFile) SlackNotification( logFile, str(date.today()) + " : " + title + " has been updated to " + version + ". " + title + " has been updated on the patch server", ) Logging(logFile, str(datetime.today()) + ": " + JSONFile + " was updated.") else: JSONFile = JSONFile.replace(" ", "%20") if pathlib.Path.exists(gitRepo / JSONFile): ModifyJSON(gitRepo / JSONFile, title, version, logFile) SlackNotification( logFile, str(date.today()) + " : " + title + " has been updated to " + version + ". " + title + " has been updated on the patch server", ) Logging(logFile, str(datetime.today()) + ": " + JSONFile + " was updated.") else: JSONFile = JSONFile.replace("%20", "") if pathlib.Path.exists(gitRepo / JSONFile): ModifyJSON(gitRepo / JSONFile, title, version, logFile) SlackNotification( logFile, str(date.today()) + " : " + title + " has been updated to " + version + ". " + title + " has been updated on the patch server", ) Logging( logFile, str(datetime.today()) + ": " + JSONFile + " was updated.") else: Logging(logFile, JSONFile + " does not exist.") SlackNotification( logFile, str(date.today()) + " : " + title + " has been updated to " + version + ". Please update patch definitions manually", ) return gitRepo / JSONFile
def GetUpdatedSoftwareVersion(): logPrefs = AutomationPreferences("LOG_LOCATION") tDate = str(date.today()) newPackageFile = open(logPrefs["LOG_LOCATION"] + "/newpackage.log", "r") softwareUpdates = {} for line in newPackageFile: if tDate in line: for software in newPackageFile: if "updated software:" in software: software = software.strip("updated software: ") software = software.rstrip("\n") software = software.rsplit(sep=" ", maxsplit=1) softwareUpdates[software[0]] = software[1] return softwareUpdates
def GetPreferences(*args): userPrefs = {} for item in args: userPrefs.update(AutomationPreferences(item)) return userPrefs
def AddPackageToDefinition(updatedSoftware): logfile = "jamfPatchUpdate.log" jamfPrefs = AutomationPreferences("JSS_URL", "API_USERNAME", "API_PASSWORD") patchURL = jamfPrefs["JSS_URL"] + "/JSSResource/patchsoftwaretitles" pkgSuffix = ".pkg" pkgList = [] for pkg in updatedSoftware: pkgList.append(pkg + "-" + updatedSoftware[pkg] + pkgSuffix) response = requests.get( patchURL, auth=(jamfPrefs["API_USERNAME"], jamfPrefs["API_PASSWORD"]), headers={"Accept": "application/xml"}, ) if response.status_code != 200: Logging(logfile, "Error connecting to Jamf: " + str(response.status_code)) Logging(logfile, str(response.content)) exit() responseTree = ElementTree.fromstring(response.content) for software in updatedSoftware: iterator = 1 software_not_found = False while iterator <= int(responseTree[0].text): if software == responseTree[iterator][0].text: Logging(logfile, "Updating patch policy for " + software) patchTitleResponse = requests.get( patchURL + "/id/" + responseTree[iterator][1].text, auth=(jamfPrefs["API_USERNAME"], jamfPrefs["API_PASSWORD"]), headers={"Accept": "application/xml"}, ) if patchTitleResponse.status_code != 200: Logging( logfile, "There was an error in retrieving XML: " + str(response.status_code), ) Logging(logfile, str(patchTitleResponse.content)) Logging(logfile, patchURL + "/id/" + responseTree[iterator][1].text) else: try: patchTitleTree = ElementTree.fromstring( patchTitleResponse.content) if patchTitleTree[6][0][0].text == updatedSoftware[ software]: for pkg in pkgList: if updatedSoftware[software] in pkg: xmlData = ( "<patch_software_title><versions><version><software_version>" + updatedSoftware[software] + "</software_version><package><name>" + pkg + "</name></package></version></versions></patch_software_title>" ) newResponse = requests.put( patchURL + "/id/" + responseTree[iterator][1].text, auth=( jamfPrefs["API_USERNAME"], jamfPrefs["API_PASSWORD"], ), data=xmlData, headers={ "content-type": "application/xml" }, ) if newResponse.status_code != 201: Logging( logfile, "Update of " + software + " failed with error code: " + str(newResponse.status_code), ) Logging(logfile, newResponse.content) else: Logging( logfile, pkg + " added to definition version " + updatedSoftware[software], ) # UpdateTargetVersion(updatedSoftware[software]) iterator = int(responseTree[0].text) + 50 else: Logging( logfile, "Updated Version does not match the latest version in Jamf.", ) Logging( logfile, "Jamf: " + str(patchTitleTree[6][0][0].text) + " != " + "Updated: " + updatedSoftware[software], ) iterator = int(responseTree[0].text) + 50 except: Logging(logfile, "There was a problem with the XML content") Logging(logfile, str(patchTitleResponse.content)) Logging( logfile, patchURL + "/id/" + responseTree[iterator][1].text) Logging(logfile, xmlData) iterator = iterator + 1 if iterator == int(responseTree[0].text): software_not_found = True if software_not_found: Logging( logfile, "No patch policy found for " + software + " " + str(updatedSoftware[software]), ) print("No patch policy found for " + software + " " + str(updatedSoftware[software]))
def UpdateTargetVersion(updatedSoftware): logfile = "jamfPatchUpdate.log" apiPrefs = AutomationPreferences("API_USERNAME", "API_PASSWORD", "JSS_URL") apiURL = apiPrefs["JSS_URL"] + "/JSSResource/patchpolicies" response = requests.get( apiURL, auth=(apiPrefs["API_USERNAME"], apiPrefs["API_PASSWORD"]), headers={"Accept": "application/xml"}, ) patchPolicyContent = ElementTree.fromstring(response.content) for software in updatedSoftware: counter = 1 Logging(logfile, "Updating target version for " + software) for title in patchPolicyContent: while counter <= int(patchPolicyContent[0].text): softwareTestPolicy = software + " Update Test" if softwareTestPolicy == patchPolicyContent[counter][1].text: patchPolicyID = patchPolicyContent[counter][0].text xmlData = ("<patch_policy><general><target_version>" + updatedSoftware[software] + "</target_version></general></patch_policy>") patchTrgtResponse = requests.put( apiURL + "/id/" + patchPolicyID, auth=(apiPrefs["API_USERNAME"], apiPrefs["API_PASSWORD"]), data=xmlData, headers={"Content-type": "application/xml"}, ) if patchTrgtResponse.status_code != 201: Logging( logfile, software + " target version update failed with response code: " + str(patchTrgtResponse.status_code), ) Logging( logfile, software + " target version " + updatedSoftware[software] + " was not updated to " + patchPolicyContent[counter][1].text, ) SlackNotification( logfile, ":failed: " + patchPolicyContent[counter][1].text + " was not updated. Please update " + patchPolicyContent[counter][1].text + " to " + updatedSoftware[software] + " manually.", ) else: Logging( logfile, patchPolicyContent[counter][1].text + " has been updated to target version " + updatedSoftware[software], ) SlackNotification( logfile, ":white_check_mark: " + patchPolicyContent[counter][1].text + " has been updated to target version " + updatedSoftware[software], ) counter = int(patchPolicyContent[0].text) + 1 else: counter = counter + 1 if counter == int(patchPolicyContent[0].text): Logging(logfile, softwareTestPolicy + " wasn't found.")