skip to content

Declarative Plans

One file names an environment and an ordered list of jobs, and the run is whatever that file says. The catch is that most job types only exist because some add-on happens to be installed.

on this pageshow

questions

5

In ZAP's automation framework, what does a plan file contain and what decides the order the work runs in?

level: middleimportance: must knowfreq 60%

answer

  1. two top-level keys, one file
  2. environment first, then work
  3. the list is the sequence
  4. env plus jobs, top to bottom

basics

~20 s

A ZAP automation plan is a YAML file with two parts: env, which names the environment the run acts on, and jobs, an ordered list of units of work. Jobs run top to bottom, in the order written.

solid answer

~40 s

The `automation` add-on reads a YAML plan with two top-level keys. `env` is mandatory and describes what the run acts on: contexts, plus `vars`, `configs` and `parameters` that govern the run as a whole. `jobs` is an ordered list; each entry carries a `type` naming what to do, optional `name`, `enabled`, `alwaysRun`, a `parameters` block and a `tests` block. There is no dependency graph and no job categories at run time: the list is executed top to bottom exactly as written, so putting a job that waits for passive scanning before anything has been crawled simply wastes the wait. `-autorun` runs the file, and the sequence performed is the sequence written there.

code

yaml · 14 lines
yaml
env:
  contexts:
    - name: target
      urls:
        - https://example.com/
  parameters:
    failOnError: true

jobs:
  - type: spider
    parameters:
      context: target
  - type: passiveScan-wait
  - type: report

go deeper

for a junior

Recall the two halves of the file: env describes what is being tested, jobs lists what to do. Be able to point at where the target URL goes and where a job's type goes.

for a middle

Explain that job order is file order, that env is mandatory while jobs is not, and what each of type, name, enabled and alwaysRun does on a job entry.

for a senior

Show that you treat the plan as reviewable configuration: you would catch an empty job list, an ordering that wastes a wait, and a disabled job still shaping the run's outcome, before any of them reached a pipeline.

for a principal

Own the argument for declaring a run in a file at all — one reviewable artefact per pipeline, diffable and portable — and say what has to sit outside it, such as credentials and the decision about which environment may be attacked.

