From 9506749dabf3b04f79ee3486944285ec9b2d4fe1 Mon Sep 17 00:00:00 2001 From: Vincent Tan <vtky@users.noreply.github.com> Date: Sun, 12 Jul 2020 03:34:44 +0800 Subject: [PATCH 1/2] jsonschema validator v1 --- engines-schema.json | 226 ++++++++++++++++++++++++++++++++++++++++++++ jsonschema.js | 26 +++++ package-lock.json | 5 + package.json | 1 + 4 files changed, 258 insertions(+) create mode 100644 engines-schema.json create mode 100644 jsonschema.js diff --git a/engines-schema.json b/engines-schema.json new file mode 100644 index 0000000..c63c538 --- /dev/null +++ b/engines-schema.json @@ -0,0 +1,226 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "$id": "http://example.com/example.json", + "type": "object", + "title": "GuardRails Engines root schema", + "description": "This jsonschema is to validate and standardize all engine outputs.", + "required": [ + "engine", + "language", + "status", + "executionTime", + "issues", + "process", + "output" + ], + "properties": { + "engine": { + "$id": "#/properties/engine", + "type": "object", + "title": "The engine schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [{ + "name": "@guardrails/guardrails-engine-typescript-tslint", + "version": "1.0.0" + }], + "required": ["name", "version"], + "properties": { + "name": { + "$id": "#/properties/engine/properties/name", + "type": "string", + "pattern": "^@guardrails/guardrails-engine-.*$", + "title": "The name schema", + "description": "An explanation about the purpose of this instance.", + "examples": [ + "@guardrails/guardrails-engine-typescript-tslint" + ] + }, + "version": { + "$id": "#/properties/engine/properties/version", + "type": "string", + "title": "The version schema", + "description": "Version number of the engine" + } + } + }, + "language": { + "$id": "#/properties/language", + "type": "string", + "enum": ["c", "ruby", "php", "python", "solidity", "elixir", "rust", "terraform", "mobile", "go", "java", "javascript", "kubernetes", "general", "typescript"], + "title": "The language schema", + "description": "Main engine lanaguage" + }, + "status": { + "$id": "#/properties/status", + "type": "string", + "enum": ["success", "completed", "errror"], + "title": "The status schema", + "description": "An explanation about the purpose of this instance." + }, + "executionTime": { + "$id": "#/properties/executionTime", + "type": "integer", + "title": "The executionTime schema", + "description": "Execution time of engine", + "default": 0 + }, + "issues": { + "$id": "#/properties/issues", + "type": "integer", + "title": "The issues schema", + "description": "Number of issues reported", + "default": 0 + }, + "process": { + "$id": "#/properties/process", + "type": "object", + "title": "The process schema", + "description": "An explanation about the purpose of this instance.", + "required": ["name", "version"], + "properties": { + "name": { + "$id": "#/properties/process/properties/name", + "type": "string", + "title": "The name schema", + "description": "An explanation about the purpose of this instance." + }, + "version": { + "$id": "#/properties/process/properties/version", + "type": "string", + "title": "The version schema", + "description": "An explanation about the purpose of this instance." + } + } + }, + "output": { + "$id": "#/properties/output", + "type": "array", + "title": "The output schema", + "description": "An explanation about the purpose of this instance.", + "items": { + "allOf": [{ + "$id": "#/properties/output/items/allOf/0", + "type": "object", + "title": "The first allOf schema", + "description": "An explanation about the purpose of this instance.", + "required": ["type", "ruleId", "location", "metadata"], + "if": { + "properties": { + "type": { + "const": "sca" + } + } + }, + "then": { + "properties": { + "metadata": { + "required": ["title"] + } + } + }, + "properties": { + "type": { + "$id": "#/properties/output/items/allOf/0/properties/type", + "type": "string", + "enum": ["sast", "sca"], + "title": "The type schema", + "description": "Type of engine" + }, + "ruleId": { + "$id": "#/properties/output/items/allOf/0/properties/ruleId", + "type": "string", + "title": "The ruleId schema", + "description": "An explanation about the purpose of this instance." + }, + "location": { + "$id": "#/properties/output/items/allOf/0/properties/location", + "type": "object", + "title": "The location schema", + "description": "Location details of the issue.", + "required": ["path", "positions"], + "properties": { + "path": { + "$id": "#/properties/output/items/allOf/0/properties/location/properties/path", + "type": "string", + "pattern": "^(?!\/opt\/mount).*$", + "title": "The path schema", + "description": "Path to the affected file. Path should not start with /opt/mount" + }, + "positions": { + "$id": "#/properties/output/items/allOf/0/properties/location/properties/positions", + "type": "object", + "title": "The positions schema", + "description": "An explanation about the purpose of this instance.", + "required": ["begin"], + "properties": { + "begin": { + "$id": "#/properties/output/items/allOf/0/properties/location/properties/positions/properties/begin", + "type": "object", + "title": "The begin schema", + "description": "An explanation about the purpose of this instance.", + "required": ["line"], + "properties": { + "line": { + "$id": "#/properties/output/items/allOf/0/properties/location/properties/positions/properties/begin/properties/line", + "type": "integer", + "title": "The line schema", + "description": "An explanation about the purpose of this instance.", + "default": 0 + } + } + }, + "end": { + "$id": "#/properties/output/items/allOf/0/properties/location/properties/positions/properties/end", + "type": "object", + "title": "The end schema", + "description": "An explanation about the purpose of this instance.", + "required": ["line"], + "properties": { + "line": { + "$id": "#/properties/output/items/allOf/0/properties/location/properties/positions/properties/begin/properties/line", + "type": "integer", + "title": "The line schema", + "description": "An explanation about the purpose of this instance.", + "default": 0 + } + } + } + } + } + } + }, + "metadata": { + "$id": "#/properties/output/items/allOf/0/properties/metadata", + "type": "object", + "title": "The metadata schema", + "description": "An explanation about the purpose of this instance.", + "required": ["description"], + "properties": { + "title": { + "$id": "#/properties/output/items/allOf/0/properties/metadata/properties/title", + "type": "string", + "title": "The title schema", + "description": "An explanation about the purpose of this instance." + }, + "description": { + "$id": "#/properties/output/items/allOf/0/properties/metadata/properties/description", + "type": "string", + "title": "The description schema", + "description": "An explanation about the purpose of this instance." + }, + "lineContent": { + "$id": "#/properties/output/items/allOf/0/properties/metadata/properties/lineContent", + "type": "string", + "title": "The lineContent schema", + "description": "An explanation about the purpose of this instance." + } + } + } + } + }], + "$id": "#/properties/output/items" + } + } + } +} \ No newline at end of file diff --git a/jsonschema.js b/jsonschema.js new file mode 100644 index 0000000..c757e2b --- /dev/null +++ b/jsonschema.js @@ -0,0 +1,26 @@ +const { validator } = require("@exodus/schemasafe"); +const fs = require("fs"); +const grschema = require("./engines-schema.json"); + + +// pass the external schemas as an option +const validate = validator(grschema, { includeErrors: true, allErrors: true }); + +function readFromStdin() { + return readFromFile("/dev/stdin"); +} + +function readFromFile(filePath) { + try { + let data = fs.readFileSync(filePath).toString(); + return JSON.parse(data); + } catch (err) { + console.log(err.message); + process.exit(1); + } +} + +reportData = readFromStdin(); + +validate(reportData); +console.log(validate.errors); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c6cfa1f..8a3a686 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,11 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@exodus/schemasafe": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.0.0-beta.1.tgz", + "integrity": "sha512-3H4VeIYMfSH672iDP2uljt02V7W4VZrpJBW9At0htnZdfE2ZUXUe9tRrdaWBe6RvhyWt4BiEh0BIobMrGLmQrQ==" + }, "@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", diff --git a/package.json b/package.json index b3b2121..f9eed17 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "author": "", "license": "ISC", "dependencies": { + "@exodus/schemasafe": "^1.0.0-beta.1", "@semantic-release/git": "^5.0.0", "commander": "^2.17.1", "joi": "^13.6.0", From ebd7fff3fd8cab3a88375ebffc2d739afe8dd0fe Mon Sep 17 00:00:00 2001 From: Vincent Tan <vtky@users.noreply.github.com> Date: Mon, 20 Jul 2020 17:23:07 +0800 Subject: [PATCH 2/2] added desc for statuses --- engines-schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engines-schema.json b/engines-schema.json index c63c538..5fb09e6 100644 --- a/engines-schema.json +++ b/engines-schema.json @@ -56,7 +56,7 @@ "type": "string", "enum": ["success", "completed", "errror"], "title": "The status schema", - "description": "An explanation about the purpose of this instance." + "description": "Success: complete with results. Completed: Engine ran with no results. Error: engine errored out due to something" }, "executionTime": { "$id": "#/properties/executionTime",