Skip to content

Commit 60c6873

Browse files
authored
adding kics remediation support
1 parent b49382a commit 60c6873

File tree

7 files changed

+142
-8
lines changed

7 files changed

+142
-8
lines changed

src/main/java/com/checkmarx/ast/kicsRealtimeResults/kicsRealtimeResults.java renamed to src/main/java/com/checkmarx/ast/kicsRealtimeResults/KicsRealtimeResults.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,22 @@
2121
@JsonDeserialize()
2222
@JsonInclude(JsonInclude.Include.NON_NULL)
2323
@JsonIgnoreProperties(ignoreUnknown = true)
24-
public class kicsRealtimeResults {
24+
public class KicsRealtimeResults {
2525

2626
int totalCount;
2727
String version;
2828
List<KicsResult> results;
2929
KicsSummary kicsSummary;
3030

3131
@JsonCreator
32-
public kicsRealtimeResults(@JsonProperty("total_counter") int totalCount, @JsonProperty("queries") List<KicsResult> results,@JsonProperty("kics_version") String version, @JsonProperty("severity_counters") KicsSummary kicsSummary) {
32+
public KicsRealtimeResults(@JsonProperty("total_counter") int totalCount, @JsonProperty("queries") List<KicsResult> results, @JsonProperty("kics_version") String version, @JsonProperty("severity_counters") KicsSummary kicsSummary) {
3333
this.totalCount = totalCount;
3434
this.version = version;
3535
this.results = results;
3636
this.kicsSummary = kicsSummary;
3737
}
3838
public static <T> T fromLine(String line) {
39-
return parse(line, TypeFactory.defaultInstance().constructType(kicsRealtimeResults.class));
39+
return parse(line, TypeFactory.defaultInstance().constructType(KicsRealtimeResults.class));
4040
}
4141

4242
private static <T> T parse(String line, JavaType type) {
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.checkmarx.ast.remediation;
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
5+
import com.fasterxml.jackson.annotation.JsonInclude;
6+
import com.fasterxml.jackson.annotation.JsonProperty;
7+
import com.fasterxml.jackson.databind.JavaType;
8+
import com.fasterxml.jackson.databind.ObjectMapper;
9+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
10+
import com.fasterxml.jackson.databind.type.TypeFactory;
11+
import lombok.Value;
12+
import org.apache.commons.lang3.StringUtils;
13+
14+
import java.io.IOException;
15+
16+
@Value
17+
@JsonDeserialize()
18+
@JsonInclude(JsonInclude.Include.NON_NULL)
19+
@JsonIgnoreProperties(ignoreUnknown = true)
20+
public class KicsRemediation {
21+
String availableRemediation;
22+
String appliedRemediation;
23+
24+
@JsonCreator
25+
public KicsRemediation(@JsonProperty("available_remediation_count") String availableRemediation, @JsonProperty("applied_remediation_count") String appliedRemediation) {
26+
this.availableRemediation = availableRemediation;
27+
this.appliedRemediation = appliedRemediation;
28+
}
29+
30+
public static <T> T fromLine(String line) {
31+
return parse(line, TypeFactory.defaultInstance().constructType(KicsRemediation.class));
32+
}
33+
34+
private static <T> T parse(String line, JavaType type) {
35+
T result = null;
36+
try {
37+
if (!StringUtils.isBlank(line) && isValidJSON(line)) {
38+
result = new ObjectMapper().readValue(line, type);
39+
40+
}
41+
} catch (IOException e) {
42+
e.printStackTrace();
43+
}
44+
return result;
45+
}
46+
47+
private static boolean isValidJSON(final String json) {
48+
try {
49+
final ObjectMapper mapper = new ObjectMapper();
50+
mapper.readTree(json);
51+
return true;
52+
} catch (IOException e) {
53+
return false;
54+
}
55+
}
56+
}

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

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package com.checkmarx.ast.wrapper;
22

33
import com.checkmarx.ast.codebashing.CodeBashing;
4-
import com.checkmarx.ast.kicsRealtimeResults.kicsRealtimeResults;
4+
import com.checkmarx.ast.kicsRealtimeResults.KicsRealtimeResults;
55
import com.checkmarx.ast.predicate.Predicate;
66
import com.checkmarx.ast.project.Project;
7+
import com.checkmarx.ast.remediation.KicsRemediation;
78
import com.checkmarx.ast.results.ReportFormat;
89
import com.checkmarx.ast.results.Results;
910
import com.checkmarx.ast.results.ResultsSummary;
@@ -304,7 +305,7 @@ public int getResultsBfl(@NonNull UUID scanId, @NonNull String queryId, List<Nod
304305

305306
}
306307

307-
public kicsRealtimeResults kicsRealtimeScan(@NonNull String fileSources, String engine, String additionalParams)
308+
public KicsRealtimeResults kicsRealtimeScan(@NonNull String fileSources, String engine, String additionalParams)
308309
throws IOException, InterruptedException, CxException {
309310
this.logger.info("Executing 'scan kics-realtime' command using the CLI.");
310311
this.logger.info("Fetching the results for fileSources {} and additionalParams {}", fileSources, additionalParams);
@@ -320,9 +321,34 @@ public kicsRealtimeResults kicsRealtimeScan(@NonNull String fileSources, String
320321
arguments.add(CxConstants.ENGINE);
321322
arguments.add(engine);
322323
}
323-
kicsRealtimeResults kicsResults = Execution.executeCommand(withConfigArguments(arguments), logger, kicsRealtimeResults::fromLine);
324+
KicsRealtimeResults kicsResults = Execution.executeCommand(withConfigArguments(arguments), logger, KicsRealtimeResults::fromLine);
324325
return kicsResults;
326+
}
327+
328+
public KicsRemediation kicsRemediate(@NonNull String resultsFile, String kicsFile, String engine,String similarityIds)
329+
throws IOException, InterruptedException, CxException {
330+
this.logger.info("Executing 'remediation kics' command using the CLI.");
331+
this.logger.info("Applying remediation for resultsFile {} and resultsFile {}", resultsFile, kicsFile);
325332

333+
List<String> arguments = new ArrayList<>();
334+
arguments.add(this.executable);
335+
arguments.add("utils");
336+
arguments.add("remediation");
337+
arguments.add("kics");
338+
arguments.add("--results-file");
339+
arguments.add(resultsFile);
340+
arguments.add("--kics-files");
341+
arguments.add(kicsFile);
342+
if (engine.length() > 0) {
343+
arguments.add(CxConstants.ENGINE);
344+
arguments.add(engine);
345+
}
346+
if (similarityIds.length() > 0) {
347+
arguments.add("--similarity-ids");
348+
arguments.add(similarityIds);
349+
}
350+
KicsRemediation remediation = Execution.executeCommand(arguments, logger, KicsRemediation::fromLine);
351+
return remediation;
326352
}
327353

328354
private int getIndexOfBfLNode(List<Node> bflNodes, List<Node> resultNodes) {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.checkmarx.ast;
2+
3+
import com.checkmarx.ast.remediation.KicsRemediation;
4+
import org.junit.jupiter.api.Assertions;
5+
import org.junit.jupiter.api.Test;
6+
import java.nio.file.Path;
7+
import java.nio.file.Paths;
8+
9+
class RemediationTest extends BaseTest {
10+
private static String RESULTS_FILE = "target/test-classes/results.json";
11+
12+
private static Path path = Paths.get("target/test-classes/");
13+
private static String KICS_FILE = path.toAbsolutePath().toString();
14+
private static String QUERY_ID = "9574288c118e8c87eea31b6f0b011295a39ec5e70d83fb70e839b8db4a99eba8";
15+
private static String ENGINE = "docker";
16+
17+
@Test
18+
void testKicsRemediation() throws Exception {
19+
KicsRemediation remediation = wrapper.kicsRemediate(RESULTS_FILE,KICS_FILE,"","");
20+
Assertions.assertTrue(remediation.getAppliedRemediation() != "");
21+
Assertions.assertTrue(remediation.getAvailableRemediation() != "");
22+
}
23+
24+
@Test
25+
void testKicsRemediationSimilarityFilter() throws Exception {
26+
KicsRemediation remediation = wrapper.kicsRemediate(RESULTS_FILE,KICS_FILE,ENGINE,QUERY_ID);
27+
Assertions.assertTrue(remediation.getAppliedRemediation() != "");
28+
Assertions.assertTrue(remediation.getAvailableRemediation() != "");
29+
}
30+
31+
}

src/test/java/com/checkmarx/ast/ScanTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.checkmarx.ast;
22

3-
import com.checkmarx.ast.kicsRealtimeResults.kicsRealtimeResults;
3+
import com.checkmarx.ast.kicsRealtimeResults.KicsRealtimeResults;
44
import com.checkmarx.ast.scan.Scan;
55
import org.junit.jupiter.api.Assertions;
66
import org.junit.jupiter.api.Test;
@@ -34,7 +34,7 @@ void testScanCreate() throws Exception {
3434

3535
@Test
3636
void testKicsRealtimeScan() throws Exception {
37-
kicsRealtimeResults scan = wrapper.kicsRealtimeScan("target/test-classes/Dockerfile","","v");
37+
KicsRealtimeResults scan = wrapper.kicsRealtimeScan("target/test-classes/Dockerfile","","v");
3838
Assertions.assertTrue(scan.getResults().size() >= 1);
3939
}
4040

src/test/resources/positive1.tf

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
resource "aws_lb_listener" "listener5" {
2+
load_balancer_arn = aws_lb.test3.arn
3+
port = 80
4+
default_action {
5+
type = "redirect"
6+
7+
redirect {
8+
port = "80"
9+
protocol = "HTTP"
10+
status_code = "HTTP_301"
11+
}
12+
}
13+
}
14+
15+
resource "aws_lb" "test3" {
16+
name = "test123"
17+
load_balancer_type = "application"
18+
subnets = [aws_subnet.subnet1.id, aws_subnet.subnet2.id]
19+
internal = true
20+
}

src/test/resources/results.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"kics_version":"v1.5.12","total_counter":6,"queries":[{"query_name":"ALB Listening on HTTP","query_id":"de7f5e83-da88-4046-871f-ea18504b1d43","severity":"HIGH","platform":"Terraform","category":"Networking and Firewall","description":"AWS Application Load Balancer (alb) should not listen on HTTP","query_url":"https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener","files":[{"file_name":"../../path/positive1.tf","similarity_id":"b42a19486a8e18324a9b2c06147b1c49feb3ba39a0e4aeafec5665e60f98d047","line":9,"issue_type":"IncorrectValue","search_key":"aws_lb_listener[listener5].default_action.redirect.protocol","search_line":0,"search_value":"","expected_value":"'default_action.redirect.protocol' is equal to 'HTTPS'","actual_value":"'default_action.redirect.protocol' is equal 'HTTP'","remediation":"{\"after\":\"HTTPS\",\"before\":\"HTTP\"}","remediation_type":"replacement"}]},{"query_name":"ALB Not Dropping Invalid Headers","query_id":"6e3fd2ed-5c83-4c68-9679-7700d224d379","severity":"MEDIUM","platform":"Terraform","category":"Best Practices","description":"It's considered a best practice when using Application Load Balancers to drop invalid header fields","query_url":"https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb#drop_invalid_header_fields","files":[{"file_name":"../../path/positive1.tf","similarity_id":"9574288c118e8c87eea31b6f0b011295a39ec5e70d83fb70e839b8db4a99eba8","line":15,"issue_type":"MissingAttribute","search_key":"aws_lb[{{test3}}]","search_line":0,"search_value":"","expected_value":"aws_lb[{{test3}}].drop_invalid_header_fields is set to true","actual_value":"aws_lb[{{test3}}].drop_invalid_header_fields is missing","remediation":"drop_invalid_header_fields = true","remediation_type":"addition"}]},{"query_name":"ALB Deletion Protection Disabled","query_id":"afecd1f1-6378-4f7e-bb3b-60c35801fdd4","severity":"LOW","platform":"Terraform","category":"Insecure Configurations","description":"Application Load Balancer should have deletion protection enabled","query_url":"https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb#enable_deletion_protection","files":[{"file_name":"../../path/positive1.tf","similarity_id":"cc22618d82eee56de73a07a558bf689f2efe1ddc42393323d14f77b0c37c29a8","line":15,"issue_type":"MissingAttribute","search_key":"aws_lb[test3]","search_line":0,"search_value":"","expected_value":"'enable_deletion_protection' is defined and set to true","actual_value":"'enable_deletion_protection' is undefined or null","remediation":"enable_deletion_protection = true","remediation_type":"addition"}]},{"query_name":"IAM Access Analyzer Not Enabled","query_id":"e592a0c5-5bdb-414c-9066-5dba7cdea370","severity":"LOW","platform":"Terraform","category":"Best Practices","description":"IAM Access Analyzer should be enabled and configured to continuously monitor resource permissions","query_url":"https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/accessanalyzer_analyzer","files":[{"file_name":"../../path/positive1.tf","similarity_id":"23486f3c10caaa350ec4e2a26d49de0969a585e7df6ec7814fe44466c8e1ff9e","line":1,"issue_type":"MissingAttribute","search_key":"resource","search_line":0,"search_value":"","expected_value":"'aws_accessanalyzer_analyzer' is set","actual_value":"'aws_accessanalyzer_analyzer' is undefined","remediation":"","remediation_type":""}]},{"query_name":"Shield Advanced Not In Use","query_id":"084c6686-2a70-4710-91b1-000393e54c12","severity":"LOW","platform":"Terraform","category":"Networking and Firewall","description":"AWS Shield Advanced should be used for Amazon Route 53 hosted zone, AWS Global Accelerator accelerator, Elastic IP Address, Elastic Load Balancing, and Amazon CloudFront Distribution to protect these resources against robust DDoS attacks","query_url":"https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/shield_protection#resource_arn","files":[{"file_name":"../../path/positive1.tf","similarity_id":"069aa314d2934c4c50746ec0045e0802e3c6f8f803ea5528c60d92917cc4d318","line":15,"issue_type":"MissingAttribute","search_key":"aws_lb[test3]","search_line":0,"search_value":"","expected_value":"aws_lb has shield advanced associated","actual_value":"aws_lb does not have shield advanced associated","remediation":"","remediation_type":""}]},{"query_name":"Resource Not Using Tags","query_id":"e38a8e0a-b88b-4902-b3fe-b0fcb17d5c10","severity":"INFO","platform":"Terraform","category":"Best Practices","description":"AWS services resource tags are an essential part of managing components. As a best practice, the field 'tags' should have additional tags defined other than 'Name'","query_url":"https://registry.terraform.io/providers/hashicorp/aws/latest/docs/guides/resource-tagging","files":[{"file_name":"../../path/positive1.tf","similarity_id":"e9119956188af27eb6b095cf0fadbf0d784270d9238e4650390e3b3d9a9756f5","line":15,"issue_type":"MissingAttribute","search_key":"aws_lb[{{test3}}]","search_line":0,"search_value":"","expected_value":"aws_lb[{{test3}}].tags is defined and not null","actual_value":"aws_lb[{{test3}}].tags is undefined or null","remediation":"","remediation_type":""}]}],"severity_counters":{"HIGH":1,"INFO":1,"LOW":3,"MEDIUM":1}}

0 commit comments

Comments
 (0)