## The shape of the file A ZAP automation plan is one YAML document read by the **`automation` add-on**. It has two top-level keys and the add-on reads only those two: - **`env`** — the environment. It is **mandatory**: if the key is absent, the plan records `Missing environment.` as an error. - **`jobs`** — an ordered list of the units of work to perform. Anything else you write at the top level is **silently ignored** — the loader reaches for `env` and `jobs` by name and never enumerates the rest of the document. That is worth knowing because the rule is the opposite one level down: an element inside `env` that the framework does not recognise is reported as an **error**, not ignored. ## What `env` carries `env` describes what the jobs act on and how the plan as a whole behaves: - **`contexts`** — the named targets the jobs refer to by name. At least one context, with at least one URL, is required; an empty environment is an error. - **`vars`** — plan-level variables, substituted into URLs and many parameters. - **`configs`** — generic configuration keys applied to the running program before the first job, the same keys the `-config` command-line option takes. - **`parameters`** — the run-wide switches: `failOnError`, `failOnWarning`, `continueOnFailure`, `progressToStdout` and `maxDuration`. ## What a job entry carries Each element of `jobs` is a map. Only `type` is required: | key | what it does | |---|---| | `type` | names the job; looked up in a registry the installed add-ons populate | | `name` | a label used in output and in job tests; defaults to the type | | `enabled` | when `false`, the job is skipped at run time (but still verified at load) | | `alwaysRun` | when `true`, the job still runs after the plan has decided to stop early | | `parameters` | the job's own settings; unrecognised names are reported | | `tests` | job outcome tests — `alert`, `stats`, `url` or `monitor` | ## Order is the order you wrote The single most common misreading is that the framework sorts the work for you. It does not. The list is executed **top to bottom exactly as it appears in the file**. The add-on does maintain a notion of job category — exploration before attack before reporting — but that ordering is used to lay out the templates the `-autogen*` options write and to place jobs added through the desktop, **not** to reorder a plan you hand it. So: 1. A job that waits for passive scanning to drain, placed before anything has crawled the site, waits for nothing. 2. A job that configures how findings are filtered, placed after the scanning jobs, does not reach the findings those jobs already raised. 3. A job that sets the exit value, placed anywhere but last, reports on a run that has not finished. The reader's job is to write the sequence, not to trust one. ## The two silences that cost pipelines Two plan shapes load cleanly, run, and tell you nothing is wrong: - **`jobs` absent or empty.** The loader takes a missing job list as "nothing to do" and records no error at all. The environment is created, no work happens, and the run ends clean. A plan that lost its job list in a bad merge is a **green pipeline that scanned nothing**. - **A disabled job.** `enabled: false` skips the work but not the load-time verification of that job, so a disabled job can still contribute a warning to the run's outcome. Because of the first, a plan is worth asserting on rather than trusting: either a job outcome test that requires evidence of work, or a pipeline step that reads the run's own output. ## Running it The plan is handed to the program with **`-autorun <source>`**, where the source is a file path or an `http`/`https` URL. **`-autocheck <source>`** loads and validates the same file without running any of it. The `-autogenmin` and `-autogenmax` options write a starting template — composed from the job types the running build actually has — and `-autogenconf` writes one reflecting the current configuration. ## Why the shape matters The plan is the whole interface. There is no hidden default sequence and no implicit target: the run is the ordered list the file names, against the environment the file names. What the file cannot settle is what the build under it makes available, which is a separate problem. That makes a plan reviewable in a pull request the way a build file is — and it makes every silence in it, including an empty job list, your responsibility rather than the tool's.

  • Does the framework reorder the jobs it is given?
    No. The job list is executed in file order. The add-on's notion of job category is used when it writes a template for you and when a job is added through the desktop, but a plan you author is run exactly as written — including an order that makes no sense.
  • What happens if the `jobs` key is missing entirely?
    Nothing is recorded as wrong. The loader treats an absent job list as nothing to do, the environment is still created, and the run ends with a clean exit value. A plan that lost its jobs still reports success, which is why a plan deserves an assertion that work actually happened.
  • Where do relative file paths inside a plan resolve from?
    Against the directory holding the plan file, which keeps a plan portable between a workstation and a container. A plan fetched from a URL has no file on disk, so its relative paths fall back to the process working directory instead.

saying these in an interview costs you the question

  • Thinks the framework sorts jobs into a sensible order
  • Assumes an empty job list is reported as an error
  • Calls env optional because jobs name their own targets
  • Reads the job list as a set of options rather than a sequence
  • Expects an unknown top-level key to be rejected
open as a page

What is the difference between running a ZAP automation plan with -autorun and checking it with -autocheck?

level: juniorimportance: should knowfreq 50%

basics

~20 s

-autorun loads a plan, creates its environment and runs its jobs. -autocheck loads and validates the same plan and stops there, running none of it. Both accept a file path or an http/https URL as the source.

open as a page

In a ZAP plan's env.parameters, what do failOnError, failOnWarning and continueOnFailure actually control?

level: seniorimportance: should knowfreq 42%

basics

~20 s

failOnError, failOnWarning and continueOnFailure control only whether a ZAP plan abandons the jobs it has not yet run. They do not set the exit value, which comes from whether any error or warning was recorded.

open as a page

A ZAP automation plan names a job type the installed build does not ship. What happens to the run?

level: seniorimportance: should knowfreq 45%

basics

~20 s

A ZAP plan naming a job type no installed add-on registers fails while it loads, with Unrecognised job type recorded as an error. The run then stops before any job executes: the environment is created and nothing else.

open as a page

What are the four job outcome tests a ZAP automation plan can attach to a job, and how do they differ?

level: middleimportance: nice to knowfreq 38%

basics

~20 s

A ZAP plan job can carry alert, stats, url and monitor tests. The first three are judged after the job finishes; monitor is judged while it runs and can stop a long job early. Each needs onFail.

open as a page