Skip to Content
AuthoringJSON Rule Authoring

JSON Rules

JSON rules provide a declarative way to create custom validation rules without writing TypeScript code. They’re ideal for simple pattern-based checks and organization-specific standards.

For comprehensive rule authoring documentation including advanced patterns, all vendor-specific helpers, and complete API reference, see the Rule Authoring Guide  on GitHub.

JSON Rule Schema

Example JSON Rule
{ "id": "ORG-SEC-001", "selector": "interface", "vendor": "cisco-ios", "category": "Organization-Security", "metadata": { "level": "warning", "obu": "Network Security", "owner": "security-team@example.com", "description": "All interfaces must have a description", "remediation": "Add 'description <text>' to the interface configuration" }, "check": { "type": "hasChild", "command": "description", "negate": false } }

Schema Reference

Root Properties

PropertyTypeRequiredDescription
idstringYesUnique rule identifier (e.g., ORG-SEC-001)
selectorstringYesCommand prefix to match (e.g., interface, router bgp)
vendorstring | string[]NoTarget vendor(s). Omit for vendor-agnostic rules
categorystring | string[]NoCompliance framework or category
metadataobjectYesRule metadata and descriptions
checkobjectYesThe validation logic

Metadata Object

PropertyTypeRequiredDescription
level"error" | "warning" | "info"YesSeverity level
obustringYesOrganizational Business Unit
ownerstringYesRule owner contact
descriptionstringNoHuman-readable description
remediationstringNoHow to fix violations
securityobjectNoCWE/CVSS metadata

Check Object

The check object defines the validation logic. SentriFlow supports several check types:

hasChild

Checks if a node has a specific child command.

{ "type": "hasChild", "command": "description", "negate": false }
PropertyTypeDescription
commandstringCommand prefix to look for
negatebooleanIf true, fails when command IS present

hasParam

Checks if a command parameter matches a pattern.

{ "type": "hasParam", "index": 1, "pattern": "^(?!1$).*$", "message": "Native VLAN should not be 1" }
PropertyTypeDescription
indexnumberParameter index (0-based)
patternstringRegex pattern to match
messagestringError message when pattern doesn’t match

matchesPattern

Checks if the full command line matches a regex pattern.

{ "type": "matchesPattern", "pattern": "no ip source-route", "message": "IP source routing should be disabled" }

custom

For complex logic, use the custom type with a JavaScript expression.

{ "type": "custom", "expression": "node.children.some(c => c.id.startsWith('switchport mode'))" }

Custom expressions run in a sandboxed environment with limited access. Only node (current ConfigNode) is available.

Complete Example

Here’s a comprehensive example rule file:

org-rules.json
{ "version": "1.0", "rules": [ { "id": "ORG-IF-001", "selector": "interface", "vendor": ["cisco-ios", "cisco-nxos"], "category": "Documentation", "metadata": { "level": "warning", "obu": "Network Operations", "owner": "netops@example.com", "description": "All physical interfaces must have a description", "remediation": "Add 'description <purpose>' to the interface" }, "check": { "type": "hasChild", "command": "description", "negate": false } }, { "id": "ORG-IF-002", "selector": "interface", "vendor": "cisco-ios", "category": "Security", "metadata": { "level": "error", "obu": "Security", "owner": "security@example.com", "description": "Unused interfaces must be shutdown", "remediation": "Add 'shutdown' to unused interfaces", "security": { "cwe": ["CWE-1188"], "cvssScore": 5.3 } }, "check": { "type": "custom", "expression": "node.children.some(c => c.id === 'shutdown') || node.children.some(c => c.id.startsWith('ip address'))" } }, { "id": "ORG-TRUNK-001", "selector": "interface", "vendor": "cisco-ios", "category": "Network-Segmentation", "metadata": { "level": "error", "obu": "Network Engineering", "owner": "neteng@example.com", "description": "Trunk ports must have explicit allowed VLANs", "remediation": "Add 'switchport trunk allowed vlan <list>'" }, "check": { "type": "custom", "expression": "!node.children.some(c => c.id.includes('switchport mode trunk')) || node.children.some(c => c.id.includes('switchport trunk allowed vlan'))" } } ] }

Using JSON Rules

CLI

# Validate with custom JSON rules sentriflow --json-rules ./org-rules.json configs/ # Multiple rule files sentriflow --json-rules ./security-rules.json --json-rules ./compliance-rules.json configs/

Configuration File

Add to .sentriflow.yml:

.sentriflow.yml
rules: - ./rules/org-security.json - ./rules/pci-compliance.json # Optionally disable default rules disableDefaultRules: rules: - NET-DOC-001 # We have our own documentation rule

VS Code Extension

Configure in VS Code settings:

settings.json
{ "sentriflow.customRules": [ "${workspaceFolder}/rules/org-rules.json" ] }

Rule Development Workflow

Create Rule File

Create a new JSON file with your rules:

mkdir -p rules touch rules/org-security.json

Define Rules

Add rules following the schema above.

Test Rules

Run validation against test configurations:

sentriflow --json-rules ./rules/org-security.json test-configs/

Iterate

Refine selectors and checks based on test results.

Deploy

Add rules to your repository and CI/CD pipeline.

Best Practices

Rule ID Naming

Use a consistent prefix for organization rules:

  • ORG- - General organization rules
  • SEC- - Security-specific rules
  • CMP- - Compliance rules
  • OPS- - Operational rules

Selector Optimization

Use specific selectors to avoid checking irrelevant nodes:

// Good - specific selector "selector": "interface GigabitEthernet" // Acceptable - matches all interfaces "selector": "interface" // Bad - too broad, runs on every node "selector": ""

Error Messages

Write clear, actionable remediation text:

// Good "remediation": "Add 'switchport trunk allowed vlan 100,200,300' to restrict trunk VLANs" // Bad "remediation": "Fix the VLAN configuration"

Troubleshooting

Rule Not Matching

  1. Verify the selector matches your config using AST output:

    sentriflow --ast configs/router.conf | grep -A5 "interface"
  2. Check vendor matches your config file vendor

  3. List loaded rules to verify your rule is included:

    sentriflow --json-rules ./rules.json --list-rules

Custom Expression Errors

Common issues with custom expressions:

  • Expression timeout (>100ms) - simplify logic
  • Undefined variable - only node is available
  • Syntax error - validate JSON and JavaScript syntax

Next Steps

Last updated on