1
0
Fork 0
salty-dog/src/rule.ts

92 lines
2.1 KiB
TypeScript
Raw Normal View History

2019-06-15 22:53:07 +00:00
import * as Ajv from 'ajv';
import { readFile } from 'fs';
2019-06-15 22:53:07 +00:00
import { JSONPath } from 'jsonpath-plus';
import { intersection } from 'lodash';
import { LogLevel } from 'noicejs';
import { promisify } from 'util';
import { safeLoad } from 'js-yaml';
import { CONFIG_SCHEMA } from './config';
const readFileSync = promisify(readFile);
export interface Rule {
level: LogLevel;
name: string;
nodes: {
filter: string;
select: string;
};
schema: any;
tags: Array<string>;
}
export interface RuleSelector {
excludeLevel: Array<LogLevel>;
excludeName: Array<string>;
excludeTag: Array<string>;
includeLevel: Array<LogLevel>;
includeName: Array<string>;
includeTag: Array<string>;
}
export async function loadRules(paths: Array<string>): Promise<Array<Rule>> {
const rules = [];
for (const path of paths) {
const contents = await readFileSync(path, {
encoding: 'utf-8',
});
const data = safeLoad(contents, {
schema: CONFIG_SCHEMA,
});
rules.push(...data.rules);
}
return rules;
}
export async function resolveRules(rules: Array<Rule>, selector: RuleSelector): Promise<Array<Rule>> {
const activeRules = new Set<Rule>();
for (const r of rules) {
if (selector.excludeLevel.includes(r.level)) {
continue;
}
if (selector.excludeName.includes(r.name)) {
continue;
}
const excludedTags = intersection(selector.excludeTag, r.tags);
if (excludedTags.length > 0) {
continue;
}
if (selector.includeLevel.includes(r.level)) {
activeRules.add(r);
}
if (selector.includeName.includes(r.name)) {
activeRules.add(r);
}
const includedTags = intersection(selector.includeTag, r.tags);
if (includedTags.length > 0) {
activeRules.add(r);
}
}
return Array.from(activeRules);
}
export function checkRule(rule: Rule, data: any): boolean {
2019-06-15 22:53:07 +00:00
const ajv = new ((Ajv as any).default)()
const schema = ajv.compile(rule.schema);
const scopes = JSONPath({
json: data,
path: rule.nodes.select,
});
2019-06-15 23:07:46 +00:00
return scopes.every((s: any) => schema(s));
}