Skip to content

Add telemetry command support (AST-103475) #858

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion checkmarx-ast-cli.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.3.26
2.3.27
541 changes: 100 additions & 441 deletions package-lock.json

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions src/main/wrapper/CxConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ export enum CxConstants {
CMD_LEARN_MORE = "learn-more",
IDE_SCANS_KEY = "scan.config.plugins.ideScans",
AI_GUIDED_REMEDIATION_KEY = "scan.config.plugins.aiGuidedRemediation",
AI_MCP_SERVER_KEY = "scan.config.plugins.aiMcpServer"

AI_MCP_SERVER_KEY = "scan.config.plugins.aiMcpServer",
TELEMETRY = "telemetry",
SUB_CMD_TELEMETRY_AI = "ai",
AI_PROVIDER = "--ai-provider",
TYPE = "--type",
SUB_TYPE = "--sub-type",
PROBLEM_SEVERITY = "--problem-severity"
}
118 changes: 67 additions & 51 deletions src/main/wrapper/CxWrapper.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import {CxConfig} from "./CxConfig";
import {CxParamType} from "./CxParamType";
import {CxConstants} from "./CxConstants";
import {ExecutionService} from "./ExecutionService";
import {CxCommandOutput} from "./CxCommandOutput";
import {getLoggerWithFilePath, logger} from "./loggerConfig";
import { CxConfig } from "./CxConfig";
import { CxParamType } from "./CxParamType";
import { CxConstants } from "./CxConstants";
import { ExecutionService } from "./ExecutionService";
import { CxCommandOutput } from "./CxCommandOutput";
import { getLoggerWithFilePath, logger } from "./loggerConfig";
import * as fs from "fs"
import * as os from "os";
import CxBFL from "../bfl/CxBFL";
import path = require('path');
import {getTrimmedMapValue} from "./utils";
import { getTrimmedMapValue } from "./utils";

type ParamTypeMap = Map<CxParamType, string>;

Expand Down Expand Up @@ -57,7 +57,7 @@ export class CxWrapper {
}
}


