Beispiel #1
0
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)
Beispiel #2
0
def CreateSoftwareIDList(APIEndpoint, apiUser, apiPass):
    logFile = "newpackage.log"
    api = APIEndpoint + "/packages"
    softwareIDList = []
    jssSoftware = requests.get(api,
                               auth=(apiUser, apiPass),
                               headers={"Accept": "application/xml"})
    if jssSoftware.status_code != 200:
        Logging(
            logFile,
            "There was an error connecting with the API with error code: " +
            str(jssSoftware.status_code),
        )
        Logging(logFile, str(jssSoftware.content))
        packageNameList = {}
        return packageNameList
    else:
        numPackagesTree = ElementTree.fromstring(jssSoftware.content)
        counter = 1
        done = "false"
        while done:
            try:
                softwareIDList.append(numPackagesTree[counter][0].text)
                counter = counter + 1
            except:
                done = "true"
                break
        packageNameList = GetPackageName(api, apiUser, apiPass, softwareIDList)
        return packageNameList
Beispiel #3
0
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")
Beispiel #4
0
def ModifyJSON(file, title, newVersion, logFile):
    todayDate = datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")
    JSONFile = open(file, "r")
    JSONDict = json.load(JSONFile)
    JSONFile.close()
    oldVersion = JSONDict.get("version")
    for item in JSONDict:
        if item == "version":
            JSONDict[item] = newVersion
        if item == "releaseDate":
            JSONDict[item] = todayDate
    for item in JSONDict.get("components")[0]:
        if item == "version":
            try:
                JSONDict.get("components")[0][item] = newVersion
            except:
                Logging(
                    logFile,
                    "Unable to get object " +
                    str(JSONDict.get("components")[0][item]),
                )
    try:
        for appCritera in JSONDict.get("components")[0].get("criteria"):
            if appCritera["value"] == oldVersion:
                appCritera["value"] = newVersion
    except:
        Logging(
            logFile,
            "Unable to get object " +
            str(appCritera in JSONDict.get("components")[0].get("criteria")),
        )
    JSONFile = open(file, "w")
    json.dump(JSONDict, JSONFile)
    JSONFile.close()
def CreateBackup(filepath):
    currentDate = datetime.today().strftime("%Y-%m-%d")
    patchPrefs = GetPreferences("PATCH_URL", "PATCH_TOKEN")
    logFile = "patchserver_backup.log"
    backupAPI = patchPrefs["PATCH_URL"] + "/api/v1/backup"
    Logging(logFile, currentDate)
    Logging(logFile, "----------------------------------------")
    Logging(logFile, "Creating backup...")
    response = requests.get(
        backupAPI,
        headers={
            "Authorization": "Bearer " + patchPrefs["PATCH_TOKEN"],
            "Accept": "application/zip",
        },
    )
    if response.status_code != 200:
        Logging(logFile, "Error connecting to patchserver.")
        Logging(logFile, response.status_code)
        Logging(logFile, response.content)
        Logging(logFile, "Patchserver database not backed up.")
    else:
        zipFileName = str(currentDate) + "-patchserver-backup.zip"
        zipFile = open(filepath + zipFileName, "wb")
        zipFile.write(response.content)
        zipFile.close()
        Logging(logFile, "Backup successfully created.")
        Logging(logFile, zipFileName + " saved to " + filepath)
Beispiel #6
0
def Main():
    logfile = "jamfPatchUpdate.log"
    todayDate = str(date.today())
    Logging(logfile,
            "********************" + str(todayDate) + "********************")
    softwareUpdate = GetUpdatedSoftwareVersion()
    if len(softwareUpdate) != 0:
        AddPackageToDefinition(softwareUpdate)
        UpdateTargetVersion(softwareUpdate)
    else:
        Logging(logfile, "No new software updates.")
Beispiel #7
0
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
Beispiel #8
0
def FindUpdatedSoftware(packageList, packageFile):
    logFile = "newpackage.log"
    updatedSoftwareDict = {}
    softwareListPath = GetFileLocation()
    if not softwareListPath.exists():
        os.mkdir(softwareListPath)
    softwareListLog = softwareListPath / packageFile
    if not softwareListLog.exists() or os.stat(softwareListLog).st_size <= 5:
        print("No file exists. Moving on...")
    else:
        softList = open(softwareListLog, "r").readlines()
        for software in packageList:
            try:
                if (str(packageList[software][0] + ":" +
                        str(packageList[software][1]) + "\n") in softList):
                    pass
                else:
                    updatedSoftwareDict[packageList[software]
                                        [0]] = packageList[software][1]
                    Logging(
                        logFile,
                        "updated software: " + packageList[software][0] + " " +
                        str(packageList[software][1]),
                    )
            except:
                pass
    return updatedSoftwareDict
def ManageBackups(filepath):
    logFile = "patchserver_backup.log"
    fileList = os.listdir(filepath)
    try:
        fileList.remove(".DS_Store")
    except:
        print("No DS_Store file present")
    sortedFileList = sorted(fileList, reverse=True)
    print(sortedFileList)
    if len(sortedFileList) > 3:
        print("Deleting oldest backup")
        Logging(logFile, "Deleting oldest backup")
        fileToDelete = sortedFileList.pop()
        os.remove(filepath + "/" + fileToDelete)
        print(fileToDelete + " has been deleted")
        Logging(logFile, fileToDelete + " has been deleted")
        Logging(logFile)
    Logging(logFile, str(filepath))
Beispiel #10
0
def WriteToSoftwareList(packageDict, packageFile):
    logFile = "newpackage.log"
    softwareListPath = GetFileLocation()
    softwareListLog = softwareListPath / packageFile
    if not softwareListPath.exists():
        os.mkdir(softwareListPath)
    softwareListFile = open(softwareListLog, "w+")
    if len(packageDict) == 0:
        Logging(
            logFile,
            "Could not reach the Jamf server. The master list of packages will remain unchanged.",
        )
    else:
        for software in packageDict:
            try:
                softwareListFile.write(packageDict[software][0] + ":" +
                                       str(packageDict[software][1]) + "\n")
            except:
                pass
        Logging(logFile, "The master list of of packages has been updated.")
Beispiel #11
0
def GithubActions(patchRepo, commit=None):
    patchRepo = pathlib.Path(patchRepo)
    logFile = "newpackage.log"
    currentDir = os.getcwd()
    if patchRepo.exists():
        if commit is None:
            Logging(logFile, "Getting updated JSON files")
            os.chdir(patchRepo)
            subprocess.call(["git", "pull"])
            os.chdir(currentDir)
        else:
            Logging(logFile, "Pushing updated JSON back to Github")
            os.chdir(patchRepo)
            subprocess.call(["git", "commit", "-a", "-m", "'daily update'"])
            subprocess.call(["git", "push"])
            os.chdir(currentDir)
    else:
        Logging(
            logFile,
            "Github folder for Jamf Patch files does not exist. Github update failed",
        )
Beispiel #12
0
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]))
Beispiel #13
0
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.")