Skip to content

Edit the JSON Files with Schema Support

Firewall rules, IP groups, Application Gateways, WAF policies and spokes are JSON files. Each type has a JSON schema that describes which properties exist, which are required and which values are allowed. An editor that knows the schema (Visual Studio Code does, with a small setting) helps you while you type: it suggests properties, lists the allowed values and underlines mistakes. This page shows how to set it up and how to use it. The runbooks tell you what to put in the files. This page helps you to put it there without mistakes.

Which schemas exist

The pipelines validate the files against the schemas of the code repository, in the config tests that run before every deployment (Pipelines). The same schemas are available to you.

Files Schema (in src/Xebia.Mcp/Files/json/ of the code repository) Folder in the configuration repository
Firewall rule collection groups firewallschema.json firewall_rule_configuration/
Application Gateways appgwschema.json application_gateways/
WAF policies wafpolicyschema.json web_application_firewall_policies/
Spokes spokeschema.json spokes/
IP groups a small schema, see below ip_groups/

Schema names depend on the version

Older how-to guides use other file names for the schemas (for example applicationgatewayschema.json). Use the files of the code version you run. Copy them again after each upgrade, so that the editor does not warn about properties that are valid in the new version.

Bind the schemas to the files

Visual Studio Code links a schema to files by path. Create the file .vscode/settings.json in the root of the configuration repository, and copy the schema files you need next to it (the root of the repository) or to a folder you choose and adapt url:

{
  "json.schemas": [
    {
      "fileMatch": ["/**/firewall_rule_configuration/**/*.json"],
      "url": "./firewallschema.json"
    },
    {
      "fileMatch": ["/**/ip_groups/**/*.json"],
      "url": "./ipgroupschema.json"
    },
    {
      "fileMatch": ["/**/application_gateways/**/*.json"],
      "url": "./appgwschema.json"
    },
    {
      "fileMatch": ["/**/web_application_firewall_policies/**/*.json"],
      "url": "./wafpolicyschema.json"
    }
  ]
}

Each entry says: for every file whose path matches fileMatch, use the schema at url. Open a rule file to check that it works. Open the Problems panel, or type a wrong value on purpose and see whether the editor reacts.

What the editor tells you

Three things help most. Descriptions below are for Visual Studio Code. Other editors with JSON schema support behave in a similar way.

Suggestions for properties. Place the cursor inside an object, for example inside a rule, and press Ctrl+Space. The editor lists the properties that the schema allows there and that you did not add yet. In an empty rule it lists protocols, source_addresses, source_ip_groups, and so on. Use it to find out which properties a rule type needs instead of copying an old rule.

Suggestions for values. Place the cursor behind a property that has a fixed set of values, for example behind "action":, and press Ctrl+Space. The editor lists the allowed values (for a network rule collection Allow and Deny). The same works wherever the schema lists fixed values, for example the FQDN tags of an application rule (WindowsUpdate, AzureBackup, and so on) and the subnet delegations in a spoke file, which has a long list of names.

Validation errors. A property or value that does not fit the schema gets a wavy underline. The colour shows the severity: red is an error, yellow a warning. Hover over the underline to read the reason, or open the Problems panel for the list of all findings in the file. Typical messages:

Message (shortened) Meaning
Missing property "<name>" A required property is absent. The firewall file needs all three collection maps (nat_rule_collections, network_rule_collections, application_rule_collections), also when they are empty.
Value is not accepted. Valid values: ... The value is not in the list. Check the spelling and the capitals (Allow, not allow).
Incorrect type. Expected "array" A list was written as a single value. Write ["443"], not "443".
String does not match the pattern of "..." The text does not follow the required format, for example an IP address or CIDR with a wrong prefix, or a name with characters that are not allowed.
Property <name> is not allowed The property does not exist in this schema, often a typo. Check the spelling before you ignore it.

Two practical tips:

  • Fix the red underlines before you commit. The pipeline fails on them anyway, and a pull request that fails its checks waits for you.
  • Format the file (Shift+Alt+F) before you commit, so that the diff shows only the real change.

What the schema does not check

The schema checks one file in isolation. These checks are done by the config tests of the pipeline, which you can run locally (Run the tests locally):

  • that a referenced IP group exists in an ip_groups folder;
  • that rule collection group priorities are unique per folder, and that NAT priorities are lower than network priorities, which are lower than application priorities;
  • that a rule has only one source type and one destination type;
  • that references in an Application Gateway point to existing keys;
  • that the management group of a spoke exists, and that the spoke environment is in the pipeline list.

Not every combination that the schema accepts is accepted by the Terraform code, and the other way round. In the spoke schema, some keys that the Terraform reads are not described, and a few are rejected (Known issues). When the editor and the pipeline disagree, the pipeline wins.

IP group schema

The IP group file has only two properties. This schema, in JSON schema draft 07, accepts an IPv4 address with an optional prefix length from /0 to /32:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "ip_group": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "cidrs": {
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})\\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})\\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})\\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(?:\\/(3[0-2]|[12]?[0-9]))?$"
          }
        }
      },
      "additionalProperties": false,
      "required": ["name", "cidrs"]
    }
  },
  "additionalProperties": false,
  "required": ["ip_group"]
}

Save it as ipgroupschema.json next to the other schemas. The pattern checks the notation, not the meaning: it does not find an address range that you should not use.