@monokle/validation
Advanced tools
Comparing version 0.7.3 to 0.8.0
import { JsonObject } from "type-fest"; | ||
import { RuleMap } from "../config/parse.js"; | ||
import { ValidationResult, ValidationRule, ValidationRuleConfig, ValidationRun } from "./sarif.js"; | ||
import { PluginMetadataWithConfig, RuleMetadataWithConfig } from "../types.js"; | ||
import { ValidationResult, RuleMetadata, RuleConfig, ValidationRun } from "./sarif.js"; | ||
import { Incremental, Resource, Plugin, PluginMetadata, CustomSchema } from "./types.js"; | ||
export declare abstract class AbstractPlugin implements Plugin { | ||
metadata: PluginMetadata; | ||
protected _metadata: PluginMetadata; | ||
configured: boolean; | ||
protected _enabled: boolean; | ||
protected _rules: ValidationRule[]; | ||
protected _rules: RuleMetadata[]; | ||
protected _ruleReverseLookup: Map<string, number>; | ||
protected _policyRuleReverseLookup: Map<string, number>; | ||
protected _ruleNameToIdLookup: Map<string, string>; | ||
protected _ruleConfig: Map<string, ValidationRuleConfig>; | ||
protected _ruleConfig: Map<string, RuleConfig>; | ||
protected _previous: ValidationResult[]; | ||
constructor(metadata: PluginMetadata, rules: ValidationRule[]); | ||
protected setRules(rules: ValidationRule[]): void; | ||
constructor(metadata: PluginMetadata, rules: RuleMetadata[]); | ||
protected setRules(rules: RuleMetadata[]): void; | ||
get metadata(): PluginMetadataWithConfig; | ||
get rules(): RuleMetadataWithConfig[]; | ||
get name(): string; | ||
get enabled(): boolean; | ||
set enabled(value: boolean); | ||
get rules(): ValidationRule[]; | ||
hasRule(rule: string): boolean; | ||
@@ -34,3 +36,3 @@ isRuleEnabled(rule: string): boolean; | ||
protected abstract doValidate(resources: Resource[], incremental?: Incremental): Promise<ValidationResult[]>; | ||
protected getRuleConfig(ruleId: string): ValidationRuleConfig; | ||
protected getRuleConfig(ruleId: string): RuleConfig; | ||
protected merge(previous: ValidationResult[], current: ValidationResult[], incremental?: Incremental): ValidationResult[]; | ||
@@ -37,0 +39,0 @@ clear(): Promise<void>; |
@@ -6,3 +6,3 @@ import keyBy from "lodash/keyBy.js"; | ||
export class AbstractPlugin { | ||
metadata; | ||
_metadata; | ||
configured = false; | ||
@@ -17,3 +17,3 @@ _enabled = true; | ||
constructor(metadata, rules) { | ||
this.metadata = metadata; | ||
this._metadata = metadata; | ||
this.setRules(rules); | ||
@@ -26,6 +26,22 @@ } | ||
rules.forEach((r, idx) => this._ruleReverseLookup.set(r.id, idx)); | ||
rules.forEach((r) => this._ruleNameToIdLookup.set(`${this.metadata.name}/${r.name}`, r.id)); | ||
rules.forEach((r) => this._ruleNameToIdLookup.set(`${this._metadata.name}/${r.name}`, r.id)); | ||
} | ||
get metadata() { | ||
return { | ||
...this._metadata, | ||
configuration: { | ||
enabled: this._enabled, | ||
}, | ||
}; | ||
} | ||
get rules() { | ||
return this._rules.map((rule) => { | ||
return { | ||
...rule, | ||
configuration: this.getRuleConfig(rule.id), | ||
}; | ||
}); | ||
} | ||
get name() { | ||
return this.metadata.name; | ||
return this._metadata.name; | ||
} | ||
@@ -38,5 +54,2 @@ get enabled() { | ||
} | ||
get rules() { | ||
return this._rules; | ||
} | ||
hasRule(rule) { | ||
@@ -43,0 +56,0 @@ const split = rule.split("/"); |
@@ -50,3 +50,3 @@ import { JsonObject } from "type-fest"; | ||
name: string; | ||
rules: ValidationRule[]; | ||
rules: RuleMetadata[]; | ||
}; | ||
@@ -59,3 +59,3 @@ /** | ||
*/ | ||
export declare type ValidationRule<TProperties extends JsonObject = {}> = { | ||
export declare type RuleMetadata<TProperties extends JsonObject = {}> = { | ||
id: string; | ||
@@ -74,3 +74,3 @@ name: string; | ||
}; | ||
defaultConfiguration?: ValidationRuleConfig; | ||
defaultConfiguration?: RuleConfig; | ||
/** | ||
@@ -89,3 +89,3 @@ * Optional, custom properties | ||
*/ | ||
export declare type ValidationRuleConfig = { | ||
export declare type RuleConfig = { | ||
/** | ||
@@ -117,3 +117,3 @@ * Whether the rule is enabled. | ||
}; | ||
export declare type RuleLevel = "warning" | "error" | "note" | "none"; | ||
export declare type RuleLevel = "warning" | "error"; | ||
export declare type ValidationInvocation = { | ||
@@ -124,3 +124,3 @@ ruleConfigurationOverrides: ValidationRuleConfigOverride; | ||
description: RuleReference; | ||
configuration: ValidationRuleConfig; | ||
configuration: RuleConfig; | ||
}; | ||
@@ -140,3 +140,3 @@ /** | ||
id: string; | ||
defaultConfiguration: ValidationRuleConfig; | ||
defaultConfiguration: RuleConfig; | ||
}; | ||
@@ -143,0 +143,0 @@ /** |
import { JsonObject } from "type-fest"; | ||
import { Scalar } from "yaml"; | ||
import { RuleMap } from "../config/parse.js"; | ||
import { PluginMetadataWithConfig, RuleMetadataWithConfig } from "../types.js"; | ||
import { ResourceSchema } from "../validators/kubernetes-schema/schemaLoader.js"; | ||
import { ResourceParser } from "./resourceParser.js"; | ||
import { ValidationPolicy, ValidationRule, ValidationRun } from "./sarif.js"; | ||
import { ValidationPolicy, ValidationRun } from "./sarif.js"; | ||
export declare type Resource = { | ||
@@ -133,2 +134,8 @@ id: string; | ||
}; | ||
export declare type PluginConfig = { | ||
/** | ||
* Whether the plugin is enabled. | ||
*/ | ||
enabled?: boolean; | ||
}; | ||
export interface Plugin { | ||
@@ -144,7 +151,7 @@ /** | ||
*/ | ||
get metadata(): PluginMetadata; | ||
get metadata(): PluginMetadataWithConfig; | ||
/** | ||
* The rules of this plugin. | ||
*/ | ||
get rules(): ValidationRule[]; | ||
get rules(): RuleMetadataWithConfig[]; | ||
get enabled(): boolean; | ||
@@ -151,0 +158,0 @@ set enabled(value: boolean); |
@@ -5,2 +5,3 @@ export * from "./common/sarif.js"; | ||
export * from "./references/index.js"; | ||
export * from "./types.js"; | ||
export * from "./utils/getRule.js"; | ||
@@ -7,0 +8,0 @@ export * from "./utils/sarif.js"; |
@@ -5,2 +5,3 @@ export * from "./common/sarif.js"; | ||
export * from "./references/index.js"; | ||
export * from "./types.js"; | ||
export * from "./utils/getRule.js"; | ||
@@ -7,0 +8,0 @@ export * from "./utils/sarif.js"; |
import { ResourceParser } from "./common/resourceParser.js"; | ||
import type { ValidationResponse } from "./common/sarif.js"; | ||
import type { Incremental, Resource, Plugin, CustomSchema } from "./common/types.js"; | ||
import type { CustomSchema, Incremental, Plugin, Resource } from "./common/types.js"; | ||
import { Config, PluginMap } from "./config/parse.js"; | ||
import { PluginMetadataWithConfig, PluginName, RuleMetadataWithConfig, Validator } from "./types.js"; | ||
import { SimpleCustomValidator } from "./validators/custom/simpleValidator.js"; | ||
@@ -21,7 +22,8 @@ import { SchemaLoader } from "./validators/kubernetes-schema/schemaLoader.js"; | ||
export declare function createDefaultPluginLoader(parser?: ResourceParser, schemaLoader?: SchemaLoader): (pluginName: string) => Promise<SimpleCustomValidator | KubernetesSchemaValidator | OpenPolicyAgentValidator | ResourceLinksValidator | YamlValidator>; | ||
export declare class MonokleValidator { | ||
export declare class MonokleValidator implements Validator { | ||
#private; | ||
constructor(loader: PluginLoader, fallback?: PluginMap); | ||
get config(): Config; | ||
set config(value: Config | undefined); | ||
get metadata(): Record<PluginName, PluginMetadataWithConfig>; | ||
get rules(): Record<PluginName, RuleMetadataWithConfig[]>; | ||
/** | ||
@@ -28,0 +30,0 @@ * Whether the rule exists in some plugin. |
@@ -0,7 +1,12 @@ | ||
import clone from "lodash/clone.js"; | ||
import difference from "lodash/difference.js"; | ||
import clone from "lodash/clone.js"; | ||
import isEqual from "lodash/isEqual.js"; | ||
import invariant from "tiny-invariant"; | ||
import { ResourceParser } from "./common/resourceParser.js"; | ||
import { nextTick, throwIfAborted } from "./utils/abort.js"; | ||
import { extractSchema, findDefaultVersion, } from "./utils/customResourceDefinitions.js"; | ||
import { PluginLoadError } from "./utils/error.js"; | ||
import { isDefined } from "./utils/isDefined.js"; | ||
import { DEV_MODE_TOKEN } from "./validators/custom/constants.js"; | ||
import { DevCustomValidator } from "./validators/custom/devValidator.js"; | ||
import { SimpleCustomValidator } from "./validators/custom/simpleValidator.js"; | ||
@@ -14,7 +19,2 @@ import { SchemaLoader } from "./validators/kubernetes-schema/schemaLoader.js"; | ||
import { YamlValidator } from "./validators/yaml-syntax/validator.js"; | ||
import { extractSchema, findDefaultVersion, } from "./utils/customResourceDefinitions.js"; | ||
import { DevCustomValidator } from "./validators/custom/devValidator.js"; | ||
import { DEV_MODE_TOKEN } from "./validators/custom/constants.js"; | ||
import { PluginLoadError } from "./utils/error.js"; | ||
import invariant from "tiny-invariant"; | ||
export function createMonokleValidator(loader, fallback) { | ||
@@ -93,3 +93,3 @@ return new MonokleValidator(loader, fallback); | ||
/** | ||
* The configuration of this validator. | ||
* The user configuration of this validator. | ||
*/ | ||
@@ -120,6 +120,10 @@ #config; | ||
} | ||
set config(value) { | ||
this.#config = value; | ||
this.cancelLoad("reconfigured"); | ||
get metadata() { | ||
const entries = this.#plugins.map((p) => [p.metadata.name, p.metadata]); | ||
return Object.fromEntries(entries); | ||
} | ||
get rules() { | ||
const entries = this.#plugins.map((p) => [p.metadata.name, p.rules]); | ||
return Object.fromEntries(entries); | ||
} | ||
/** | ||
@@ -178,5 +182,3 @@ * Whether the rule exists in some plugin. | ||
async preload(config) { | ||
if (config) { | ||
this.config = config; | ||
} | ||
this.#config = config; | ||
return this.load(); | ||
@@ -367,3 +369,3 @@ } | ||
await this.doUnload(pluginNames); | ||
this.config = undefined; | ||
this.#config = undefined; | ||
this.#failedPlugins = []; | ||
@@ -370,0 +372,0 @@ } |
@@ -12,2 +12,2 @@ import { ResourceParser } from "../common/resourceParser.js"; | ||
*/ | ||
export declare function processRefs(resources: Resource[], parser: ResourceParser, incremental?: Incremental): Resource[]; | ||
export declare function processRefs(resources: Resource[], parser: ResourceParser, incremental?: Incremental, files?: string[]): Resource[]; |
@@ -22,3 +22,7 @@ import groupBy from "lodash/groupBy.js"; | ||
*/ | ||
export function processRefs(resources, parser, incremental) { | ||
export function processRefs(resources, parser, incremental, | ||
// optional list of files that were processed to extract the specified resources, needed to resolve refs | ||
// to files that don't contain any resources. If not specified the list of files will be extracted from | ||
// specified resources instead. | ||
files) { | ||
const filteredResources = filterResources(resources, incremental); | ||
@@ -29,4 +33,4 @@ doProcessRefs(resources, filteredResources, { | ||
}); | ||
// extract all unique file paths from resources | ||
const filePaths = new Set(resources.map((obj) => obj.filePath)); | ||
// extract all unique file paths from resources if not specified | ||
const filePaths = files ? new Set(files) : new Set(resources.map((obj) => obj.filePath)); | ||
processKustomizations(resources, filePaths, parser); | ||
@@ -33,0 +37,0 @@ return resources; |
@@ -74,3 +74,6 @@ import { ResourceRefType, } from "../../common/types.js"; | ||
export function isFolderPath(filePath, files) { | ||
return Array.from(files).find(f => f.startsWith(filePath + path.sep)) !== undefined; | ||
if (!filePath.endsWith(path.sep)) { | ||
filePath += path.sep; | ||
} | ||
return Array.from(files).find(f => f.startsWith(filePath)) !== undefined; | ||
} | ||
@@ -77,0 +80,0 @@ export function findChildren(files, parentFile) { |
@@ -52,5 +52,5 @@ import path from "../../utils/path.js"; | ||
function processKustomizationResourceRef(kustomization, refNode, resources, files) { | ||
let kustomizationPath = path.join(path.parse(kustomization.filePath).dir, refNode.nodeValue()); | ||
if (files.has(kustomizationPath)) { | ||
let children = findChildren(files, kustomizationPath); | ||
let resourcePath = path.join(path.parse(kustomization.filePath).dir, refNode.nodeValue()); | ||
if (files.has(resourcePath)) { | ||
let children = findChildren(files, resourcePath); | ||
if (children.length > 0) { | ||
@@ -65,3 +65,7 @@ children | ||
// resource is file -> check for contained resources | ||
linkParentKustomization(kustomizationPath, kustomization, resources, refNode); | ||
let result = linkParentKustomization(resourcePath, kustomization, resources, refNode); | ||
// no resources found in file? - create a fileref instead | ||
if (result.length === 0) { | ||
createKustomizationFileRef(kustomization, refNode, resourcePath, files); | ||
} | ||
} | ||
@@ -71,3 +75,3 @@ } | ||
// resource is file or folder ref | ||
createKustomizationFileRef(kustomization, refNode, kustomizationPath, files); | ||
createKustomizationFileRef(kustomization, refNode, resourcePath, files); | ||
} | ||
@@ -103,2 +107,9 @@ } | ||
} | ||
// as specified by https://github.com/hashicorp/go-getter#url-format | ||
function isExternalResourceRef(refNode) { | ||
const externalPrefixes = ["http://", "https://", "github.com/", "gitlab.com/", | ||
"bitbucket.org/", "git::", "hg::", "s3::", "gcs::", "file:"]; | ||
let value = refNode.nodeValue().toLowerCase(); | ||
return externalPrefixes.findIndex(v => value.startsWith(v)) >= 0; | ||
} | ||
/** | ||
@@ -120,3 +131,3 @@ * Processes all kustomizations in resourceMap and establishes corresponding resourcerefs | ||
resourceNodes | ||
.filter((refNode) => !refNode.nodeValue().startsWith("http")) | ||
.filter((refNode) => !isExternalResourceRef(refNode)) | ||
.forEach((refNode) => { | ||
@@ -123,0 +134,0 @@ processKustomizationResourceRef(kustomization, refNode, resources, files); |
@@ -1,3 +0,3 @@ | ||
import { ValidationResponse, ValidationResult, ValidationRule } from "../common/sarif.js"; | ||
export declare function getRuleForResult(response: ValidationResponse, result: ValidationResult): ValidationRule; | ||
import { ValidationResponse, ValidationResult, RuleMetadata } from "../common/sarif.js"; | ||
export declare function getRuleForResult(response: ValidationResponse, result: ValidationResult): RuleMetadata; | ||
export declare function createResourceErrorMap(response: ValidationResponse): Map<string, ValidationResult[]>; |
import { JsonObject } from "type-fest"; | ||
import { ResourceParser } from "../../common/resourceParser.js"; | ||
import { ValidationRule, ValidationRun } from "../../common/sarif.js"; | ||
import { CustomSchema, Incremental, Plugin, PluginMetadata, Resource } from "../../common/types.js"; | ||
import { ValidationRun } from "../../common/sarif.js"; | ||
import { CustomSchema, Incremental, Plugin, Resource } from "../../common/types.js"; | ||
import { RuleMap } from "../../config/parse.js"; | ||
import { PluginMetadataWithConfig, RuleMetadataWithConfig } from "../../types.js"; | ||
/** | ||
@@ -21,4 +22,4 @@ * Validator for developing custom policies. | ||
get name(): string; | ||
get metadata(): PluginMetadata; | ||
get rules(): ValidationRule<{}>[]; | ||
get metadata(): PluginMetadataWithConfig; | ||
get rules(): RuleMetadataWithConfig[]; | ||
get enabled(): boolean; | ||
@@ -25,0 +26,0 @@ set enabled(value: boolean); |
@@ -84,3 +84,3 @@ import { DEV_MODE_TOKEN } from "./constants.js"; | ||
if (!this._currentValidator) { | ||
return DEFAULT_METADATA; | ||
return { ...DEFAULT_METADATA, configuration: { enabled: false } }; | ||
} | ||
@@ -87,0 +87,0 @@ return { |
@@ -87,3 +87,7 @@ import { paramCase, sentenceCase } from "change-case"; | ||
return { | ||
...plugin, | ||
id: plugin.id, | ||
name: plugin.name, | ||
description: plugin.description, | ||
icon: plugin.icon, | ||
learnMoreUrl: plugin.learnMoreUrl, | ||
displayName: plugin.displayName ?? sentenceCase(plugin.name), | ||
@@ -90,0 +94,0 @@ }; |
@@ -1,2 +0,2 @@ | ||
import { ValidationRule } from "../../common/sarif.js"; | ||
export declare const KUBERNETES_SCHEMA_RULES: ValidationRule[]; | ||
import { RuleMetadata } from "../../common/sarif.js"; | ||
export declare const KUBERNETES_SCHEMA_RULES: RuleMetadata[]; |
import { PolicyMetadata } from "./types.js"; | ||
export declare const DEFAULT_TRIVY_PLUGIN: PolicyMetadata; | ||
export declare const OPEN_POLICY_AGENT_RULES: import("../../index.js").ValidationRule<import("./types.js").OpaProperties>[]; | ||
export declare const OPEN_POLICY_AGENT_RULES: import("../../index.js").RuleMetadata<import("./types.js").OpaProperties>[]; |
@@ -86,2 +86,5 @@ export const DEFAULT_TRIVY_PLUGIN = { | ||
}, | ||
defaultConfiguration: { | ||
level: "error", | ||
}, | ||
properties: { | ||
@@ -106,2 +109,5 @@ "security-severity": 8, | ||
}, | ||
defaultConfiguration: { | ||
level: "error", | ||
}, | ||
properties: { | ||
@@ -126,2 +132,5 @@ "security-severity": 8, | ||
}, | ||
defaultConfiguration: { | ||
level: "error", | ||
}, | ||
properties: { | ||
@@ -146,2 +155,5 @@ "security-severity": 8, | ||
}, | ||
defaultConfiguration: { | ||
level: "error", | ||
}, | ||
properties: { | ||
@@ -166,2 +178,5 @@ "security-severity": 8, | ||
}, | ||
defaultConfiguration: { | ||
level: "error", | ||
}, | ||
properties: { | ||
@@ -300,2 +315,5 @@ "security-severity": 8, | ||
}, | ||
defaultConfiguration: { | ||
level: "error", | ||
}, | ||
properties: { | ||
@@ -396,2 +414,5 @@ "security-severity": 8, | ||
}, | ||
defaultConfiguration: { | ||
level: "error", | ||
}, | ||
properties: { | ||
@@ -398,0 +419,0 @@ "security-severity": 8, |
import { loadPolicy } from "@open-policy-agent/opa-wasm"; | ||
import { ValidationRule } from "../../common/sarif.js"; | ||
import { RuleMetadata } from "../../common/sarif.js"; | ||
export declare type LoadedPolicy = Awaited<ReturnType<typeof loadPolicy>>; | ||
@@ -20,3 +20,3 @@ export declare type PolicyError = { | ||
module: string; | ||
rules: ValidationRule<OpaProperties>[]; | ||
rules: RuleMetadata<OpaProperties>[]; | ||
}; | ||
@@ -23,0 +23,0 @@ /** |
@@ -1,2 +0,2 @@ | ||
import { ValidationRule } from "../../common/sarif.js"; | ||
export declare const RESOURCE_LINK_RULES: ValidationRule[]; | ||
import { RuleMetadata } from "../../common/sarif.js"; | ||
export declare const RESOURCE_LINK_RULES: RuleMetadata[]; |
import { ErrorCode } from "yaml"; | ||
import { ValidationRule } from "../../common/sarif.js"; | ||
import { RuleMetadata } from "../../common/sarif.js"; | ||
/** | ||
@@ -12,2 +12,2 @@ * Maps a YAML error code to its rule identifier. | ||
export declare const YAML_RULE_MAP: Record<ErrorCode | string, string>; | ||
export declare const YAML_RULES: ValidationRule[]; | ||
export declare const YAML_RULES: RuleMetadata[]; |
{ | ||
"name": "@monokle/validation", | ||
"version": "0.7.3", | ||
"version": "0.8.0", | ||
"description": "Kubernetes resource validation", | ||
@@ -5,0 +5,0 @@ "author": "Kubeshop", |
273051
154
6824