Skip to content

Instantly share code, notes, and snippets.

@lazymutt
Last active May 3, 2023 08:01
Show Gist options
  • Save lazymutt/5a3e7b3631b073db5529722f857f54aa to your computer and use it in GitHub Desktop.
Save lazymutt/5a3e7b3631b073db5529722f857f54aa to your computer and use it in GitHub Desktop.
parses update versions, some managed by `sudo softwareupdate --background-critical`, ported from an applescript found at https://www.jamf.com/jamf-nation/discussions/19111/xprotect-status-extension-attribute
#!/usr/bin/python
# Copyright (c) 2019 University of Utah Student Computing Labs. ################
# All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appears in all copies and
# that both that copyright notice and this permission notice appear
# in supporting documentation, and that the name of The University
# of Utah not be used in advertising or publicity pertaining to
# distribution of the software without specific, written prior
# permission. This software is supplied as is without expressed or
# implied warranties of any kind.
################################################################################
# report_critical_update_versions.py ###########################################
# 07/12/19, v0.4, todd.mcdaniel@utah.edu
#
# works with Python 2 or 3
#
# more of a learning experience than a useful product.
# ported from an applescript found here:
# https://www.jamf.com/jamf-nation/discussions/19111/xprotect-status-extension-attribute
# parses update versions, some managed by `sudo softwareupdate --background-critical`
#
################################################################################
from __future__ import print_function
import datetime
import os
import subprocess
import sys
def main():
# format for update description:
# update title, file for date calculation, file for version discovery, version command to use
py2 = False
py3 = False
if sys.version_info[0] == 2:
py2 = True
elif sys.version_info[0] == 3:
py3 = True
updates = [
["XProtect", "/System/Library/CoreServices/XProtect.bundle/Contents/Resources/XProtect.meta.plist", "/System/Library/CoreServices/XProtect.bundle/Contents/Resources/XProtect.meta.plist", "Version"],
["Gatekeeper", "/private/var/db/gkopaque.bundle/Contents/version.plist", "/private/var/db/gkopaque.bundle/Contents/version.plist", "CFBundleShortVersionString"],
["SIP", "/System/Library/Sandbox/Compatibility.bundle/Contents/version.plist", "/System/Library/Sandbox/Compatibility.bundle/Contents/version.plist", "CFBundleShortVersionString"],
["MRT", "/System/Library/CoreServices/MRT.app/Contents/version.plist", "/System/Library/CoreServices/MRT.app/Contents/version", "CFBundleShortVersionString"],
["Core Suggestions", "/System/Library/Intelligent Suggestions/Assets.suggestionsassets/Contents/version.plist", "/System/Library/Intelligent Suggestions/Assets.suggestionsassets/Contents/version.plist", "CFBundleShortVersionString"],
["Incompatible Kernel Ext.", "/System/Library/Extensions/AppleKextExcludeList.kext/Contents/version.plist", "/System/Library/Extensions/AppleKextExcludeList.kext/Contents/version", "CFBundleShortVersionString"],
["Chinese Word List", "/usr/share/mecabra/updates/com.apple.inputmethod.SCIM.bundle/Contents/version.plist", "/usr/share/mecabra/updates/com.apple.inputmethod.SCIM.bundle/Contents/info", "SUVersionString"],
["Core LSKD (dkrl)", "/usr/share/kdrl.bundle/info.plist", "/usr/share/kdrl.bundle/info", "CFBundleVersion"]
]
print("-" * 50)
print("| {:<24} | {} | {:>6}|".format("Name", "Dated", "Version"))
for _, data in enumerate(updates):
print("|" + "-" * 26 + "+" + "-" * 12 + "+" + "-" * 8 + "|")
version_number = ""
try:
mod_time = datetime.datetime.fromtimestamp(os.path.getmtime(data[1]))
formatted_modtime = mod_time.strftime('%Y.%m.%d')
try:
version_string = subprocess.check_output(["defaults", "read", data[2], data[3]])
if py2:
version_number = version_string.strip()
if py3:
version_number = str(version_string.strip(), 'utf-8')
except Exception as this_exception:
print(this_exception)
print("| {:<24} | {} | {:>6} |".format(data[0], formatted_modtime, version_number))
except OSError:
formatted_modtime = "Deprecated/missing."
print("| {:<24} | {} |".format(data[0], formatted_modtime))
print("-" * 50)
if __name__ == '__main__':
main()
@lazymutt
Copy link
Author

Sample output of new release:

--------------------------------------------------
| Name                     | Dated      | Version|
|--------------------------+------------+--------|
| XProtect                 | 2019.04.26 |   2103 |
|--------------------------+------------+--------|
| Gatekeeper               | 2019.07.12 |    172 |
|--------------------------+------------+--------|
| SIP                      | 2019.02.22 |   15.0 |
|--------------------------+------------+--------|
| MRT                      | 2019.07.15 |   1.46 |
|--------------------------+------------+--------|
| Core Suggestions         | Deprecated/missing. |
|--------------------------+------------+--------|
| Incompatible Kernel Ext. | 2019.04.10 | 14.5.1 |
|--------------------------+------------+--------|
| Chinese Word List        | Deprecated/missing. |
|--------------------------+------------+--------|
| Core LSKD (dkrl)         | 2019.02.28 |      8 |
--------------------------------------------------

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment