Skip to content

Crypt after OS Updates and Upgrades

Rod Christiansen edited this page Oct 25, 2023 · 10 revisions

Updates and upgrades to macOS commonly remove Crypt from authorizationdb. This could lead to unexpected situations, such as the machine not being encrypted on first login, or Crypt losing the ability to force FV2.

For Crypt to function, the following lines must be included in authorizationdb:

<string>Crypt:Check,privileged</string>
<string>Crypt:CryptGUI</string>
<string>Crypt:Enablement,privileged</string>

Presence of these lines can be confirmed via

/usr/bin/security authorizationdb read system.login.console

This can be managed via a configuration management tool (Puppet, Salt, etc), or via the following Munki checkinstall script, which will force a reinstall of Crypt if the authorizationdb entries are absent. If you are using AutoPkg, use the Crypt recipe from Graham's repo which includes this script already. If you are importing manually, be sure to update %version% in the script below to a string with the version of Crypt2 you are deploying with that pkginfo.

#!/Library/ManagedFrameworks/Python/Python3.framework/Versions/Current/bin/python3

"""This installcheck script template evaluates the installed version
of Crypt as well as if Crypt is included properly in the authdb."""

from subprocess import check_output
from packaging import version
import plistlib
import os


def get_mechs():
    """returns a list of all current authdb mechs"""
    cmd = ["/usr/bin/security", "authorizationdb", "read", "system.login.console"]
    cur_mech_plist = plistlib.loads(check_output(cmd))
    mechs_only = cur_mech_plist["mechanisms"]
    return mechs_only


def get_crypt_vers():
    """returns the installed version of the Crypt bundle"""
    try:
        f = open(
            "/Library/Security/SecurityAgentPlugins/Crypt.bundle/Contents/Info.plist",
            "rb",
        )
    except:
        print("Unable to open Crypt bundle to get version")
        exit(0)
    try:
        plist = plistlib.load(f)
    except:
        print("Unable to get plist info from Crypt bundle")
        exit(0)
    f.close()
    return plist["CFBundleShortVersionString"]


def main():
    """Checks if Crypt is properly installed and up to date. Note that the version var
    below is auto-substituted by AutoPkg - if you are adding this installcheck manually,
    be sure to insert the proper version number."""

    pkg_vers = "%version%"

    install_items = [
        "/Library/Security/SecurityAgentPlugins/Crypt.bundle",
        "/Library/LaunchDaemons/com.grahamgilbert.crypt.plist",
        "/Library/Crypt/checkin",
        "/Library/Crypt/python",
        "/Library/Crypt/Python.framework",
        "/Library/Security/SecurityAgentPlugins/Crypt.bundle",
    ]
    for item in install_items:
        if not os.path.exists(item):
            # we are missing a needed file - Crypt is damaged or not installed
            exit(0)

    # check if Crypt is up to date
    installed_vers = get_crypt_vers()
    if version.parse(installed_vers) < version.parse(pkg_vers):
        # we are out of date compared to the pkg version
        exit(0)

    mechs = ["Crypt:Check,privileged", "Crypt:CryptGUI", "Crypt:Enablement,privileged"]
    current_mechs = get_mechs()
    for crypt_mech in mechs:
        if crypt_mech not in current_mechs:
            # mechs are not in place
            exit(0)

    # all mechs in place and version is up to date
    exit(1)


if __name__ == "__main__":
    main()

If you're not using Munki and/or deploying a managed Python 3 runtime, a shell-only method of checking the authorizationdb entries is outlined here.

Clone this wiki locally