@xliic/cicd-core-node
Advanced tools
Comparing version 5.20.0 to 5.21.0
/// <reference types="node" /> | ||
import { ApiStatus, AuditOptions, ApiCollectionResponse, TaskOptions, ScanOptions, ApiErrors, Api, ApiReport, AuditCompliance, SecurityGates, NamingConvention, PlatformConfig, Tag } from "./types"; | ||
export declare function listApis(collectionId: string, options: TaskOptions): Promise<ApiCollectionResponse>; | ||
export declare function getListCollectionsId(options: TaskOptions): Promise<[string]>; | ||
export declare function deleteApi(apiId: string, options: TaskOptions): Promise<unknown>; | ||
@@ -24,3 +25,5 @@ export declare function createApi(collectionId: string, name: string, contents: Buffer, options: AuditOptions): Promise<Api | ApiErrors>; | ||
export declare function assignSetTag(apiId: string, tags: Tag[], options: TaskOptions): Promise<void>; | ||
export declare function saveTag(tag: Tag, options: TaskOptions): Promise<string>; | ||
export declare function deleteTag(tag: Tag, options: TaskOptions): Promise<void>; | ||
export declare function requestAudit(apiId: string, options: TaskOptions): Promise<void>; | ||
export declare function getPlatformConfig(options: TaskOptions): Promise<PlatformConfig>; |
@@ -16,3 +16,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getPlatformConfig = exports.requestAudit = exports.assignSetTag = exports.getPlatformTags = exports.getCollectionNamingConvention = exports.getApiNamingConvention = exports.readScanConfiguration = exports.startScan = exports.readScan = exports.readScanReport = exports.readGates = exports.readCompliance = exports.readAssessment = exports.createTechnicalCollection = exports.deleteCollection = exports.readTechnicalCollection = exports.readCollection = exports.updateApi = exports.readApiStatus = exports.createTechnicalApi = exports.createApi = exports.deleteApi = exports.listApis = void 0; | ||
exports.getPlatformConfig = exports.requestAudit = exports.deleteTag = exports.saveTag = exports.assignSetTag = exports.getPlatformTags = exports.getCollectionNamingConvention = exports.getApiNamingConvention = exports.readScanConfiguration = exports.startScan = exports.readScan = exports.readScanReport = exports.readGates = exports.readCompliance = exports.readAssessment = exports.createTechnicalCollection = exports.deleteCollection = exports.readTechnicalCollection = exports.readCollection = exports.updateApi = exports.readApiStatus = exports.createTechnicalApi = exports.createApi = exports.deleteApi = exports.getListCollectionsId = exports.listApis = void 0; | ||
const got_1 = require("got"); | ||
@@ -87,2 +87,9 @@ const FormData = require("form-data"); | ||
exports.listApis = listApis; | ||
function getListCollectionsId(options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const { body } = yield (0, got_1.default)(`api/v1/collections`, gotOptions("GET", options)); | ||
return body.list.map((collection) => collection.desc.id); | ||
}); | ||
} | ||
exports.getListCollectionsId = getListCollectionsId; | ||
function deleteApi(apiId, options) { | ||
@@ -298,9 +305,5 @@ return __awaiter(this, void 0, void 0, function* () { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const { body } = yield (0, got_1.default)(`api/v2/sqgs/reportComplianceStatus`, Object.assign({ searchParams: { taskId, reportType: "audit" } }, gotOptions("GET", options))); | ||
const processingDetails = body.processingDetails; | ||
if (processingDetails) { | ||
const blockingGates = processingDetails.map((detail) => detail.blockingSqgId); | ||
return { blockingGates }; | ||
} | ||
return { blockingGates: [] }; | ||
const { body } = (yield (0, got_1.default)(`api/v2/sqgs/audit/reportComplianceStatus/${taskId}`, Object.assign({}, gotOptions("GET", options)))); | ||
const blockingGates = body.processingDetails; | ||
return { blockingGates }; | ||
}); | ||
@@ -434,17 +437,35 @@ } | ||
return __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
const { body } = yield (0, got_1.default)(`api/v2/apis/${apiId}/tags/assignset`, Object.assign(Object.assign({}, gotOptions("PUT", options)), { json: { | ||
list: tags, | ||
} })); | ||
if ("code" in body || "message" in body) { | ||
throw new error_1.TaskError(`Can't assing tags for ${apiId}: | ||
const { body } = yield (0, got_1.default)(`api/v2/apis/${apiId}/tags/assignset`, Object.assign(Object.assign({}, gotOptions("PUT", options)), { json: { | ||
list: tags, | ||
} })); | ||
if ("code" in body || "message" in body) { | ||
throw new error_1.TaskError(`Can't assign tags for ${apiId}: | ||
` + JSON.stringify(body)); | ||
} | ||
} | ||
catch (err) { | ||
throw new error_1.TaskError(`Can't assing tags for ${apiId}: ` + err); | ||
}); | ||
} | ||
exports.assignSetTag = assignSetTag; | ||
function saveTag(tag, options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const { body } = (yield (0, got_1.default)(`api/v2/categories/${tag.categoryName}/tags`, Object.assign(Object.assign({}, gotOptions("POST", options)), { json: { | ||
name: tag.tagName, | ||
} }))); | ||
if ("code" in body || "message" in body) { | ||
throw new error_1.TaskError(`Can't save tag ${tag} cause: ${body.message}}`); | ||
} | ||
options.logger.info(`Save tag on platform: ${tag.categoryName}:${tag.tagName}`); | ||
return body.id; | ||
}); | ||
} | ||
exports.assignSetTag = assignSetTag; | ||
exports.saveTag = saveTag; | ||
function deleteTag(tag, options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const { body } = (yield (0, got_1.default)(`api/v2/categories/${tag.categoryName}/tags/${tag.tagName}`, Object.assign({}, gotOptions("DELETE", options)))); | ||
if ("code" in body || "message" in body) { | ||
throw new error_1.TaskError(`Can't delete tag ${tag} cause: ${body.message}}`); | ||
} | ||
options.logger.debug(`Tag ${tag.categoryName}:${tag.tagName} deleted on platform`); | ||
}); | ||
} | ||
exports.deleteTag = deleteTag; | ||
function requestAudit(apiId, options) { | ||
@@ -465,3 +486,3 @@ return __awaiter(this, void 0, void 0, function* () { | ||
if (missing.length > 0) { | ||
throw new error_1.TaskError(`Tags: [${missing.map((t) => `${t.categoryName}:${t.tagName}`)}] specified in the confguration do not exist on the platform`); | ||
throw new error_1.TaskError(`Tags: [${missing.map((t) => `${t.categoryName}:${t.tagName}`)}] specified in the configuration do not exist on the platform`); | ||
} | ||
@@ -468,0 +489,0 @@ } |
@@ -32,3 +32,3 @@ "use strict"; | ||
const issues = yield (0, issues_1.getIssues)(path.resolve(options.rootDir, filename), report.data, api.mapping, options.logger, options.lineNumbers); | ||
const failures = (0, checks_1.checkReport)(report.data, failureConditions, gates, compliance, options.logger); | ||
const failures = (0, checks_1.checkReport)(report.data, failureConditions, gates, compliance, options.skipLocalChecks, options.logger); | ||
files.set(filename, Object.assign(Object.assign({}, api), { score: report.data.score, issues, | ||
@@ -35,0 +35,0 @@ failures })); |
@@ -63,4 +63,4 @@ "use strict"; | ||
} | ||
let minScore = undefined; | ||
if (typeof inputs.minScore !== "undefined") { | ||
let minScore = 75; | ||
if (inputs.minScore !== undefined) { | ||
minScore = parseInt(inputs.minScore, 10); | ||
@@ -67,0 +67,0 @@ if (isNaN(minScore) || minScore < 0 || minScore > 100) { |
import { AuditCompliance, FailureConditions, Logger, SecurityGates } from "./types"; | ||
export declare function checkReport(report: any, conditions: FailureConditions, gates: SecurityGates | null, compliance: AuditCompliance | null, log: Logger): string[]; | ||
export declare function checkReport(report: any, conditions: FailureConditions, gates: SecurityGates | null, compliance: AuditCompliance | null, skipLocalChecks: boolean | undefined, log: Logger): string[]; |
@@ -9,13 +9,19 @@ "use strict"; | ||
const picomatch = require("picomatch"); | ||
const checks = [ | ||
checkOverallScore, | ||
checkCategoryScore, | ||
checkSeverity, | ||
checkIssueId, | ||
checkInvalidContract, | ||
checkSecurityGates, | ||
]; | ||
function checkReport(report, conditions, gates, compliance, log) { | ||
function getCheks(skipLocalChecks) { | ||
const localCheks = [ | ||
checkOverallScore, | ||
checkCategoryScore, | ||
checkSeverity, | ||
checkIssueId, | ||
checkInvalidContract, | ||
]; | ||
const checks = [ | ||
...(skipLocalChecks ? [] : localCheks), | ||
checkSecurityGates, | ||
]; | ||
return checks; | ||
} | ||
function checkReport(report, conditions, gates, compliance, skipLocalChecks, log) { | ||
let result = []; | ||
for (const check of checks) { | ||
for (const check of getCheks(skipLocalChecks)) { | ||
result = result.concat(check(report, conditions, gates, compliance, log)); | ||
@@ -142,7 +148,18 @@ } | ||
} | ||
return compliance.blockingGates.map((gateId) => { | ||
let res = compliance.blockingGates.reduce((result, blockingGate) => { | ||
var _a; | ||
const gateName = ((_a = gates[gateId]) === null || _a === void 0 ? void 0 : _a.name) || "Unknown Security Quality Gate"; | ||
return `The API failed the security quality gate "${gateName}"`; | ||
}); | ||
const gateName = ((_a = gates[blockingGate.blockingSqgId]) === null || _a === void 0 ? void 0 : _a.name) || | ||
"Unknown Security Quality Gate"; | ||
if (blockingGate.blockingRules.length > 0) { | ||
return [ | ||
...result, | ||
...blockingGate.blockingRules.map((rule) => `The API failed the security quality gate "${gateName}" - ${rule}`), | ||
]; | ||
} | ||
return [ | ||
...result, | ||
`The API failed the security quality gate "${gateName}".`, | ||
]; | ||
}, []); | ||
return res; | ||
} |
import { ApiErrors, TaskOptions } from "./types"; | ||
export declare class TaskError extends Error { | ||
constructor(message: string); | ||
networkFailure: boolean; | ||
constructor(message: string, networkFailure?: boolean); | ||
} | ||
export declare function formatApiErrors(errors: ApiErrors): string; | ||
export declare function handleTaskError(err: any, options: TaskOptions): void; |
@@ -11,4 +11,8 @@ "use strict"; | ||
class TaskError extends Error { | ||
constructor(message) { | ||
constructor(message, networkFailure) { | ||
super(message); | ||
this.networkFailure = false; | ||
if (networkFailure != undefined) { | ||
this.networkFailure = networkFailure; | ||
} | ||
Object.setPrototypeOf(this, TaskError.prototype); | ||
@@ -18,2 +22,10 @@ } | ||
exports.TaskError = TaskError; | ||
const NETWORK_ERRORS = [ | ||
"ETIMEDOUT", | ||
"ENOTFOUND", | ||
"ECONNRESET", | ||
"ECONNREFUSED", | ||
"ECONNABORTED", | ||
"EAI_AGAIN", | ||
]; | ||
function formatApiErrors(errors) { | ||
@@ -37,3 +49,3 @@ if (errors.errors.parsing) { | ||
function handleTaskError(err, options) { | ||
var _a, _b, _c, _d; | ||
var _a, _b, _c; | ||
if (err instanceof TaskError) { | ||
@@ -44,9 +56,13 @@ throw err; | ||
const transactionId = ((_b = (_a = err === null || err === void 0 ? void 0 : err.response) === null || _a === void 0 ? void 0 : _a.headers) === null || _b === void 0 ? void 0 : _b["x-42c-transactionid"]); | ||
if (((_c = err === null || err === void 0 ? void 0 : err.response) === null || _c === void 0 ? void 0 : _c.statusCode) === 401) { | ||
const statusCode = err.response.statusCode; | ||
if (statusCode === 401) { | ||
throw new TaskError(`Received 'Unauthorized' response to an API call. Check that the API token is correct. See the config instructions ${options.onboardingUrl} or contact support@42crunch.com for support. Transaction ID: ${transactionId}`); | ||
} | ||
else { | ||
throw new TaskError(`Unexpected HTTP response ${err.response.statusCode}, transaction ID: ${transactionId}: ${JSON.stringify((_d = err === null || err === void 0 ? void 0 : err.response) === null || _d === void 0 ? void 0 : _d.body)}`); | ||
throw new TaskError(`Unexpected HTTP response ${statusCode}, transaction ID: ${transactionId}: ${JSON.stringify((_c = err === null || err === void 0 ? void 0 : err.response) === null || _c === void 0 ? void 0 : _c.body)}`); | ||
} | ||
} | ||
else if (err instanceof got_1.RequestError) { | ||
throw new TaskError(`Unexpected exception "${err.message}"`, NETWORK_ERRORS.includes(err.code)); | ||
} | ||
else if (err instanceof config_1.ConfigError) { | ||
@@ -53,0 +69,0 @@ throw new TaskError(`Config file error: ${err.message}`); |
@@ -91,4 +91,8 @@ export declare type Result<R, E> = [R, undefined] | [undefined, E]; | ||
export interface AuditCompliance { | ||
blockingGates: string[]; | ||
blockingGates: BlockingGates[]; | ||
} | ||
export interface BlockingGates { | ||
blockingSqgId: string; | ||
blockingRules: string[]; | ||
} | ||
export interface SecurityGates { | ||
@@ -188,2 +192,3 @@ [key: string]: { | ||
writeJsonReportTo?: string; | ||
skipLocalChecks?: boolean; | ||
} | ||
@@ -223,2 +228,3 @@ export interface ScanInputs extends TaskInputs { | ||
writeJsonReportTo?: string; | ||
skipLocalChecks?: boolean; | ||
} | ||
@@ -225,0 +231,0 @@ export interface PlatformConfig { |
{ | ||
"name": "@xliic/cicd-core-node", | ||
"version": "5.20.0", | ||
"version": "5.21.0", | ||
"description": "Performs API contract security audit to get a detailed analysis of the possible vulnerabilities and other issues in the API contract.", | ||
@@ -36,7 +36,7 @@ "main": "lib/index.js", | ||
"@types/picomatch": "^2.2.2", | ||
"jest": "^28.1.0", | ||
"jest": "^29.3.0", | ||
"json-schema": "^0.4.0", | ||
"ts-jest": "^28.0.3", | ||
"ts-jest": "^29.0.0", | ||
"typescript": "^4.7.2" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
127600
2934