Usage
This page covers running nac-validate and the options shared by both validation stages. How to write a schema is described in Schema Validation, how to write rules in Semantic Validation.
Running Validation
Section titled “Running Validation”nac-validate takes one or more YAML files or directories. Directories are searched recursively for .yaml and .yml files:
nac-validate data/By default, the schema is read from .schema.yaml and the rules from .rules/ in the current directory. If they don’t exist, the respective validation is skipped. Other locations are passed with -s/--schema and -r/--rules, which can be repeated to use rules from several directories:
nac-validate data/ -s schemas/schema.yaml -r rules/ -r custom_rules/All options can also be set with environment variables, listed in the Overview.
Input Data
Section titled “Input Data”Every file is first parsed and validated against the schema on its own. For semantic validation, all files are then merged into a single data structure:
- Maps are merged recursively.
- List items that are maps are merged if all the fields they have in common have the same values. Otherwise, they are added as separate items.
- Other list items are concatenated.
For example, these two files:
fabric: nodes: - id: 101 name: leaf-101fabric: nodes: - id: 101 mgmt_ip: 10.0.0.101/24result in a single node 101 with name and mgmt_ip. If a list in one of the files contains duplicate items, its items are not merged but concatenated. See Merging YAML for details and more examples.
-o/--output writes the merged data to a file, for example to inspect it or to pass it to other tools:
nac-validate data/ -o merged.yamlThe output is only written if the validation passed. Variables and templates of Network as Code architectures that support them (IOS XE, NX-OS, IOS XR and Meraki) are resolved by the Terraform module, not by nac-validate, so the merged output still contains them.
Reading Environment Variables
Section titled “Reading Environment Variables”The !env YAML tag can be used to read values from environment variables.
root: name: !env VAR_NAMEAnsible Vault Support
Section titled “Ansible Vault Support”Values can be encrypted using Ansible Vault and the !vault tag:
password: !vault | $ANSIBLE_VAULT;1.2;AES256;dev 6535616566336139303566666336633163663431306337356461633439626638...This requires Ansible (ansible-core) to be installed and the following two environment variables to be defined:
export ANSIBLE_VAULT_ID=devexport ANSIBLE_VAULT_PASSWORD=Password123ANSIBLE_VAULT_ID is optional, and if not defined will be omitted. Ansible Vault is not supported on Windows.
Exit Codes
Section titled “Exit Codes”nac-validate uses distinct exit codes so CI pipelines can distinguish between failure types:
| Code | Meaning |
|---|---|
| 0 | Validation passed |
| 1 | Semantic validation failed (rule violations) |
| 2 | Syntax validation failed (YAML syntax or schema errors) |
| 3 | Configuration error (e.g. missing schema, invalid schema or rules, a rule raising an exception) |
Output Formats
Section titled “Output Formats”By default, results are printed as text with colors, followed by a summary. --no-color (or the NO_COLOR environment variable) disables colors, and --compact omits the explanations and recommendations of rules.
-f json/--format json prints the results as JSON to stdout, for example for CI/CD integration:
nac-validate data/ -s schema.yaml -r rules/ --format json{ "syntax_errors": [], "semantic_errors": [ { "rule_id": "101", "description": "Verify interfaces reference existing nodes", "severity": "HIGH", "errors": [ { "message": "Node 103 of interface eth1/3 is not defined", "path": "fabric.interfaces[node_id=103,name=eth1/3].node_id", "details": { "node_id": 103 } } ], "title": "Interface references unknown node", "explanation": "Every interface must belong to a node defined under fabric.nodes.", "recommendation": "Add the node to fabric.nodes or fix the node_id of the interface." } ]}Syntax errors are listed with their file and message:
{ "syntax_errors": [ { "file": "data/nodes.yaml", "message": "fabric.nodes.[name=leaf-102].role: 'border' not in ('leaf', 'spine')" } ], "semantic_errors": []}Configuration errors are reported in an additional error field.
Listing Schema and Rules
Section titled “Listing Schema and Rules”--list-artifacts shows the schema and the rules that would be used, without validating any data:
$ nac-validate --list-artifacts
Artifact Layers (highest priority first): schema .schema.yaml, rules .rules [local]
Effective Schema: .schema.yaml [local]
Available Validation Rules:────────────────────────────────────────────────────────────────────────────────
[101] Verify interfaces reference existing nodes (HIGH) [local]
────────────────────────────────────────────────────────────────────────────────Total: 1 rulesRules are read from their source code without executing them.
Pre-Commit Hook
Section titled “Pre-Commit Hook”The tool can be integrated via a pre-commit hook with the following config (.pre-commit-config.yaml), assuming the default values (.schema.yaml, .rules/) are appropriate:
repos: - repo: https://github.com/netascode/nac-validate rev: v2.1.0 hooks: - id: nac-validateIn case the schema or validation rules are located somewhere else the required CLI arguments can be added like this:
repos: - repo: https://github.com/netascode/nac-validate rev: v2.1.0 hooks: - id: nac-validate args: - '-s' - 'my_schema.yaml' - '-r' - 'rules/'Packaged Schema and Rules (Experimental)
Section titled “Packaged Schema and Rules (Experimental)”Besides the local --schema and --rules paths, schema and rules can be packaged with the Terraform module of a Network as Code architecture or distributed as bundles. Loading them is enabled with --artifacts (or NAC_VALIDATE_ARTIFACTS=true), and also by passing --bundle or --module-dir:
nac-validate --artifacts data/Schema and rules are combined from the following layers, highest priority first:
- Local:
--schema/--rules, or the.schema.yamland.rules/defaults - Bundle: every
.zip,.tar.gzor.tgzarchive and every directory in the project’snac/bundles/(or the paths given with--bundle), withmanifest.yaml,schema.yamlandrules/at its root - Module: the
nac/directory (nac/schema.yaml,nac/rules/) of the Terraform module installed byterraform init(or the one given with--module-dir)
The schema of the highest layer providing one is used. A rule replaces rules with the same ID from lower layers. Rules of bundles and modules can be disabled by ID in nac/overrides.yaml:
disable: rules: - "101"The project directory is the current working directory: nac/bundles/, nac/overrides.yaml and the .terraform/ directory (or TF_DATA_DIR) are looked up there, so run nac-validate from the root module directory. --list-artifacts shows the layers in use and the origin of each rule.
Rules are Python code executed by nac-validate, so bundles and modules require the same trust as code in your own repository. Review them with --list-artifacts before enabling --artifacts, and note that a module update (terraform init -upgrade) or a new file in nac/bundles/ changes which code runs.