initializeCommands(formatRequired: boolean): string[] {
const list: string[] = [];
if (this.config.clientId) {
Expand All @@ -84,8 +84,8 @@ export class CxWrapper {
list.push(CxConstants.TENANT);
list.push(this.config.tenant);
}
if(this.config.additionalParameters){
this.prepareAdditionalParams(this.config.additionalParameters).forEach(function (param){
if (this.config.additionalParameters) {
this.prepareAdditionalParams(this.config.additionalParameters).forEach(function (param) {
list.push(param)
})
}
Expand Down Expand Up @@ -216,9 +216,9 @@ export class CxWrapper {
return await exec.executeCommands(this.config.pathToExecutable, commands, CxConstants.PREDICATE_TYPE);
}

async triageUpdate(projectId: string, similarityId: string, scanType: string, state: string, comment: string, severity: string, stateId:number|null = null): Promise<CxCommandOutput> {
async triageUpdate(projectId: string, similarityId: string, scanType: string, state: string, comment: string, severity: string, stateId: number | null = null): Promise<CxCommandOutput> {
const commands: string[] = [CxConstants.CMD_TRIAGE, CxConstants.SUB_CMD_UPDATE, CxConstants.PROJECT_ID, projectId, CxConstants.SIMILARITY_ID, similarityId, CxConstants.SCAN_TYPES_SUB_CMD, scanType, CxConstants.STATE, state, CxConstants.COMMENT, comment, CxConstants.SEVERITY, severity];
if(stateId) {
if (stateId) {
commands.push(CxConstants.STATE_ID)
commands.push(stateId.toString())
}
Expand All @@ -245,7 +245,7 @@ export class CxWrapper {
return exec.executeResultsCommandsFile(scanId, CxConstants.FORMAT_JSON, CxConstants.FORMAT_JSON_FILE, commands, this.config.pathToExecutable, fileName);
}

async riskManagementResults(projectId: string, scanId: string, limit?: number): Promise<CxCommandOutput> {
async riskManagementResults(projectId: string, scanId: string, limit?: number): Promise<CxCommandOutput> {
const commands: string[] = [CxConstants.CMD_RESULT, CxConstants.CMD_RISK_MANAGEMENT];
commands.push(CxConstants.PROJECT_ID, projectId);
commands.push(CxConstants.SCAN_ID, scanId);
Expand Down Expand Up @@ -313,10 +313,10 @@ export class CxWrapper {
return response;
}

async kicsRealtimeScan(fileSources: string, engine:string, additionalParams: string):Promise<[Promise<CxCommandOutput>,any]> {
async kicsRealtimeScan(fileSources: string, engine: string, additionalParams: string): Promise<[Promise<CxCommandOutput>, any]> {
const commands: string[] = [CxConstants.CMD_SCAN, CxConstants.CMD_KICS_REALTIME, CxConstants.FILE_SOURCES, fileSources, CxConstants.ADDITONAL_PARAMS, additionalParams];
if(engine.length>0){
commands.push(CxConstants.ENGINE,engine)
if (engine.length > 0) {
commands.push(CxConstants.ENGINE, engine)
}
commands.push(...this.initializeCommands(false));
const exec = new ExecutionService();
Expand All @@ -335,66 +335,66 @@ export class CxWrapper {
}


async learnMore(queryId: string){
const commands: string[] = [CxConstants.CMD_UTILS,CxConstants.CMD_LEARN_MORE,CxConstants.QUERY_ID,queryId]
async learnMore(queryId: string) {
const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.CMD_LEARN_MORE, CxConstants.QUERY_ID, queryId]
commands.push(...this.initializeCommands(true))
const exec = new ExecutionService();
return exec.executeCommands(this.config.pathToExecutable, commands, CxConstants.LEARN_MORE_DESCRIPTIONS_TYPE);
}

async kicsRemediation(resultsFile: string, kicsFile:string, engine:string,similarityIds?: string):Promise<[Promise<CxCommandOutput>,any]> {
const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.CMD_REMEDIATION,CxConstants.KICS,CxConstants.KICS_REMEDIATION_RESULTS_FILE, resultsFile, CxConstants.KICS_REMEDIATION_KICS_FILE, kicsFile];
if(engine.length>0){
commands.push(CxConstants.ENGINE,engine)
async kicsRemediation(resultsFile: string, kicsFile: string, engine: string, similarityIds?: string): Promise<[Promise<CxCommandOutput>, any]> {
const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.CMD_REMEDIATION, CxConstants.KICS, CxConstants.KICS_REMEDIATION_RESULTS_FILE, resultsFile, CxConstants.KICS_REMEDIATION_KICS_FILE, kicsFile];
if (engine.length > 0) {
commands.push(CxConstants.ENGINE, engine)
}
if(similarityIds){
commands.push(CxConstants.KICS_REMEDIATION_SIMILARITY_IDS,similarityIds)
if (similarityIds) {
commands.push(CxConstants.KICS_REMEDIATION_SIMILARITY_IDS, similarityIds)
}
commands.push(...this.initializeCommands(false));
const exec = new ExecutionService();
return exec.executeKicsCommands(this.config.pathToExecutable, commands, CxConstants.KICS_REMEDIATION_TYPE);
}

async scaRemediation(packageFiles: string, packages:string, packageVersion:string): Promise<CxCommandOutput> {
const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.CMD_REMEDIATION,CxConstants.SUB_CMD_REMEDIATION_SCA,CxConstants.SCA_REMEDIATION_PACKAGE_FILES, packageFiles,CxConstants.SCA_REMEDIATION_PACKAGE, packages,CxConstants.SCA_REMEDIATION_PACKAGE_VERSION,packageVersion];
async scaRemediation(packageFiles: string, packages: string, packageVersion: string): Promise<CxCommandOutput> {
const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.CMD_REMEDIATION, CxConstants.SUB_CMD_REMEDIATION_SCA, CxConstants.SCA_REMEDIATION_PACKAGE_FILES, packageFiles, CxConstants.SCA_REMEDIATION_PACKAGE, packages, CxConstants.SCA_REMEDIATION_PACKAGE_VERSION, packageVersion];
commands.push(...this.initializeCommands(false));
const exec = new ExecutionService();
return exec.executeCommands(this.config.pathToExecutable, commands);
}

async ideScansEnabled(): Promise<boolean> {
const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.SUB_CMD_TENANT];
commands.push(...this.initializeCommands(false));
const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.SUB_CMD_TENANT];
commands.push(...this.initializeCommands(false));

const exec = new ExecutionService();
const output = await exec.executeMapTenantOutputCommands(this.config.pathToExecutable, commands);
const exec = new ExecutionService();
const output = await exec.executeMapTenantOutputCommands(this.config.pathToExecutable, commands);

const value = getTrimmedMapValue(output, CxConstants.IDE_SCANS_KEY);
return value?.toLowerCase() === "true";
}
const value = getTrimmedMapValue(output, CxConstants.IDE_SCANS_KEY);
return value?.toLowerCase() === "true";
}

async guidedRemediationEnabled(): Promise<boolean> {
const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.SUB_CMD_TENANT];
commands.push(...this.initializeCommands(false));
const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.SUB_CMD_TENANT];
commands.push(...this.initializeCommands(false));

const exec = new ExecutionService();
const output = await exec.executeMapTenantOutputCommands(this.config.pathToExecutable, commands);
const exec = new ExecutionService();
const output = await exec.executeMapTenantOutputCommands(this.config.pathToExecutable, commands);

const value = getTrimmedMapValue(output, CxConstants.AI_GUIDED_REMEDIATION_KEY);
return value?.toLowerCase() === "true";
}
const value = getTrimmedMapValue(output, CxConstants.AI_GUIDED_REMEDIATION_KEY);
return value?.toLowerCase() === "true";
}


async aiMcpServerEnabled(): Promise<boolean> {
const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.SUB_CMD_TENANT];
commands.push(...this.initializeCommands(false));
async aiMcpServerEnabled(): Promise<boolean> {
const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.SUB_CMD_TENANT];
commands.push(...this.initializeCommands(false));

const exec = new ExecutionService();
const output = await exec.executeMapTenantOutputCommands(this.config.pathToExecutable, commands);
const exec = new ExecutionService();
const output = await exec.executeMapTenantOutputCommands(this.config.pathToExecutable, commands);

const value = getTrimmedMapValue(output, CxConstants.AI_MCP_SERVER_KEY);
return value?.toLowerCase() === "true";
}
const value = getTrimmedMapValue(output, CxConstants.AI_MCP_SERVER_KEY);
return value?.toLowerCase() === "true";
}

async kicsChat(apikey: string, file: string, line: number, severity: string, vulnerability: string, input: string, conversationId?: string, model?: string): Promise<CxCommandOutput> {
const commands: string[] = [
Expand Down Expand Up @@ -437,7 +437,7 @@ export class CxWrapper {
return new ExecutionService().executeCommands(this.config.pathToExecutable, commands, CxConstants.CHAT_TYPE);
}

async maskSecrets( file: string): Promise<CxCommandOutput> {
async maskSecrets(file: string): Promise<CxCommandOutput> {
const commands: string[] = [
CxConstants.CMD_UTILS,
CxConstants.CMD_MASK_SECRETS,
Expand All @@ -448,10 +448,26 @@ export class CxWrapper {
return new ExecutionService().executeCommands(this.config.pathToExecutable, commands, CxConstants.MASK_TYPE);
}

prepareAdditionalParams(additionalParameters: string) : string[] {
telemetryAIEvent(aiProvider: string, agent: string, eventType: string, subType: string, engine: string, problemSeverity: string): Promise<CxCommandOutput> {
const commands: string[] = [
CxConstants.TELEMETRY,
CxConstants.SUB_CMD_TELEMETRY_AI,
CxConstants.AI_PROVIDER, aiProvider,
CxConstants.AGENT, agent,
CxConstants.TYPE, eventType,
CxConstants.SUB_TYPE, subType,
CxConstants.ENGINE, engine,
CxConstants.PROBLEM_SEVERITY, problemSeverity
];
commands.push(...this.initializeCommands(false));
const exec = new ExecutionService();
return exec.executeCommands(this.config.pathToExecutable, commands);
}

prepareAdditionalParams(additionalParameters: string): string[] {
const params: string[] = [];

if(!additionalParameters) {
if (!additionalParameters) {
return params;
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/wrapper/resources/cx-linux
Git LFS file not shown
4 changes: 2 additions & 2 deletions src/main/wrapper/resources/cx-mac
Git LFS file not shown
4 changes: 2 additions & 2 deletions src/main/wrapper/resources/cx.exe
Git LFS file not shown
36 changes: 36 additions & 0 deletions src/tests/TelemetryTest.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { CxWrapper } from '../main/wrapper/CxWrapper';
import { CxCommandOutput } from "../main/wrapper/CxCommandOutput";
import { BaseTest } from "./BaseTest";

describe("Telemetry cases", () => {
const cxScanConfig = new BaseTest();

it.skip('TelemetryAIEvent Successful case with minimal parameters', async () => {
const wrapper = new CxWrapper(cxScanConfig);
const cxCommandOutput: CxCommandOutput = await wrapper.telemetryAIEvent(
"Cursor",
"Cursos",
"click",
"ast-results.viewPackageDetails",
"secrets",
"high"
);
console.log("Json object from telemetryAIEvent successful case: " + JSON.stringify(cxCommandOutput));
expect(cxCommandOutput.exitCode).toBe(0);
});


it.skip('TelemetryAIEvent Successful case with edge case parameters', async () => {
const wrapper = new CxWrapper(cxScanConfig);
const cxCommandOutput: CxCommandOutput = await wrapper.telemetryAIEvent(
"",
"",
"",
"",
"",
""
);
console.log("Json object from telemetryAIEvent with empty parameters: " + JSON.stringify(cxCommandOutput));
expect(typeof cxCommandOutput.exitCode).toBe(0);
});
});
Loading