.. _environment: ===================== Execution Environment ===================== Script Basics ------------------------------------ Input ~~~~~ When your script is run, it is given raw output from the command and other metadata. Scripts should rely primarily on the `ctx` argument they receive, which is an instance of :class:`~utils.context.Context`. For backwards compability, `raw_output` and `questions` are directly available, but :attr:`utils.context.Context.raw` and :meth:`utils.context.Context.answer` should be prefered in new scripts. Output ~~~~~~ Your script should output the desired result to standard output, typically using `print()`. Standard error will also be captured, although Xylok may use that in the future to detect errors. If a script needs to exit early, a standard Python `return` is the best approach. `os.exit()` may result in unexpected behavior. If the postprocessing script has enough information to definitively determine if the output indicates a finding or not, it may use the helper utilties in :mod:`utils.recommendations`, which are imported by default. If uncaptured exceptions occur during your script's execution, they will be displayed in the script output. Line numbers will *not* correspond to your script--they come from the larger :ref:`Script Wrapper` that your script runs in. Modules ~~~~~~~ By default, nothing is imported; this script should import standard library modules as needed. There are also a helper utilities modules and some third-party modules available. See :ref:`Python Version and Modules` for more information. Script Wrapper ~~~~~~~~~~~~~~ The script entered as a post-processing script gets dropped into a script that looks roughly like: .. code:: python from utils.recommendations import * from utils.context import Context context = json.loads(r'''{...context data...}''') context = Context(**context) def the_actual_pp_script(ctx, raw_output, questions): # BEGIN CUSTOM CODE ############ YOUR CODE HERE ################## # END CUSTOM CODE the_actual_pp_script(context, context.raw, context.questions) print_recommendations() Postprocessing code should rely only on the arguments passed into `the_actual_pp_script` and the fact that :ref:`Recommendations` are imported by default. Python Version and Modules ------------------------------------ Base Environment ~~~~~~~~~~~~~~~~~~~~~~~~ Post-processing scripts run in a Python 3.7 environment, with all of the standard library available. Two things to keep in mind when developing scripts: - Never assume files on disk will last beyond the life of your script. - Never use network resources--Xylok is typically used without Internet access. All functions in the recommendations module are imported by default (`from utils.recommendations import *`) and can be used without an explicit import in the postprocessing script. Third-Party Modules ~~~~~~~~~~~~~~~~~~~~~~~~ In addition to the Python standard library, the following modules are installed and available to post-processing scripts: - terminaltables_ - ciscoconfparse_ (prefer Xylok's networkparse) - networkparse_ = ">=0.7.0" See their respective documentation for more information. .. _terminaltables: https://robpol86.github.io/terminaltables/ .. _ciscoconfparse: http://www.pennington.net/py/ciscoconfparse/ .. _networkparse: https://networkparse.readthedocs.io/en/latest/ Utilities Modules ~~~~~~~~~~~~~~~~~~~~~~~~ The post-processor also ships with a `utils` module that includes tools specific to the needs of PP scripts. These functions are documented in detail in the :ref:`Utility Modules`.