Skip to content

Commit f27370c

Browse files
cx-atish-jadhavcx-anand-nandeshwarcx-anjali-deore
authored
Add Telemetry AI event support to Java wrapper with test coverage (AST-127560) (#454)
* aimcp server changes * oss-realtime scanner changes * Create OssRealtimeVulnerability.java * Unify realtime scan wrappers; consolidate Secrets/IaC models; deprecate and stub obsolete result classes * Add ContainersRealtimeVulnerability model for containers realtime scan parsing * Add @JsonCreator constructor to OssRealtimeVulnerability for reliable Jackson deserialization * Refactoring package name and adding test for oss and mcp flag * Add integration tests for OSS, Container, and Secrets realtime scanners * Replaced Id to CVE in oss vulnerability * Changed variable from id to CVE as per OSS response * aimcp server changes * oss-realtime scanner changes * Create OssRealtimeVulnerability.java * Unify realtime scan wrappers; consolidate Secrets/IaC models; deprecate and stub obsolete result classes * Add ContainersRealtimeVulnerability model for containers realtime scan parsing * Add @JsonCreator constructor to OssRealtimeVulnerability for reliable Jackson deserialization * Refactoring package name and adding test for oss and mcp flag * Add integration tests for OSS, Container, and Secrets realtime scanners * Changed variable from id to CVE as per OSS response * Add maskedResult for secret remediation and change log level from INFO to DEBUG * Remove masked secrets functionality from codebase * Implemented mask cmd in java wrapper * Added fix for containerTool for IAC * Add telemetry AI command with full parameter support and tests * Add ignoredFilePath parameter to ScanAsca method * Removing ASCA ignore file path changes --------- Co-authored-by: cx-anand-nandeshwar <73646287+cx-anand-nandeshwar@users.noreply.github.com> Co-authored-by: anjali-deore <200181980+cx-anjali-deore@users.noreply.github.com>
1 parent d95cdea commit f27370c

File tree

3 files changed

+135
-8
lines changed

3 files changed

+135
-8
lines changed

src/main/java/com/checkmarx/ast/wrapper/CxConstants.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,13 @@ public final class CxConstants {
8282
static final String SUB_CMD_CONTAINERS_REALTIME = "containers-realtime";
8383
static final String SUB_CMD_MASK = "mask";
8484
static final String RESULT_FILE = "--result-file";
85+
static final String CMD_TELEMETRY = "telemetry";
86+
static final String SUB_CMD_TELEMETRY_AI = "ai";
87+
static final String AI_PROVIDER = "--ai-provider";
88+
static final String TYPE = "--type";
89+
static final String SUB_TYPE = "--sub-type";
90+
static final String PROBLEM_SEVERITY = "--problem-severity";
91+
static final String SCAN_TYPE_FLAG = "--scan-type";
92+
static final String STATUS = "--status";
93+
static final String TOTAL_COUNT = "--total-count";
8594
}

src/main/java/com/checkmarx/ast/wrapper/CxWrapper.java

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ public KicsRealtimeResults kicsRealtimeScan(@NonNull String fileSources, String
409409
return Execution.executeCommand(withConfigArguments(arguments), logger, KicsRealtimeResults::fromLine);
410410
}
411411

412-
public <T> T realtimeScan(@NonNull String subCommand, @NonNull String sourcePath, String ignoredFilePath, java.util.function.Function<String, T> resultParser)
412+
public <T> T realtimeScan(@NonNull String subCommand, @NonNull String sourcePath, String containerTool, String ignoredFilePath, java.util.function.Function<String, T> resultParser)
413413
throws IOException, InterruptedException, CxException {
414414
this.logger.info("Executing 'scan {}' command using the CLI.", subCommand);
415415
this.logger.info("Source: {} IgnoredFilePath: {}", sourcePath, ignoredFilePath);
@@ -418,6 +418,10 @@ public <T> T realtimeScan(@NonNull String subCommand, @NonNull String sourcePath
418418
arguments.add(subCommand);
419419
arguments.add(CxConstants.SOURCE);
420420
arguments.add(sourcePath);
421+
if(StringUtils.isNotBlank(containerTool)){
422+
arguments.add(CxConstants.ENGINE);
423+
arguments.add(containerTool);
424+
}
421425
if (StringUtils.isNotBlank(ignoredFilePath)) {
422426
arguments.add(CxConstants.IGNORED_FILE_PATH);
423427
arguments.add(ignoredFilePath);
@@ -428,27 +432,26 @@ public <T> T realtimeScan(@NonNull String subCommand, @NonNull String sourcePath
428432
// OSS Realtime
429433
public OssRealtimeResults ossRealtimeScan(@NonNull String sourcePath, String ignoredFilePath)
430434
throws IOException, InterruptedException, CxException {
431-
return realtimeScan(CxConstants.SUB_CMD_OSS_REALTIME, sourcePath, ignoredFilePath, OssRealtimeResults::fromLine);
435+
return realtimeScan(CxConstants.SUB_CMD_OSS_REALTIME, sourcePath,"", ignoredFilePath, OssRealtimeResults::fromLine);
432436
}
433437

434438
// IAC Realtime
435-
public IacRealtimeResults iacRealtimeScan(@NonNull String sourcePath, String ignoredFilePath)
439+
public IacRealtimeResults iacRealtimeScan(@NonNull String sourcePath,String containerTool, String ignoredFilePath)
436440
throws IOException, InterruptedException, CxException {
437-
return realtimeScan(CxConstants.SUB_CMD_IAC_REALTIME, sourcePath, ignoredFilePath, IacRealtimeResults::fromLine);
441+
return realtimeScan(CxConstants.SUB_CMD_IAC_REALTIME, sourcePath,containerTool, ignoredFilePath, IacRealtimeResults::fromLine);
438442
}
439443

444+
440445
// Secrets Realtime
441446
public SecretsRealtimeResults secretsRealtimeScan(@NonNull String sourcePath, String ignoredFilePath)
442447
throws IOException, InterruptedException, CxException {
443-
return realtimeScan(CxConstants.SUB_CMD_SECRETS_REALTIME, sourcePath, ignoredFilePath, SecretsRealtimeResults::fromLine);
448+
return realtimeScan(CxConstants.SUB_CMD_SECRETS_REALTIME, sourcePath,"", ignoredFilePath, SecretsRealtimeResults::fromLine);
444449
}
445450

446-
447-
448451
// Containers Realtime
449452
public ContainersRealtimeResults containersRealtimeScan(@NonNull String sourcePath, String ignoredFilePath)
450453
throws IOException, InterruptedException, CxException {
451-
return realtimeScan(CxConstants.SUB_CMD_CONTAINERS_REALTIME, sourcePath, ignoredFilePath, ContainersRealtimeResults::fromLine);
454+
return realtimeScan(CxConstants.SUB_CMD_CONTAINERS_REALTIME, sourcePath, "",ignoredFilePath, ContainersRealtimeResults::fromLine);
452455
}
453456

454457
public KicsRemediation kicsRemediate(@NonNull String resultsFile, String kicsFile, String engine,String similarityIds)
@@ -534,6 +537,54 @@ public MaskResult maskSecrets(@NonNull String filePath) throws CxException, IOEx
534537
return Execution.executeCommand(withConfigArguments(arguments), logger, MaskResult::fromLine);
535538
}
536539

540+
/**
541+
* Executes telemetry AI command to collect telemetry data for user interactions related to AI features.
542+
*
543+
* @param aiProvider AI provider name (e.g., "Copilot")
544+
* @param agent Agent name (e.g., "Jetbrains")
545+
* @param eventType Event type (e.g., "click")
546+
* @param subType Event subtype (e.g., "ast-results.viewPackageDetails")
547+
* @param engine Engine type (e.g., "secrets")
548+
* @param problemSeverity Severity level (e.g., "high")
549+
* @param scanType Type of scan
550+
* @param status Status information
551+
* @param totalCount Number count
552+
* @return Command output as string
553+
* @throws IOException if I/O error occurs
554+
* @throws InterruptedException if command execution is interrupted
555+
* @throws CxException if CLI command fails
556+
*/
557+
public String telemetryAIEvent(String aiProvider, String agent, String eventType, String subType,
558+
String engine, String problemSeverity, String scanType, String status,
559+
Integer totalCount) throws IOException, InterruptedException, CxException {
560+
this.logger.info("Executing telemetry AI event with provider: {}, type: {}, subType: {}",
561+
aiProvider, eventType, subType);
562+
563+
List<String> arguments = new ArrayList<>();
564+
arguments.add(CxConstants.CMD_TELEMETRY);
565+
arguments.add(CxConstants.SUB_CMD_TELEMETRY_AI);
566+
arguments.add(CxConstants.AI_PROVIDER);
567+
arguments.add(aiProvider);
568+
arguments.add(CxConstants.AGENT);
569+
arguments.add(agent);
570+
arguments.add(CxConstants.TYPE);
571+
arguments.add(eventType);
572+
arguments.add(CxConstants.SUB_TYPE);
573+
arguments.add(subType);
574+
arguments.add(CxConstants.ENGINE);
575+
arguments.add(engine);
576+
arguments.add(CxConstants.PROBLEM_SEVERITY);
577+
arguments.add(problemSeverity);
578+
arguments.add(CxConstants.SCAN_TYPE_FLAG);
579+
arguments.add(scanType);
580+
arguments.add(CxConstants.STATUS);
581+
arguments.add(status);
582+
arguments.add(CxConstants.TOTAL_COUNT);
583+
arguments.add(totalCount.toString());
584+
585+
return Execution.executeCommand(withConfigArguments(arguments), logger, line -> line);
586+
}
587+
537588
private int getIndexOfBfLNode(List<Node> bflNodes, List<Node> resultNodes) {
538589

539590
int bflNodeNotFound = -1;
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.checkmarx.ast;
2+
3+
import com.checkmarx.ast.wrapper.CxException;
4+
import org.junit.jupiter.api.Assertions;
5+
import org.junit.jupiter.api.Test;
6+
7+
import java.io.IOException;
8+
9+
/**
10+
* Telemetry AI event test cases covering various parameter scenarios.
11+
*/
12+
class TelemetryTest extends BaseTest {
13+
14+
@Test
15+
void testTelemetryAIEventSuccessfulCaseWithMinimalParametersAiLog() throws CxException, IOException, InterruptedException {
16+
// Test case: AI logging with specific parameters and some empty values
17+
Assertions.assertDoesNotThrow(() -> {
18+
String result = wrapper.telemetryAIEvent(
19+
"Cursor", // aiProvider
20+
"Cursos", // agent
21+
"click", // eventType
22+
"ast-results.viewPackageDetails", // subType
23+
"secrets", // engine
24+
"high", // problemSeverity
25+
"", // scanType (empty)
26+
"", // status (empty)
27+
0 // totalCount
28+
);
29+
}, "Telemetry AI event should execute successfully");
30+
}
31+
32+
@Test
33+
void testTelemetryAIEventSuccessfulCaseWithMinimalParametersDetectionLog() throws CxException, IOException, InterruptedException {
34+
// Test case: Detection logging with most parameters empty and specific scan data
35+
Assertions.assertDoesNotThrow(() -> {
36+
String result = wrapper.telemetryAIEvent(
37+
"", // aiProvider (empty)
38+
"", // agent (empty)
39+
"", // eventType (empty)
40+
"", // subType (empty)
41+
"", // engine (empty)
42+
"", // problemSeverity (empty)
43+
"asca", // scanType
44+
"Critical", // status
45+
10 // totalCount
46+
);
47+
}, "Telemetry AI event should execute successfully for detection log");
48+
}
49+
50+
@Test
51+
void testTelemetryAIEventSuccessfulCaseWithEdgeCaseParameters() throws CxException, IOException, InterruptedException {
52+
// Test case: Edge case with minimal required parameters
53+
Assertions.assertDoesNotThrow(() -> {
54+
String result = wrapper.telemetryAIEvent(
55+
"test-provider", // aiProvider (minimal value)
56+
"java-wrapper", // agent (minimal value)
57+
"", // eventType (empty)
58+
"", // subType (empty)
59+
"", // engine (empty)
60+
"", // problemSeverity (empty)
61+
"", // scanType (empty)
62+
"", // status (empty)
63+
0 // totalCount
64+
);
65+
}, "Telemetry AI event should execute successfully for edge case");
66+
}
67+
}

0 commit comments

Comments
 (0)