Rule Engine API
The rule engine evaluates validation rules against parsed configuration nodes. This page covers the API for running rules programmatically.
Installation
npm install @sentriflow/core
npm install @sentriflow/rules-default # Optional: default rulesBasic Usage
import { SchemaAwareParser, RuleEngine } from '@sentriflow/core';
import { allRules } from '@sentriflow/rules-default';
const config = `
hostname Router1
interface GigabitEthernet0/0
ip address 192.168.1.1 255.255.255.0
`;
const parser = new SchemaAwareParser();
const nodes = parser.parse(config);
const engine = new RuleEngine();
const results = engine.run(nodes, allRules);
for (const result of results) {
if (!result.passed) {
console.log(`[${result.level}] ${result.ruleId}: ${result.message}`);
}
}SchemaAwareParser
The SchemaAwareParser class parses configuration text into an array of ConfigNode objects.
Signature
class SchemaAwareParser {
parse(config: string): ConfigNode[]
}Example
import { SchemaAwareParser } from '@sentriflow/core';
const config = loadConfig('./router.conf');
const parser = new SchemaAwareParser();
const nodes = parser.parse(config);
console.log(`Parsed ${nodes.length} configuration nodes`);RuleEngine
The RuleEngine class evaluates rules against parsed configuration nodes.
Constructor
const engine = new RuleEngine();run()
Evaluate rules against parsed configuration nodes.
Signature
class RuleEngine {
run(nodes: ConfigNode[], rules: IRule[]): RuleResult[]
}Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
nodes | ConfigNode[] | Yes | Parsed configuration nodes |
rules | IRule[] | Yes | Rules to evaluate |
Returns
Returns an array of RuleResult objects.
Example
import { SchemaAwareParser, RuleEngine } from '@sentriflow/core';
import { allRules, getRulesByVendor } from '@sentriflow/rules-default';
const config = loadConfig('./router.conf');
const parser = new SchemaAwareParser();
const nodes = parser.parse(config);
const engine = new RuleEngine();
// Evaluate all rules
const allResults = engine.run(nodes, allRules);
// Evaluate only Cisco rules
const ciscoRules = getRulesByVendor('cisco-ios');
const ciscoResults = engine.run(nodes, ciscoRules);RuleResult Interface
interface RuleResult {
/** Whether the rule check passed */
passed: boolean;
/** Result message */
message: string;
/** Rule ID that generated this result */
ruleId: string;
/** Node ID that was checked */
nodeId: string;
/** Severity level */
level: 'error' | 'warning' | 'info';
/** Optional remediation text */
remediation?: string;
/** Source location */
loc?: {
startLine: number;
endLine: number;
};
}Working with Rules
Using Default Rules
import { allRules, getRulesByVendor } from '@sentriflow/rules-default';
// All built-in rules
console.log(`Total rules: ${allRules.length}`);
// Filter rules by vendor
const ciscoRules = getRulesByVendor('cisco-ios');
const juniperRules = getRulesByVendor('juniper');Custom Rule Definition
Define custom rules programmatically:
import { SchemaAwareParser, RuleEngine } from '@sentriflow/core';
import type { IRule } from '@sentriflow/core';
const customRule: IRule = {
id: 'ORG-SEC-001',
selector: 'interface',
vendor: 'cisco-ios',
metadata: {
level: 'warning',
obu: 'Security',
owner: 'security@example.com',
description: 'Custom security check',
},
check(node) {
// Validation logic
return { passed: true, /* ... */ };
},
};
const parser = new SchemaAwareParser();
const nodes = parser.parse(config);
const engine = new RuleEngine();
const results = engine.run(nodes, [customRule]);Combining Rules
import { SchemaAwareParser, RuleEngine } from '@sentriflow/core';
import { allRules } from '@sentriflow/rules-default';
import type { IRule } from '@sentriflow/core';
const customRules: IRule[] = [
// Your custom rules here
];
const parser = new SchemaAwareParser();
const nodes = parser.parse(config);
const engine = new RuleEngine();
const results = engine.run(nodes, [...allRules, ...customRules]);Rule Packs
Load rules from rule packs:
import { loadRulePack, SchemaAwareParser, RuleEngine } from '@sentriflow/core';
// Load from file
const pack = await loadRulePack('./custom-rules.json');
// Use with engine
const parser = new SchemaAwareParser();
const nodes = parser.parse(config);
const engine = new RuleEngine();
const results = engine.run(nodes, pack.rules);Complete Example
import { SchemaAwareParser, RuleEngine } from '@sentriflow/core';
import { allRules, getRulesByVendor } from '@sentriflow/rules-default';
import * as fs from 'fs';
// Load configuration
const config = fs.readFileSync('./router.conf', 'utf-8');
// Parse configuration
const parser = new SchemaAwareParser();
const nodes = parser.parse(config);
// Get vendor-specific rules
const ciscoRules = getRulesByVendor('cisco-ios');
// Evaluate rules
const engine = new RuleEngine();
const results = engine.run(nodes, ciscoRules);
// Process results
const failures = results.filter(r => !r.passed);
const errors = failures.filter(r => r.level === 'error');
const warnings = failures.filter(r => r.level === 'warning');
console.log(`Found ${errors.length} errors, ${warnings.length} warnings`);
for (const result of failures) {
console.log(`[${result.level}] ${result.ruleId}: ${result.message}`);
if (result.loc) {
console.log(` at lines ${result.loc.startLine}-${result.loc.endLine}`);
}
if (result.remediation) {
console.log(` fix: ${result.remediation}`);
}
}Performance Tips
- Filter rules by vendor before evaluation using
getRulesByVendor() - Only include rules you need - smaller rule sets evaluate faster
- Reuse parser and engine instances when processing multiple configurations
Next Steps
- Parser API - Parsing configurations
- ConfigNode API - Working with AST
- TypeScript Rules - Creating custom rules
Last updated on