@monokle/validation
Advanced tools
Comparing version 0.28.2 to 0.29.0
@@ -23,3 +23,9 @@ import { parseDocument, LineCounter } from 'yaml'; | ||
const start = lineCounter.linePos(pos[0]); | ||
const end = lineCounter.linePos(pos[1]); | ||
let end = lineCounter.linePos(pos[1]); | ||
if (end.line > start.line && end.col === 1) { | ||
// When the cursor ends at the first character of the next line | ||
// then we move it to the last character of the previous line | ||
// This gives better UX when focusing the editor. | ||
end = lineCounter.linePos(pos[1] - 1); | ||
} | ||
return { | ||
@@ -26,0 +32,0 @@ startLine: start.line, |
@@ -76,11 +76,21 @@ import { Suppression } from '@monokle/types'; | ||
}; | ||
export declare type Replacement = TextualReplacement | BinaryReplacement; | ||
export declare type TextualReplacement = { | ||
export declare type Replacement = OffsetTextualReplacement | LineTextualReplacement | BinaryReplacement; | ||
export declare type OffsetTextualReplacement = { | ||
deletedRegion: { | ||
charOffset: number; | ||
charLength: number; | ||
}; | ||
insertedContent?: { | ||
text: string; | ||
}; | ||
}; | ||
export declare type LineTextualReplacement = { | ||
deletedRegion: { | ||
startLine: number; | ||
startColumn: number; | ||
endLine: number; | ||
endColumn: number; | ||
endLine?: number; | ||
endColumn?: number; | ||
}; | ||
insertedContent?: Message; | ||
insertedContent?: { | ||
text: string; | ||
}; | ||
}; | ||
@@ -87,0 +97,0 @@ export declare type BinaryReplacement = { |
@@ -76,3 +76,3 @@ import { ResourceParser } from './common/resourceParser.js'; | ||
validate({ resources, incremental, baseline, abortSignal: externalAbortSignal, }: ValidateParams): Promise<ValidationResponse>; | ||
applySuppressions(result: ValidationResponse, resources: Resource[], suppressions?: Suppression[]): Promise<ValidationResponse>; | ||
applySuppressions(response: ValidationResponse, resources: Resource[], suppressions?: Suppression[]): Promise<ValidationResponse>; | ||
/** | ||
@@ -79,0 +79,0 @@ * Compares the validation result with a baseline. |
@@ -12,2 +12,3 @@ import { v4 } from 'uuid'; | ||
import { SuppressEngine } from './sarif/suppressions/engine.js'; | ||
import { sortResults } from './utils/sortResults.js'; | ||
export class MonokleValidator { | ||
@@ -202,3 +203,3 @@ _config = {}; | ||
}; | ||
const result = { | ||
const response = { | ||
$schema: 'https://json.schemastore.org/sarif-2.1.0.json', | ||
@@ -209,7 +210,8 @@ version: '2.1.0', | ||
if (baseline) { | ||
this.compareWithBaseline(result, baseline); | ||
this.compareWithBaseline(response, baseline); | ||
} | ||
return this.applySuppressions(result, resources); | ||
sortResults(response); | ||
return this.applySuppressions(response, resources); | ||
} | ||
async applySuppressions(result, resources, suppressions) { | ||
async applySuppressions(response, resources, suppressions) { | ||
if (suppressions) { | ||
@@ -219,7 +221,7 @@ this._suppressions = suppressions; | ||
} | ||
await this._suppressor.suppress(result, resources, { | ||
await this._suppressor.suppress(response, resources, { | ||
noInSourceSuppressions: this._config?.settings?.noInSourceSuppressions, | ||
noExternalSuppressions: this._config?.settings?.noExternalSuppressions, | ||
}); | ||
return result; | ||
return response; | ||
} | ||
@@ -232,4 +234,4 @@ /** | ||
*/ | ||
compareWithBaseline(result, baseline) { | ||
for (const run of result.runs) { | ||
compareWithBaseline(response, baseline) { | ||
for (const run of response.runs) { | ||
const baselineRun = baseline.runs.find(r => r.tool.driver.name === run.tool.driver.name); | ||
@@ -236,0 +238,0 @@ if (!baselineRun) |
import { ResourceParser } from '../../common/resourceParser.js'; | ||
import type { Resource } from '../../common/types.js'; | ||
import type { Fix } from '../../common/sarif.js'; | ||
import { FixMetadata } from '../../custom.js'; | ||
export * from './plugins/DisabledSuppressor.js'; | ||
export interface Fixer { | ||
createFix(resource: Resource, fixedContent: any, parser: ResourceParser): Fix[]; | ||
createFix(resource: Resource, fixedContent: any, fixMetadata: FixMetadata | undefined, parser: ResourceParser): Fix[]; | ||
} |
@@ -99,3 +99,3 @@ import type { Document, ParsedNode } from 'yaml'; | ||
*/ | ||
fix?: (ctx: FixContext, api: FixApi) => void; | ||
fix?: (ctx: FixContext, api: FixApi) => FixMetadata | void; | ||
/** | ||
@@ -147,6 +147,23 @@ * Advanced rule settings. | ||
/** | ||
* Utility that sets the given value. | ||
* Utility that gets the value at given path. | ||
*/ | ||
get(resource: Resource, path: string): any; | ||
/** | ||
* Utility that sets the value for given path. | ||
*/ | ||
set(resource: Resource, path: string, value: any): void; | ||
/** | ||
* Utility that unsets the given path. | ||
*/ | ||
unset(resource: Resource, path: string): void; | ||
}; | ||
export declare type FixMetadata = { | ||
/** | ||
* Describes the proposed fix and recommended actions. | ||
* | ||
* @remark A notification with this description will appear after applying this fix. | ||
* @example "Adds a user id. You might need to tweak your Dockerfile." | ||
*/ | ||
description?: string; | ||
}; | ||
export declare type ReportArgs = { | ||
@@ -153,0 +170,0 @@ /** |
@@ -8,2 +8,3 @@ import { paramCase, sentenceCase } from 'change-case'; | ||
import { isDefined } from '../../utils/isDefined.js'; | ||
import { get, unset } from 'lodash'; | ||
/** | ||
@@ -97,3 +98,3 @@ * Validator for simple custom policies. | ||
const fixedResource = JSON.parse(JSON.stringify(resource.content)); | ||
fix?.({ | ||
const fixMetadata = fix?.({ | ||
resource: fixedResource, | ||
@@ -103,10 +104,14 @@ problem: result, | ||
}, { | ||
get: (resource, path) => { | ||
return get(resource, path.split('.')); | ||
}, | ||
set: (resource, path, value) => { | ||
set(resource, path.split('.'), value); | ||
}, | ||
}); | ||
if (fixedResource) { | ||
delete fixedResource['_id']; | ||
result.fixes = this._fixer?.createFix(resource, fixedResource, this._parser); | ||
} | ||
unset: (resource, path) => { | ||
unset(resource, path.split('.')); | ||
}, | ||
}) ?? undefined; | ||
delete fixedResource['_id']; | ||
result.fixes = this._fixer?.createFix(resource, fixedResource, fixMetadata, this._parser); | ||
} | ||
@@ -113,0 +118,0 @@ return result; |
@@ -32,2 +32,6 @@ import { defineRule } from '../../custom/config.js'; | ||
}, | ||
fix({ resource, path }, { set }) { | ||
set(resource, path, '350m'); | ||
return { description: 'Sets a cpu request. You might want to tweak the value to accomodate your workload.' }; | ||
}, | ||
}); |
@@ -32,2 +32,6 @@ import { defineRule } from '../../custom/config.js'; | ||
}, | ||
fix({ resource, path }, { set }) { | ||
set(resource, path, '500m'); | ||
return { description: 'Sets a cpu limit. You might want to tweak the value to accomodate your workload.' }; | ||
}, | ||
}); |
@@ -32,2 +32,6 @@ import { defineRule } from '../../custom/config.js'; | ||
}, | ||
fix({ resource, path }, { set }) { | ||
set(resource, path, '512M'); | ||
return { description: 'Sets a memory request. You might want to tweak the value to accomodate your workload.' }; | ||
}, | ||
}); |
@@ -32,2 +32,6 @@ import { defineRule } from '../../custom/config.js'; | ||
}, | ||
fix({ resource, path }, { set }) { | ||
set(resource, path, '512M'); | ||
return { description: 'Sets a memory limit. You might want to tweak the value to accomodate your workload.' }; | ||
}, | ||
}); |
@@ -7,3 +7,3 @@ import { defineRule } from '../../custom/config.js'; | ||
fullDescription: 'The container should drop all default capabilities and add only those that are needed for its execution.', | ||
help: "Add 'ALL' to containers[].securityContext.capabilities.drop.", | ||
help: "Do not include 'SYS_ADMIN' in `securityContext.capabilities.add`.", | ||
advanced: { | ||
@@ -34,2 +34,9 @@ severity: 8, | ||
}, | ||
fix({ resource, path }, { set, get }) { | ||
const capabilities = get(resource, path); | ||
if (!Array.isArray(capabilities)) | ||
return; | ||
set(resource, path, capabilities.filter(c => c !== 'SYS_ADMIN')); | ||
return { description: 'Remove the sys admin capability.' }; | ||
}, | ||
}); |
@@ -26,2 +26,6 @@ import { NSA_RELATIONS } from '../../../taxonomies/nsa.js'; | ||
}, | ||
fix({ resource, path }, { unset }) { | ||
unset(resource, path); | ||
return { description: 'Removes the host path.' }; | ||
}, | ||
}); |
@@ -33,2 +33,6 @@ import { NSA_RELATIONS } from '../../../taxonomies/nsa.js'; | ||
}, | ||
fix({ resource, path }, { set }) { | ||
set(resource, path, true); | ||
return { description: 'Sets the root filesystem to readonly.' }; | ||
}, | ||
}); |
@@ -35,2 +35,6 @@ import { CIS_RELATIONS, NSA_RELATIONS } from '../../../taxonomies/index.js'; | ||
}, | ||
fix({ resource, path }, { set }) { | ||
set(resource, path, 'ALL'); | ||
return { description: 'Drops all capabilities.' }; | ||
}, | ||
}); |
@@ -37,2 +37,6 @@ import { NSA_RELATIONS } from '../../../taxonomies/nsa.js'; | ||
}, | ||
fix({ resource, path }, { set }) { | ||
set(resource, path, 10001); | ||
return { description: 'Sets a high user id. You might need to tweak your Dockerfile.' }; | ||
}, | ||
}); |
@@ -37,2 +37,6 @@ import { NSA_RELATIONS } from '../../../taxonomies/nsa.js'; | ||
}, | ||
fix({ resource, path }, { set }) { | ||
set(resource, path, 10001); | ||
return { description: 'Sets a high group id. You might need to tweak your Dockerfile.' }; | ||
}, | ||
}); |
@@ -31,3 +31,4 @@ import { NSA_RELATIONS } from '../../../taxonomies/nsa.js'; | ||
set(resource, path, false); | ||
return { description: 'Disables automount service account tokens.' }; | ||
}, | ||
}); |
@@ -23,2 +23,11 @@ import { defineRule } from '../../custom/config.js'; | ||
}, | ||
fix({ resource, path }, { set, get }) { | ||
const verbs = get(resource, path); | ||
if (!Array.isArray(verbs)) | ||
return; | ||
set(resource, path, verbs.filter(c => c !== 'create')); | ||
return { | ||
description: 'Remove the create pod permission. You might end up with a service with reduced functionality.', | ||
}; | ||
}, | ||
}); | ||
@@ -25,0 +34,0 @@ function isTarget(r) { |
@@ -23,2 +23,11 @@ import { defineRule } from '../../custom/config.js'; | ||
}, | ||
fix({ resource, path }, { set, get }) { | ||
const verbs = get(resource, path); | ||
if (!Array.isArray(verbs)) | ||
return; | ||
set(resource, path, verbs.filter(c => c !== 'execute')); | ||
return { | ||
description: 'Remove the execute pod permission. You might end up with a service with reduced functionality.', | ||
}; | ||
}, | ||
}); | ||
@@ -25,0 +34,0 @@ function isTarget(r) { |
@@ -36,2 +36,11 @@ import { NSA_RELATIONS } from '../../../taxonomies/nsa.js'; | ||
}, | ||
fix({ resource, path }, { set, get }) { | ||
const verbs = get(resource, path); | ||
if (!Array.isArray(verbs)) | ||
return; | ||
set(resource, path, verbs.filter(c => c !== 'execute')); | ||
return { | ||
description: 'Remove the execute pod permission. You might end up with a service with reduced functionality.', | ||
}; | ||
}, | ||
}); |
{ | ||
"name": "@monokle/validation", | ||
"version": "0.28.2", | ||
"version": "0.29.0", | ||
"description": "Kubernetes resource validation", | ||
@@ -5,0 +5,0 @@ "author": "Kubeshop", |
510207
348
12724