diff --git a/CHANGELOG.md b/CHANGELOG.md index e2164c0..7114d69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [1.9.0] - 2021-01-18 + +### Added +- Added check for any unexpected processor arguments in any AutoPkg processor. + +### Removed +- CodeSignatureVerifier processor argument verification (added in v1.8.2) has been replaced by the above. ## [1.8.2] - 2021-01-18 diff --git a/README.md b/README.md index 7102771..1011165 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ For any hook in this repo you wish to use, add the following to your pre-commit ```yaml - repo: https://github.com/homebysix/pre-commit-macadmin - rev: v1.8.2 + rev: v1.9.0 hooks: - id: check-plists # - id: ... @@ -52,7 +52,7 @@ After adding a hook to your pre-commit config, it's not a bad idea to run `pre-c - __check-autopkg-recipes__ - This hook checks AutoPkg recipes to ensure they meet various requirements. + This hook checks AutoPkg recipes to ensure they meet various requirements and conventions. - Optionally specify your preferred AutoPkg recipe and/or override prefix, if you wish to enforce them: `args: ['--override-prefix=com.yourcompany.autopkg.']` @@ -65,7 +65,7 @@ After adding a hook to your pre-commit config, it's not a bad idea to run `pre-c (default: `1.0.0`) Specifying `0.1.0` will not ignore any MinimumVersion mismatches. - - If you're a purist, you can also enable strict mode. This enforces recipe type conventions, all processor/MinimumVersion mismatches, and forbids `` style comments. + - If you're a purist, you can also enable strict mode. This enforces recipe type conventions, all processor/MinimumVersion mismatches, forbids `` style comments, and ensures all processor input variables (arguments) are valid. `args: ['--strict']` (default: False) @@ -121,7 +121,7 @@ When combining arguments that take lists (for example: `--required-keys`, `--cat ```yaml - repo: https://github.com/homebysix/pre-commit-macadmin - rev: v1.8.2 + rev: v1.9.0 hooks: - id: check-munki-pkgsinfo args: ['--catalogs', 'testing', 'stable', '--'] @@ -131,7 +131,7 @@ But if you also use the `--categories` argument, you would move the trailing `-- ```yaml - repo: https://github.com/homebysix/pre-commit-macadmin - rev: v1.8.2 + rev: v1.9.0 hooks: - id: check-munki-pkgsinfo args: ['--catalogs', 'testing', 'stable', '--categories', 'Design', 'Engineering', 'Web Browsers', '--'] @@ -143,7 +143,7 @@ If it looks better to your eye, feel free to use a multi-line list for long argu ```yaml - repo: https://github.com/homebysix/pre-commit-macadmin - rev: v1.8.2 + rev: v1.9.0 hooks: - id: check-munki-pkgsinfo args: [ diff --git a/pre_commit_hooks/check_autopkg_recipes.py b/pre_commit_hooks/check_autopkg_recipes.py index 5a01c9f..09984e0 100755 --- a/pre_commit_hooks/check_autopkg_recipes.py +++ b/pre_commit_hooks/check_autopkg_recipes.py @@ -4,7 +4,10 @@ requirements.""" import argparse +import os import plistlib +import sys +from contextlib import contextmanager from distutils.version import LooseVersion from xml.parsers.expat import ExpatError @@ -15,6 +18,29 @@ ) +# Import AutoPkg libraries, but ignore any warnings generated by the import. +@contextmanager +def suppress_stdout(): + with open(os.devnull, "w") as devnull: + old_stdout = sys.stdout + sys.stdout = devnull + try: + yield + finally: + sys.stdout = old_stdout + + +sys.path.append("/Library/AutoPkg") +try: + with suppress_stdout(): + from autopkglib import get_processor, processor_names + + HAS_AUTOPKGLIB = True +except ImportError: + # Silently skip checks that require autopkglib. + HAS_AUTOPKGLIB = False + + def build_argument_parser(): """Build and return the argument parser.""" @@ -148,26 +174,6 @@ def validate_endofcheckphase(process, filename): return passed -def validate_codesignatureverifier(process, filename): - """Ensure CodeSignatureVerifier uses correct arguments.""" - - passed = True - csv_args = [ - x.get("Arguments") - for x in process - if x.get("Processor") == "CodeSignatureVerifier" - ] - if csv_args: - if "requirements" in csv_args[0]: - print( - '{}: Found unexpected key "{}" in ' - "CodeSignatureVerifier arguments.".format(filename, "requirements") - ) - passed = False - - return passed - - def validate_minimumversion(process, min_vers, ignore_min_vers_before, filename): """Ensure MinimumVersion is set appropriately for the processors used.""" @@ -388,6 +394,56 @@ def validate_required_proc_for_types(process, filename): return passed +def validate_proc_args(process, filename): + """Warn if invalid processor arguments are used.""" + + passed = True + + # List of argument names (lowercase) that will not be flagged as invalid. + ignored_args = ("note", "notes", "comment", "comments") + + # Create dictionary of AutoPkg core processors and their inputs. + core_procs = {} + for proc in processor_names(): + if hasattr(get_processor(proc), "input_variables"): + core_procs[proc] = get_processor(proc).input_variables + else: + core_procs[proc] = {} + + for proc in process: + if proc["Processor"] not in core_procs: + # Skip input variable validation for non-core processors. + continue + for arg in proc.get("Arguments", {}): + if arg.lower() in ignored_args: + # Skip args in ignored list above. + continue + + if not core_procs[proc["Processor"]]: + print( + "{}: Unknown argument {} for processor {}, " + "which does not accept any arguments.".format( + filename, + arg, + proc["Processor"], + ) + ) + passed = False + elif arg not in core_procs[proc["Processor"]]: + print( + "{}: Unknown argument {} for processor {}. " + "Allowed arguments are: {}".format( + filename, + arg, + proc["Processor"], + ", ".join(core_procs[proc["Processor"]]), + ) + ) + passed = False + + return passed + + def main(argv=None): """Main process.""" @@ -482,9 +538,6 @@ def main(argv=None): if not validate_endofcheckphase(process, filename): retval = 1 - if not validate_codesignatureverifier(process, filename): - retval = 1 - if not validate_no_var_in_app_path(process, filename): retval = 1 @@ -500,6 +553,10 @@ def main(argv=None): if not validate_no_superclass_procs(process, filename): retval = 1 + if HAS_AUTOPKGLIB: + if not validate_proc_args(process, filename): + retval = 1 + if args.strict: if not validate_proc_type_conventions(process, filename): retval = 1 diff --git a/setup.py b/setup.py index e0ba07d..9e13a28 100755 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ name="pre-commit-macadmin", description="Pre-commit hooks for Mac admins, client engineers, and IT consultants.", url="https://github.com/homebysix/pre-commit-macadmin", - version="1.8.2", + version="1.9.0", author="Elliot Jordan", author_email="elliot@elliotjordan.com", packages=["pre_commit_hooks"],